mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-23 06:16:47 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fc5f4f7d8 | ||
|
|
d16a0bdb3a | ||
|
|
6eaf0c231c | ||
|
|
cd8eb8776e | ||
|
|
3d0a2aba2c | ||
|
|
f600e774d5 | ||
|
|
d16dd26660 | ||
|
|
8c04d669f9 | ||
|
|
5d2dcfd7f7 | ||
|
|
0b3f1e4119 | ||
|
|
8bd9fc7128 | ||
|
|
1b551aaf94 | ||
|
|
a3dda80fb2 | ||
|
|
9e9d5ccfdd | ||
|
|
07daee9438 | ||
|
|
82808d8b5d | ||
|
|
c045f51a7f | ||
|
|
d72eadb885 | ||
|
|
e99f0a8f51 | ||
|
|
ed2cb380cd | ||
|
|
dc8e941260 | ||
|
|
d486b81f23 | ||
|
|
59c2f16a5f | ||
|
|
1470a061fd | ||
|
|
c1333a21ef | ||
|
|
04ef0b7d80 | ||
|
|
2fc9413d1f | ||
|
|
c94bdbcdb0 | ||
|
|
1820cd0244 | ||
|
|
aa3cbbdf99 | ||
|
|
0a9b6f34ae | ||
|
|
5c2c5453ac | ||
|
|
0c6bb476ea | ||
|
|
568924dcb5 | ||
|
|
33b3f7bdda | ||
|
|
3a04e0a051 | ||
|
|
66ae377801 | ||
|
|
898db57405 | ||
|
|
0fe45b5046 | ||
|
|
20cfe99457 | ||
|
|
4ec8b38a5c | ||
|
|
79add47002 | ||
|
|
c429f4c9a7 | ||
|
|
7f6a0b652a | ||
|
|
9f3f9154eb | ||
|
|
498fd06412 | ||
|
|
6d3b780791 | ||
|
|
a0ec981c50 | ||
|
|
930cd598a0 | ||
|
|
77adab0f33 | ||
|
|
0e3768f829 | ||
|
|
22884f2e64 | ||
|
|
62da6aca28 | ||
|
|
525ebddb0c | ||
|
|
521750c007 | ||
|
|
85d2833a62 | ||
|
|
e2cc258283 | ||
|
|
f09cf85c76 | ||
|
|
c32de1dba0 | ||
|
|
628b866c36 | ||
|
|
08dbe801c1 | ||
|
|
101810df21 | ||
|
|
3877b636df | ||
|
|
9d028a63f2 | ||
|
|
35e5cea9df | ||
|
|
ec510071f1 | ||
|
|
7413c533f6 | ||
|
|
dde69cebb6 | ||
|
|
f942657ad5 | ||
|
|
fad1620828 | ||
|
|
a9931e7a58 | ||
|
|
6cd4adb135 | ||
|
|
9643b86ab3 | ||
|
|
452eaeaea8 | ||
|
|
3a6e2df958 | ||
|
|
e73b7e2656 | ||
|
|
469ec11190 | ||
|
|
e0bbfa512c | ||
|
|
94c9af2a5d | ||
|
|
9f2e7df0ff | ||
|
|
f02b2c9d7a | ||
|
|
058dac4290 | ||
|
|
ce4e21a962 | ||
|
|
065d6bc1e3 | ||
|
|
312d09dc1d | ||
|
|
faf7f30283 | ||
|
|
5d41e98c1f | ||
|
|
5e8330a4ff | ||
|
|
ef8964c65a | ||
|
|
aa42ec381c | ||
|
|
c9d4aab9cb | ||
|
|
b8bc531f05 | ||
|
|
79cb8c883a | ||
|
|
27e633410c | ||
|
|
7527c466ed | ||
|
|
3ea1214160 | ||
|
|
782542922d | ||
|
|
1f8102c4dc | ||
|
|
c4b34e8720 | ||
|
|
e494be7cbf | ||
|
|
eb0a78e9ce | ||
|
|
e80138ec8c | ||
|
|
943316c6f6 | ||
|
|
52b8ed9077 | ||
|
|
fc227aa3e1 | ||
|
|
41993815e9 | ||
|
|
c5063f5d2f | ||
|
|
f28aa11936 | ||
|
|
3131fa68b7 | ||
|
|
def3809b3f | ||
|
|
3429c24a6a | ||
|
|
f47627d752 | ||
|
|
9468f3d06f | ||
|
|
b997de63a5 | ||
|
|
f50f06ab4e | ||
|
|
d5d03812cd | ||
|
|
b6d5a0675e | ||
|
|
e63e830d62 | ||
|
|
74ca34bd82 | ||
|
|
c9d480028e | ||
|
|
cc89ba66af | ||
|
|
05e6d51004 | ||
|
|
ae583204e3 | ||
|
|
018476f7cd | ||
|
|
bfabeab6b9 | ||
|
|
4a3f1a3641 | ||
|
|
d97560caa7 | ||
|
|
393102d43a | ||
|
|
8e97a0e4d4 | ||
|
|
4ea789a2d7 | ||
|
|
354f7ad920 | ||
|
|
f4a6206790 | ||
|
|
fd29ba3398 | ||
|
|
44fbf60885 | ||
|
|
a0d69113c3 | ||
|
|
86942ac592 | ||
|
|
075f9cbc4b | ||
|
|
9dab368880 | ||
|
|
5f6027fb66 | ||
|
|
53156793fe | ||
|
|
4644c220e8 | ||
|
|
c30cd9afea | ||
|
|
a8f45a18f0 | ||
|
|
6828e3e2ea | ||
|
|
75eb372adf | ||
|
|
3b753fe52b | ||
|
|
8c73fa7840 | ||
|
|
d310e656c7 | ||
|
|
0510367b70 | ||
|
|
3e11207a56 | ||
|
|
665f31271f | ||
|
|
9a2b56675c | ||
|
|
c9f38f5ffa | ||
|
|
5ea4152162 | ||
|
|
327c897d7e | ||
|
|
29ebe486b7 | ||
|
|
4af0acb3be | ||
|
|
8435774c26 | ||
|
|
6172748c65 | ||
|
|
ca0ae9040a | ||
|
|
d9cdbde3f6 | ||
|
|
307a97116f | ||
|
|
83d2c6dfd1 |
@@ -17,7 +17,6 @@ configure
|
||||
Makefile
|
||||
check
|
||||
check.cc
|
||||
check.vvp
|
||||
config.status
|
||||
config.log
|
||||
config.cache
|
||||
|
||||
@@ -104,7 +104,7 @@ module may not be needed as long as the ``-s <name>'' switch is
|
||||
given.
|
||||
|
||||
So when you send a test case, ask yourself "Can poor overworked Steve
|
||||
invoke the error without any Verilog other than what is included?" And
|
||||
invoke the error without any Verilog other then what is included?" And
|
||||
while we are at it, please place a copyright notice in your test
|
||||
program and include a GPL license statement if you can. Your test
|
||||
program may find its way into the test suite, and the notices will
|
||||
@@ -160,11 +160,8 @@ 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 $
|
||||
$Id: BUGS.txt,v 1.4 2003/02/19 04:36:31 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.
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* 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 $"
|
||||
#ident "$Id: HName.cc,v 1.5 2002/11/02 03:27:52 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -29,107 +29,235 @@
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
|
||||
|
||||
hname_t::hname_t()
|
||||
{
|
||||
number_ = INT_MIN;
|
||||
item_ = 0;
|
||||
count_ = 0;
|
||||
}
|
||||
|
||||
hname_t::hname_t(perm_string text)
|
||||
hname_t::hname_t(const char*text)
|
||||
{
|
||||
name_ = text;
|
||||
number_ = INT_MIN;
|
||||
}
|
||||
|
||||
hname_t::hname_t(perm_string text, int num)
|
||||
{
|
||||
name_ = text;
|
||||
number_ = num;
|
||||
item_ = strdup(text);
|
||||
count_ = 1;
|
||||
}
|
||||
|
||||
hname_t::hname_t(const hname_t&that)
|
||||
{
|
||||
name_ = that.name_;
|
||||
number_ = that.number_;
|
||||
}
|
||||
|
||||
hname_t& hname_t::operator = (const hname_t&that)
|
||||
{
|
||||
name_ = that.name_;
|
||||
number_ = that.number_;
|
||||
return *this;
|
||||
count_ = that.count_;
|
||||
switch (count_) {
|
||||
case 0:
|
||||
item_ = 0;
|
||||
break;
|
||||
case 1:
|
||||
item_ = strdup(that.item_);
|
||||
break;
|
||||
default:
|
||||
array_ = new char*[count_];
|
||||
for (unsigned idx = 0 ; idx < count_ ; idx += 1)
|
||||
array_[idx] = strdup(that.array_[idx]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
hname_t::~hname_t()
|
||||
{
|
||||
switch (count_) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
free(item_);
|
||||
break;
|
||||
default:
|
||||
for (unsigned idx = 0 ; idx < count_ ; idx += 1)
|
||||
free(array_[idx]);
|
||||
delete[]array_;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
perm_string hname_t::peek_name(void) const
|
||||
unsigned hname_t::component_count() const
|
||||
{
|
||||
return name_;
|
||||
return count_;
|
||||
}
|
||||
|
||||
bool hname_t::has_number() const
|
||||
void hname_t::append(const char*text)
|
||||
{
|
||||
return number_ != INT_MIN;
|
||||
char**tmp;
|
||||
|
||||
switch (count_) {
|
||||
case 0:
|
||||
count_ = 1;
|
||||
item_ = strdup(text);
|
||||
break;
|
||||
case 1:
|
||||
count_ = 2;
|
||||
tmp = new char*[2];
|
||||
tmp[0] = item_;
|
||||
tmp[1] = strdup(text);
|
||||
array_ = tmp;
|
||||
break;
|
||||
default:
|
||||
tmp = new char*[count_+1];
|
||||
for (unsigned idx = 0 ; idx < count_ ; idx += 1)
|
||||
tmp[idx] = array_[idx];
|
||||
delete[]array_;
|
||||
array_ = tmp;
|
||||
array_[count_] = strdup(text);
|
||||
count_ += 1;
|
||||
}
|
||||
}
|
||||
|
||||
int hname_t::peek_number() const
|
||||
void hname_t::prepend(const char*text)
|
||||
{
|
||||
return number_;
|
||||
char**tmp;
|
||||
|
||||
switch (count_) {
|
||||
case 0:
|
||||
count_ = 1;
|
||||
item_ = strdup(text);
|
||||
break;
|
||||
case 1:
|
||||
count_ = 2;
|
||||
tmp = new char*[2];
|
||||
tmp[0] = strdup(text);
|
||||
tmp[1] = item_;
|
||||
array_ = tmp;
|
||||
break;
|
||||
default:
|
||||
tmp = new char*[count_+1];
|
||||
tmp[0] = strdup(text);
|
||||
for (unsigned idx = 0 ; idx < count_ ; idx += 1)
|
||||
tmp[idx+1] = array_[idx];
|
||||
delete[]array_;
|
||||
array_ = tmp;
|
||||
count_ += 1;
|
||||
}
|
||||
}
|
||||
|
||||
char* hname_t::remove_tail_name()
|
||||
{
|
||||
if (count_ == 0)
|
||||
return 0;
|
||||
|
||||
if (count_ == 1) {
|
||||
char*tmp = item_;
|
||||
count_ = 0;
|
||||
item_ = 0;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
if (count_ == 2) {
|
||||
char*tmp1 = array_[0];
|
||||
char*tmp2 = array_[1];
|
||||
delete[]array_;
|
||||
count_ = 1;
|
||||
item_ = tmp1;
|
||||
return tmp2;
|
||||
}
|
||||
|
||||
char*tmpo = array_[count_-1];
|
||||
char**tmpa = new char*[count_-1];
|
||||
for (unsigned idx = 0 ; idx < count_-1 ; idx += 1)
|
||||
tmpa[idx] = array_[idx];
|
||||
|
||||
delete[]array_;
|
||||
array_ = tmpa;
|
||||
count_ -= 1;
|
||||
return tmpo;
|
||||
}
|
||||
|
||||
const char* hname_t::peek_name(unsigned idx) const
|
||||
{
|
||||
if (idx >= count_)
|
||||
return 0;
|
||||
|
||||
if (count_ == 1)
|
||||
return item_;
|
||||
|
||||
return array_[idx];
|
||||
}
|
||||
|
||||
const char* hname_t::peek_tail_name() const
|
||||
{
|
||||
switch (count_) {
|
||||
case 0:
|
||||
return 0;
|
||||
case 1:
|
||||
return item_;
|
||||
default:
|
||||
return array_[count_-1];
|
||||
}
|
||||
}
|
||||
|
||||
bool operator < (const hname_t&l, const hname_t&r)
|
||||
{
|
||||
int cmp = strcmp(l.peek_name(), r.peek_name());
|
||||
if (cmp < 0) return true;
|
||||
if (cmp > 0) return false;
|
||||
if (l.has_number() && r.has_number())
|
||||
return l.peek_number() < r.peek_number();
|
||||
else
|
||||
unsigned idx = 0;
|
||||
const char*lc = l.peek_name(idx);
|
||||
const char*rc = r.peek_name(idx);
|
||||
|
||||
while (lc && rc) {
|
||||
int cmp = strcmp(lc, rc);
|
||||
if (cmp < 0)
|
||||
return true;
|
||||
if (cmp > 0)
|
||||
return false;
|
||||
idx += 1;
|
||||
lc = l.peek_name(idx);
|
||||
rc = r.peek_name(idx);
|
||||
}
|
||||
|
||||
if (lc && !rc)
|
||||
return false;
|
||||
if (rc && !lc)
|
||||
return true;
|
||||
|
||||
// Must be ==
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator == (const hname_t&l, const hname_t&r)
|
||||
{
|
||||
if (l.peek_name() == r.peek_name()) {
|
||||
if (l.has_number() && r.has_number())
|
||||
return l.peek_number() == r.peek_number();
|
||||
else
|
||||
return true;
|
||||
unsigned idx = 0;
|
||||
const char*lc = l.peek_name(idx);
|
||||
const char*rc = r.peek_name(idx);
|
||||
|
||||
while (lc && rc) {
|
||||
int cmp = strcmp(lc, rc);
|
||||
if (cmp != 0)
|
||||
return false;
|
||||
idx += 1;
|
||||
lc = l.peek_name(idx);
|
||||
rc = r.peek_name(idx);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
if (lc || rc)
|
||||
return false;
|
||||
|
||||
bool operator != (const hname_t&l, const hname_t&r)
|
||||
{ return ! (l==r); }
|
||||
// Must be ==
|
||||
return true;
|
||||
}
|
||||
|
||||
ostream& operator<< (ostream&out, const hname_t&that)
|
||||
{
|
||||
if (that.peek_name() == 0) {
|
||||
switch (that.count_) {
|
||||
case 0:
|
||||
out << "";
|
||||
return out;
|
||||
case 1:
|
||||
out << that.item_;
|
||||
return out;
|
||||
|
||||
default:
|
||||
out << that.array_[0];
|
||||
for (unsigned idx = 1 ; idx < that.count_ ; idx += 1)
|
||||
out << "." << that.array_[idx];
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
out << that.peek_name();
|
||||
if (that.has_number())
|
||||
out << "[" << that.peek_number() << "]";
|
||||
|
||||
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.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __HName_H
|
||||
#define __HName_H
|
||||
/*
|
||||
* Copyright (c) 2001-2007 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -19,11 +19,10 @@
|
||||
* 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 $"
|
||||
#ident "$Id: HName.h,v 1.4 2002/11/02 03:27:51 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <iostream>
|
||||
# include "StringHeap.h"
|
||||
#ifdef __GNUC__
|
||||
#if __GNUC__ > 2
|
||||
using namespace std;
|
||||
@@ -31,56 +30,59 @@ using namespace std;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This class represents a component of a Verilog hierarchical name. A
|
||||
* hierarchical component contains a name string (prepresented here
|
||||
* with a perm_string) and an optional signed number. This signed
|
||||
* number is used if the scope is part of an array, for example an
|
||||
* array of module instances or a loop generated scope.
|
||||
* This class represents a Verilog hierarchical name. A hierarchical
|
||||
* name is an ordered list of simple names.
|
||||
*/
|
||||
|
||||
class hname_t {
|
||||
|
||||
public:
|
||||
hname_t ();
|
||||
explicit hname_t (perm_string text);
|
||||
explicit hname_t (perm_string text, int num);
|
||||
explicit hname_t (const char*text);
|
||||
hname_t (const hname_t&that);
|
||||
~hname_t();
|
||||
|
||||
hname_t& operator= (const hname_t&);
|
||||
// This method adds a name to the end of the hierarchical
|
||||
// path. This becomes a new base name.
|
||||
void append(const char*text);
|
||||
|
||||
// Return the string part of the hname_t.
|
||||
perm_string peek_name(void) const;
|
||||
// This method adds a name to the *front* of the hierarchical
|
||||
// path. The base name remains the same, unless this is the
|
||||
// only component.
|
||||
void prepend(const char*text);
|
||||
|
||||
bool has_number() const;
|
||||
int peek_number() const;
|
||||
// This method removes the tail name from the hierarchy, and
|
||||
// returns a pointer to that tail name. That tail name now
|
||||
// must be removed by the caller.
|
||||
char* remove_tail_name();
|
||||
|
||||
// Return the given component in the hierarchical name. If the
|
||||
// idx is too large, return 0.
|
||||
const char*peek_name(unsigned idx) const;
|
||||
const char*peek_tail_name() const;
|
||||
|
||||
// Return the number of components in the hierarchical
|
||||
// name. If this is a simple name, this will return 1.
|
||||
unsigned component_count() const;
|
||||
|
||||
friend ostream& operator<< (ostream&, const hname_t&);
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
// 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_;
|
||||
union {
|
||||
char**array_;
|
||||
char* item_;
|
||||
};
|
||||
unsigned count_;
|
||||
|
||||
private: // not implemented
|
||||
hname_t& operator= (const hname_t&);
|
||||
};
|
||||
|
||||
extern bool operator < (const hname_t&, const hname_t&);
|
||||
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&);
|
||||
|
||||
/*
|
||||
* $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.
|
||||
|
||||
+7
-4
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: LineInfo.cc,v 1.4 2003/01/17 05:49:03 steve Exp $"
|
||||
#ident "$Id: LineInfo.cc,v 1.4.2.1 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -34,12 +34,12 @@ LineInfo::~LineInfo()
|
||||
{
|
||||
}
|
||||
|
||||
string LineInfo::get_line() const
|
||||
std::string LineInfo::get_line() const
|
||||
{
|
||||
ostringstream buf;
|
||||
std::ostringstream buf;
|
||||
buf << (file_? file_ : "") << ":" << lineno_;
|
||||
|
||||
string res = buf.str();
|
||||
std::string res = buf.str();
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -61,6 +61,9 @@ void LineInfo::set_lineno(unsigned n)
|
||||
|
||||
/*
|
||||
* $Log: LineInfo.cc,v $
|
||||
* Revision 1.4.2.1 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.4 2003/01/17 05:49:03 steve
|
||||
* Use stringstream in place of sprintf.
|
||||
*
|
||||
|
||||
+7
-4
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: LineInfo.h,v 1.8 2005/06/14 19:13:43 steve Exp $"
|
||||
#ident "$Id: LineInfo.h,v 1.7.2.2 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -40,7 +40,7 @@ class LineInfo {
|
||||
LineInfo();
|
||||
~LineInfo();
|
||||
|
||||
string get_line() const;
|
||||
std::string get_line() const;
|
||||
|
||||
void set_line(const LineInfo&that);
|
||||
|
||||
@@ -54,8 +54,11 @@ class LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: LineInfo.h,v $
|
||||
* Revision 1.8 2005/06/14 19:13:43 steve
|
||||
* gcc3/4 compile errors.
|
||||
* Revision 1.7.2.2 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.7.2.1 2005/06/14 15:33:54 steve
|
||||
* Fix gcc4 build issues.
|
||||
*
|
||||
* Revision 1.7 2003/01/17 05:49:03 steve
|
||||
* Use stringstream in place of sprintf.
|
||||
|
||||
+50
-30
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.181 2007/05/24 04:07:11 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.169.2.7 2007/05/30 17:48:53 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -25,7 +25,7 @@ SHELL = /bin/sh
|
||||
# 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
|
||||
VERSION = 0.8.5
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
@@ -43,6 +43,7 @@ mandir = @mandir@
|
||||
libdir64 = @libdir64@
|
||||
|
||||
dllib=@DLLIB@
|
||||
strip_dynamic=@strip_dynamic@
|
||||
|
||||
CC = @CC@
|
||||
CXX = @CXX@
|
||||
@@ -50,23 +51,32 @@ INSTALL = @INSTALL@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
STRIP = @STRIP@
|
||||
LEX = @LEX@
|
||||
YACC = @YACC@
|
||||
MAN = @MAN@
|
||||
PS2PDF = @PS2PDF@
|
||||
|
||||
CPPFLAGS = @ident_support@ @DEFS@ -I. -I$(srcdir) @CPPFLAGS@
|
||||
CXXFLAGS = -Wall @CXXFLAGS@
|
||||
PICFLAGS = @PICFLAG@
|
||||
LDFLAGS = @rdynamic@ @LDFLAGS@
|
||||
|
||||
# The TARGETS variable lists the target modules that can be build and
|
||||
# installed. Some of them depend on external things, so are only
|
||||
# compiled if the prerequisites are installed.
|
||||
TARGETS = tgt-null
|
||||
|
||||
all: dep ivl@EXEEXT@
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for dir in ivlpp ; \
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
|
||||
for dir in ivlpp tgt-verilog tgt-stub; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
cd driver ; $(MAKE) VERSION=$(VERSION) $@
|
||||
|
||||
# In the windows world, the installer will need a dosify program to
|
||||
# dosify text files.
|
||||
ifeq (@MING32@,yes)
|
||||
ifeq (@WIN32@,yes)
|
||||
all: dep dosify.exe
|
||||
dosify.exe: dosify.c
|
||||
$(CC) -o dosify.exe dosify.c
|
||||
@@ -82,37 +92,37 @@ check: all
|
||||
|
||||
clean:
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp tgt-verilog tgt-pal driver driver-vpi; \
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp tgt-verilog tgt-stub driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
rm -f *.o parse.cc parse.cc.output parse.h lexor.cc
|
||||
rm -f ivl.exp iverilog-vpi.pdf iverilog-vpi.ps parse.output
|
||||
rm -f syn-rules.output dosify.exe ivl@EXEEXT@ check.vvp
|
||||
rm -f lexor_keyword.cc libivl.a libvpi.a iverilog-vpi syn-rules.cc*
|
||||
rm -rf dep
|
||||
rm -rf dep ivl@EXEEXT@
|
||||
|
||||
distclean: clean
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp tgt-verilog tgt-pal driver driver-vpi; \
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp tgt-verilog tgt-stub driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
rm -f Makefile config.status config.log config.cache config.h
|
||||
rm -f _pli_types.h
|
||||
rm -rf autom4te.cache
|
||||
|
||||
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
|
||||
TT = t-dll.o t-dll-api.o t-dll-expr.o t-dll-proc.o t-xnf.o
|
||||
FF = cprop.o nodangle.o synth.o synth2.o syn-rules.o xnfio.o
|
||||
|
||||
O = main.o async.o design_dump.o dup_expr.o elaborate.o elab_expr.o \
|
||||
elab_lval.o elab_net.o elab_pexpr.o elab_scope.o \
|
||||
elab_lval.o elab_net.o elab_anet.o elab_pexpr.o elab_scope.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_assign.o \
|
||||
load_module.o netlist.o NetLatch.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_udp.o pad_to_width.o \
|
||||
parse.o parse_misc.o pform.o pform_dump.o pform_types.o \
|
||||
net_proc.o net_scope.o net_udp.o net_variable.o pad_to_width.o \
|
||||
parse.o parse_misc.o pform.o pform_dump.o \
|
||||
set_width.o symbol_search.o sync.o sys_funcs.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 PSpec.o \
|
||||
Attrib.o HName.o LineInfo.o Module.o PData.o PDelays.o PEvent.o \
|
||||
PExpr.o PGate.o \
|
||||
PTask.o PUdp.o PFunction.o PWire.o Statement.o StringHeap.o \
|
||||
$(FF) $(TT)
|
||||
|
||||
@@ -129,10 +139,11 @@ ivl@EXEEXT@: $O ivl.def
|
||||
$(CXX) -o ivl@EXEEXT@ $O $(dllib) @EXTRALIBS@
|
||||
dlltool --dllname ivl@EXEEXT@ --def ivl.def \
|
||||
--output-lib libivl.a --output-exp ivl.exp
|
||||
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@
|
||||
$(CXX) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@
|
||||
else
|
||||
ivl@EXEEXT@: $O
|
||||
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ $O $(dllib)
|
||||
|
||||
endif
|
||||
|
||||
ifeq (@MINGW32@,yes)
|
||||
@@ -142,9 +153,6 @@ all: dep iverilog-vpi
|
||||
|
||||
iverilog-vpi: iverilog-vpi.sh
|
||||
sed -e 's;@SHARED@;@shared@;' -e 's;@PIC@;@PICFLAG@;' \
|
||||
-e 's;@IVCC@;$(CC);' \
|
||||
-e 's;@IVCXX@;$(CXX);' \
|
||||
-e 's;@IVCFLAGS@;$(CXXFLAGS);' \
|
||||
-e 's;@INCLUDEDIR@;@includedir@;' \
|
||||
-e 's;@LIBDIR64@;@libdir64@;' \
|
||||
-e 's;@VPIDIR1@;@vpidir1@;' -e 's;@VPIDIR2@;@vpidir2@;' \
|
||||
@@ -156,7 +164,7 @@ dep:
|
||||
mkdir dep
|
||||
|
||||
%.o: %.cc
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o
|
||||
$(CXX) $(CPPFLAGS) $(CXXFLAGS) -MD -c $< -o $*.o $(DEBUGFLAGS)
|
||||
mv $*.d dep/$*.d
|
||||
|
||||
|
||||
@@ -180,15 +188,25 @@ lexor_keyword.cc: lexor_keyword.gperf
|
||||
gperf -o -i 7 -C -k 1-3,$$ -L ANSI-C -H keyword_hash -N check_identifier -t $(srcdir)/lexor_keyword.gperf > lexor_keyword.cc || (rm -f lexor_keyword.cc ; false)
|
||||
|
||||
iverilog-vpi.ps: $(srcdir)/iverilog-vpi.man
|
||||
man -t $(srcdir)/iverilog-vpi.man > iverilog-vpi.ps
|
||||
$(MAN) -t $(srcdir)/iverilog-vpi.man > iverilog-vpi.ps
|
||||
|
||||
iverilog-vpi.pdf: iverilog-vpi.ps
|
||||
ps2pdf iverilog-vpi.ps iverilog-vpi.pdf
|
||||
$(PS2PDF) iverilog-vpi.ps iverilog-vpi.pdf
|
||||
|
||||
ifeq (@MING32@,yes)
|
||||
# Build and install the iverilog-vpi.pdf only if there is a man
|
||||
# program *and* a ps2pdf program.
|
||||
ifeq (@WIN32@,yes)
|
||||
ifeq ($(MAN),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
|
||||
else
|
||||
ifeq ($(PS2PDF),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
|
||||
else
|
||||
INSTALL_DOC = $(prefix)/iverilog-vpi.pdf $(mandir)/man1/iverilog-vpi.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
all: dep iverilog-vpi.pdf
|
||||
endif
|
||||
endif
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
else
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog-vpi.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
@@ -202,8 +220,9 @@ endif
|
||||
|
||||
XNF_INSTALL = $(libdir)/ivl/xnf.conf $(libdir)/ivl/xnf-s.conf
|
||||
|
||||
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(includedir)/ivl_target.h $(includedir)/_pli_types.h $(includedir)/vpi_user.h $(includedir)/acc_user.h $(includedir)/veriuser.h $(WIN32_INSTALL) $(INSTALL_DOC)
|
||||
install: all installdirs $(libdir)/ivl/ivl@EXEEXT@ $(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)
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
|
||||
@@ -266,16 +285,17 @@ installdirs: mkinstalldirs
|
||||
|
||||
uninstall:
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for tgt in $(TARGETS); do (cd $$tgt ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
for f in xnf.conf xnf-s.conf ivl@EXEEXT@; \
|
||||
for f in xnf.conf xnf-s.conf ivl; \
|
||||
do rm -f $(libdir)/ivl/$$f; done
|
||||
-rmdir $(libdir)/ivl
|
||||
for f in verilog iverilog-vpi gverilog@EXEEXT@; \
|
||||
do rm -f $(bindir)/$$f; done
|
||||
for f in ivl_target.h vpi_user.h _pli_types.h acc_user.h veriuser.h; \
|
||||
do rm -f $(includedir)/$$f; done
|
||||
rm -f $(mandir)/man1/iverilog-vpi.1 $(prefix)/iverilog-vpi.pdf
|
||||
rm -f $(mandir)/man1/iverilog-vpi.1
|
||||
|
||||
|
||||
-include $(patsubst %.o, dep/%.d, $O)
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Module.cc,v 1.27 2007/05/24 04:07:11 steve Exp $"
|
||||
#ident "$Id: Module.cc,v 1.25 2004/10/04 01:10:51 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -31,7 +31,6 @@
|
||||
Module::Module(perm_string n)
|
||||
: name_(n)
|
||||
{
|
||||
library_flag = false;
|
||||
default_nettype = NetNet::NONE;
|
||||
}
|
||||
|
||||
@@ -111,9 +110,9 @@ unsigned Module::find_port(const char*name) const
|
||||
}
|
||||
|
||||
|
||||
PWire* Module::get_wire(const pform_name_t&name) const
|
||||
PWire* Module::get_wire(const hname_t&name) const
|
||||
{
|
||||
map<pform_name_t,PWire*>::const_iterator obj = wires_.find(name);
|
||||
map<hname_t,PWire*>::const_iterator obj = wires_.find(name);
|
||||
if (obj == wires_.end())
|
||||
return 0;
|
||||
else
|
||||
@@ -133,6 +132,11 @@ PGate* Module::get_gate(perm_string name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
const map<hname_t,PWire*>& Module::get_wires() const
|
||||
{
|
||||
return wires_;
|
||||
}
|
||||
|
||||
const list<PGate*>& Module::get_gates() const
|
||||
{
|
||||
return gates_;
|
||||
@@ -146,13 +150,6 @@ const list<PProcess*>& Module::get_behaviors() const
|
||||
|
||||
/*
|
||||
* $Log: Module.cc,v $
|
||||
* Revision 1.27 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.26 2007/04/19 02:52:53 steve
|
||||
* Add support for -v flag in command file.
|
||||
*
|
||||
* Revision 1.25 2004/10/04 01:10:51 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Module.h,v 1.43 2007/05/24 04:07:11 steve Exp $"
|
||||
#ident "$Id: Module.h,v 1.37 2004/06/13 04:56:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
@@ -30,13 +30,11 @@
|
||||
# include "named.h"
|
||||
# include "LineInfo.h"
|
||||
# include "netlist.h"
|
||||
# include "pform_types.h"
|
||||
class PData;
|
||||
class PEvent;
|
||||
class PExpr;
|
||||
class PEIdent;
|
||||
class PGate;
|
||||
class PGenerate;
|
||||
class PSpecPath;
|
||||
class PTask;
|
||||
class PFunction;
|
||||
class PWire;
|
||||
@@ -69,12 +67,6 @@ class Module : public LineInfo {
|
||||
explicit Module(perm_string name);
|
||||
~Module();
|
||||
|
||||
/* Initially false. This is set to true if the module has been
|
||||
declared as a library module. This makes the module
|
||||
ineligible for being chosen as an implicit root. It has no
|
||||
other effect. */
|
||||
bool library_flag;
|
||||
|
||||
NetNet::Type default_nettype;
|
||||
|
||||
/* The module has parameters that are evaluated when the
|
||||
@@ -99,7 +91,7 @@ class Module : public LineInfo {
|
||||
new parameters within the module, but may be used to set
|
||||
values within this module (when instantiated) or in other
|
||||
instantiated modules. */
|
||||
map<pform_name_t,PExpr*>defparms;
|
||||
map<hname_t,PExpr*>defparms;
|
||||
|
||||
/* Parameters may be overridden at instantiation time;
|
||||
the overrides do not contain explicit parameter names,
|
||||
@@ -116,22 +108,15 @@ class Module : public LineInfo {
|
||||
/* Keep a table of named events declared in the module. */
|
||||
map<perm_string,PEvent*>events;
|
||||
|
||||
/* Keep a table of datum variables declared in the module. */
|
||||
map<hname_t,PData*>datum;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
/* These are the timescale for this module. The default is
|
||||
set by the `timescale directive. */
|
||||
int time_unit, time_precision;
|
||||
|
||||
/* The module has a list of genvars that may be used in
|
||||
various generate schemes. */
|
||||
list<perm_string> genvars;
|
||||
|
||||
/* the module has a list of generate schemes that appear in
|
||||
the module definition. These are used at elaboration time. */
|
||||
list<PGenerate*> generate_schemes;
|
||||
|
||||
list<PSpecPath*> specify_paths;
|
||||
|
||||
perm_string mod_name() const { return name_; }
|
||||
|
||||
void add_gate(PGate*gate);
|
||||
@@ -151,24 +136,24 @@ class Module : public LineInfo {
|
||||
|
||||
// Find a wire by name. This is used for connecting gates to
|
||||
// existing wires, etc.
|
||||
PWire* get_wire(const pform_name_t&name) const;
|
||||
PWire* get_wire(const hname_t&name) const;
|
||||
PGate* get_gate(perm_string name);
|
||||
|
||||
const map<hname_t,PWire*>& get_wires() const;
|
||||
const list<PGate*>& get_gates() const;
|
||||
const list<PProcess*>& get_behaviors() const;
|
||||
|
||||
void dump(ostream&out) const;
|
||||
bool elaborate(Design*, NetScope*scope) const;
|
||||
|
||||
typedef map<perm_string,NetExpr*> replace_t;
|
||||
bool elaborate_scope(Design*, NetScope*scope, const replace_t&rep) const;
|
||||
bool elaborate_scope(Design*, NetScope*scope) const;
|
||||
|
||||
bool elaborate_sig(Design*, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
|
||||
map<pform_name_t,PWire*> wires_;
|
||||
map<hname_t,PWire*> wires_;
|
||||
list<PGate*> gates_;
|
||||
list<PProcess*> behaviors_;
|
||||
map<perm_string,PTask*> tasks_;
|
||||
@@ -182,23 +167,45 @@ class Module : public LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: Module.h,v $
|
||||
* Revision 1.43 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.37 2004/06/13 04:56:53 steve
|
||||
* Add support for the default_nettype directive.
|
||||
*
|
||||
* Revision 1.42 2007/04/19 02:52:53 steve
|
||||
* Add support for -v flag in command file.
|
||||
* Revision 1.36 2004/05/25 19:21:06 steve
|
||||
* More identifier lists use perm_strings.
|
||||
*
|
||||
* Revision 1.41 2006/09/23 04:57:19 steve
|
||||
* Basic support for specify timing.
|
||||
* Revision 1.35 2004/02/20 18:53:33 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
* Revision 1.40 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
* Revision 1.34 2004/02/20 06:22:56 steve
|
||||
* parameter keys are per_strings.
|
||||
*
|
||||
* Revision 1.39 2006/03/30 01:49:07 steve
|
||||
* Fix instance arrays indexed by overridden parameters.
|
||||
* Revision 1.33 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.38 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
* Revision 1.32 2003/06/20 00:53:19 steve
|
||||
* Module attributes from the parser
|
||||
* through to elaborated form.
|
||||
*
|
||||
* Revision 1.31 2003/06/13 19:10:45 steve
|
||||
* Properly manage real variables in subscopes.
|
||||
*
|
||||
* Revision 1.30 2003/03/06 04:37:12 steve
|
||||
* lex_strings.add module names earlier.
|
||||
*
|
||||
* Revision 1.29 2003/02/27 06:45:11 steve
|
||||
* specparams as far as pform.
|
||||
*
|
||||
* Revision 1.28 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.27 2002/08/19 02:39:16 steve
|
||||
* Support parameters with defined ranges.
|
||||
*
|
||||
* Revision 1.26 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.25 2002/05/19 23:37:28 steve
|
||||
* Parse port_declaration_lists from the 2001 Standard.
|
||||
*/
|
||||
#endif
|
||||
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
// NetLatch.cc
|
||||
// Author: Alan M. Feldstein
|
||||
// Class NetLatch member-function definitions
|
||||
|
||||
#include "NetLatch.h" // NetLatch class definition
|
||||
#include "target.h" // target_t structure definition
|
||||
|
||||
// constructor
|
||||
NetLatch::NetLatch( NetScope *scope, perm_string name, unsigned width )
|
||||
// explicitly call base-class constructor
|
||||
: NetNode( scope, name, 2U * width + 1U )
|
||||
{
|
||||
} // end NetLatch constructor
|
||||
|
||||
unsigned NetLatch::width() const
|
||||
{
|
||||
return ( pin_count() - 1U ) / 2U;
|
||||
} // end function width
|
||||
|
||||
Link &NetLatch::pin_Data( unsigned w )
|
||||
{
|
||||
unsigned pn = 1 + 2 * w;
|
||||
assert( pn < pin_count() );
|
||||
return pin( pn );
|
||||
} // end function pin_Data
|
||||
|
||||
Link &NetLatch::pin_Q( unsigned w )
|
||||
{
|
||||
unsigned pn = 2 + 2 * w;
|
||||
assert( pn < pin_count() );
|
||||
return pin( pn );
|
||||
} // end function pin_Q
|
||||
|
||||
Link &NetLatch::pin_Gate()
|
||||
{
|
||||
return pin( 0 );
|
||||
} // end function pin_Q
|
||||
|
||||
bool NetLatch::emit_node( target_t *driverPtr ) const
|
||||
{
|
||||
driverPtr->lpm_latch( this );
|
||||
return true;
|
||||
} // end function emit_node
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
// NetLatch.h
|
||||
// Author: Alan M. Feldstein
|
||||
// This class represents an LPM_LATCH device. In Verilog, storage components of this type can be inferred.
|
||||
// The pinout is assigned like so:
|
||||
// 0 -- Gate
|
||||
//
|
||||
// 1 -- Data[0]
|
||||
// 2 -- Q[0]
|
||||
// ...
|
||||
#ifndef NETLATCH_H
|
||||
#define NETLATCH_H
|
||||
|
||||
#include "netlist.h" // NetNode, NetScope, Link class definitions
|
||||
#include "StringHeap.h" // perm_string class definition
|
||||
|
||||
class NetLatch : public NetNode
|
||||
{
|
||||
public:
|
||||
NetLatch( NetScope *, perm_string, unsigned );
|
||||
|
||||
unsigned width() const;
|
||||
|
||||
Link &pin_Data( unsigned );
|
||||
Link &pin_Q( unsigned );
|
||||
Link &pin_Gate();
|
||||
|
||||
const Link &pin_Data( unsigned ) const;
|
||||
const Link &pin_Q( unsigned ) const;
|
||||
const Link &pin_Gate() const;
|
||||
|
||||
virtual bool emit_node( target_t * ) const;
|
||||
}; // end class NetLatch
|
||||
|
||||
#endif
|
||||
+24
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2006 Stephen Williams <steve@icarus.com>
|
||||
* Copyright (c) 2003 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,18 +17,34 @@
|
||||
* 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 $"
|
||||
#ident "$Id: PData.cc,v 1.2 2003/11/10 20:11:01 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PSpec.h"
|
||||
# include "config.h"
|
||||
# include "PData.h"
|
||||
|
||||
PSpecPath::PSpecPath(unsigned src_cnt, unsigned dst_cnt)
|
||||
: conditional(false), condition(0), edge(0),
|
||||
src(src_cnt), dst(dst_cnt),
|
||||
data_source_expression(0)
|
||||
PData::PData(const hname_t&h)
|
||||
: hname_(h)
|
||||
{
|
||||
}
|
||||
|
||||
PSpecPath::~PSpecPath()
|
||||
PData::~PData()
|
||||
{
|
||||
}
|
||||
|
||||
const hname_t&PData::name() const
|
||||
{
|
||||
return hname_;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PData.cc,v $
|
||||
* Revision 1.2 2003/11/10 20:11:01 steve
|
||||
* missing include of config.h
|
||||
*
|
||||
* Revision 1.1 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
#ifndef __PData_H
|
||||
#define __PData_H
|
||||
/*
|
||||
* Copyright (c) 2003 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PData.h,v 1.1 2003/01/26 21:15:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "HName.h"
|
||||
# include "netlist.h"
|
||||
# include "LineInfo.h"
|
||||
|
||||
/*
|
||||
* The PData object represents declaration of atomic datum such as
|
||||
* real and realtime variables. These are variables that cannot be bit
|
||||
* or part selected, but can be used in expressions.
|
||||
*/
|
||||
|
||||
class PData : public LineInfo {
|
||||
|
||||
public:
|
||||
PData(const hname_t&hname);
|
||||
~PData();
|
||||
|
||||
// Return a hierarchical name.
|
||||
const hname_t&name() const;
|
||||
|
||||
void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
|
||||
map<string,PExpr*> attributes;
|
||||
|
||||
private:
|
||||
hname_t hname_;
|
||||
|
||||
private:
|
||||
PData(const PData&);
|
||||
PData& operator= (const PData&);
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PData.h,v $
|
||||
* Revision 1.1 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
+31
-52
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PDelays.cc,v 1.15 2006/07/08 21:48:46 steve Exp $"
|
||||
#ident "$Id: PDelays.cc,v 1.11.2.1 2006/10/04 00:37:03 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -62,15 +62,30 @@ void PDelays::set_delays(const svector<PExpr*>*del, bool df)
|
||||
delete_flag_ = df;
|
||||
}
|
||||
|
||||
static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
|
||||
static unsigned long calculate_val(Design*des, NetScope*scope,
|
||||
const PExpr*expr)
|
||||
{
|
||||
|
||||
NetExpr*dex = expr->elaborate_expr(des, scope, -1, false);
|
||||
NetExpr*dex = expr->elaborate_expr(des, scope);
|
||||
if (NetExpr*tmp = dex->eval_tree()) {
|
||||
delete dex;
|
||||
dex = tmp;
|
||||
}
|
||||
|
||||
int shift = scope->time_unit() - des->get_precision();
|
||||
if (sizeof(unsigned) <= 4 && shift > 9) {
|
||||
cerr << expr->get_line() << ": error: Precision overflow"
|
||||
<< " in scope " << scope->name() << "." << endl;
|
||||
cerr << expr->get_line() << ": :"
|
||||
<< " Units are 10e" << scope->time_unit()
|
||||
<< " minus precision 10e" << des->get_precision()
|
||||
<< " is 10e" << shift << "." << endl;
|
||||
cerr << expr->get_line() << ": : Perhaps a timescale "
|
||||
<< "is missing or incorrect?" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If the delay expression is a real constant or vector
|
||||
constant, then evaluate it, scale it to the local time
|
||||
units, and return an adjusted value. */
|
||||
@@ -78,15 +93,12 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
|
||||
if (NetECReal*tmp = dynamic_cast<NetECReal*>(dex)) {
|
||||
verireal fn = tmp->value();
|
||||
|
||||
int shift = scope->time_unit() - des->get_precision();
|
||||
long delay = fn.as_long(shift);
|
||||
if (delay < 0)
|
||||
delay = 0;
|
||||
|
||||
delete tmp;
|
||||
NetEConst*tmp2 = new NetEConst(verinum(delay));
|
||||
tmp2->set_line(*expr);
|
||||
return tmp2;
|
||||
return delay;
|
||||
}
|
||||
|
||||
|
||||
@@ -97,57 +109,35 @@ static NetExpr*calculate_val(Design*des, NetScope*scope, const PExpr*expr)
|
||||
des->scale_to_precision(fn.as_ulong(), scope);
|
||||
|
||||
delete tmp;
|
||||
NetEConst*tmp2 = new NetEConst(verinum(delay));
|
||||
tmp2->set_line(*expr);
|
||||
return tmp2;
|
||||
return delay;
|
||||
}
|
||||
|
||||
/* Oops, cannot evaluate down to a constant. */
|
||||
return dex;
|
||||
}
|
||||
/* Oops, cannot evaluate down to a constant. Error message. */
|
||||
delete dex;
|
||||
|
||||
static NetExpr* make_delay_nets(Design*des, NetExpr*expr)
|
||||
{
|
||||
if (dynamic_cast<NetESignal*> (expr))
|
||||
return expr;
|
||||
cerr << expr->get_line() << ": sorry: non-constant "
|
||||
<< "delays not supported here: " << *expr << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
|
||||
if (dynamic_cast<NetEConst*> (expr))
|
||||
return expr;
|
||||
|
||||
NetNet*sig = expr->synthesize(des);
|
||||
if (sig == 0) {
|
||||
cerr << expr->get_line() << ": error: Expression " << *expr
|
||||
<< " is not suitable for delay expression." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
expr = new NetESignal(sig);
|
||||
return expr;
|
||||
}
|
||||
|
||||
void PDelays::eval_delays(Design*des, NetScope*scope,
|
||||
NetExpr*&rise_time,
|
||||
NetExpr*&fall_time,
|
||||
NetExpr*&decay_time,
|
||||
bool as_nets_flag) const
|
||||
unsigned long&rise_time,
|
||||
unsigned long&fall_time,
|
||||
unsigned long&decay_time) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
|
||||
if (delay_[0]) {
|
||||
rise_time = calculate_val(des, scope, delay_[0]);
|
||||
if (as_nets_flag)
|
||||
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, fall_time);
|
||||
|
||||
if (delay_[2]) {
|
||||
decay_time = calculate_val(des, scope, delay_[2]);
|
||||
if (as_nets_flag)
|
||||
decay_time = make_delay_nets(des, decay_time);
|
||||
|
||||
} else {
|
||||
if (rise_time < fall_time)
|
||||
@@ -169,19 +159,8 @@ void PDelays::eval_delays(Design*des, NetScope*scope,
|
||||
|
||||
/*
|
||||
* $Log: PDelays.cc,v $
|
||||
* Revision 1.15 2006/07/08 21:48:46 steve
|
||||
* Handle real valued literals in net contexts.
|
||||
*
|
||||
* Revision 1.14 2006/06/02 04:48:49 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.13 2006/01/03 05:22:14 steve
|
||||
* Handle complex net node delays.
|
||||
*
|
||||
* Revision 1.12 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
* Revision 1.11.2.1 2006/10/04 00:37:03 steve
|
||||
* Detect delay precision overflow.
|
||||
*
|
||||
* Revision 1.11 2003/06/21 01:21:42 steve
|
||||
* Harmless fixup of warnings.
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* 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 $"
|
||||
#ident "$Id: PDelays.h,v 1.7 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "svector.h"
|
||||
@@ -34,7 +34,6 @@ using namespace std;
|
||||
|
||||
class Design;
|
||||
class NetScope;
|
||||
class NetExpr;
|
||||
class PExpr;
|
||||
|
||||
/*
|
||||
@@ -54,10 +53,9 @@ class PDelays {
|
||||
void set_delays(const svector<PExpr*>*del, bool delete_flag=true);
|
||||
|
||||
void eval_delays(Design*des, NetScope*scope,
|
||||
NetExpr*&rise_time,
|
||||
NetExpr*&fall_time,
|
||||
NetExpr*&decay_time,
|
||||
bool as_nets_flag =false) const;
|
||||
unsigned long&rise_time,
|
||||
unsigned long&fall_time,
|
||||
unsigned long&decay_time) const;
|
||||
|
||||
void dump_delays(ostream&out) const;
|
||||
|
||||
@@ -74,12 +72,6 @@ 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.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PExpr.cc,v 1.39 2007/05/24 04:07:11 steve Exp $"
|
||||
#ident "$Id: PExpr.cc,v 1.35.2.1 2006/02/07 22:46:23 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -53,14 +53,6 @@ NetNet* PExpr::elaborate_lnet(Design*des, NetScope*, bool) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetNet* PExpr::elaborate_bi_net(Design*des, NetScope*) const
|
||||
{
|
||||
cerr << get_line() << ": error: "
|
||||
<< "expression not valid as argument to inout port: "
|
||||
<< *this << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
PEBinary::PEBinary(char op, PExpr*l, PExpr*r)
|
||||
: op_(op), left_(l), right_(r)
|
||||
{
|
||||
@@ -75,44 +67,13 @@ bool PEBinary::is_constant(Module*mod) const
|
||||
return left_->is_constant(mod) && right_->is_constant(mod);
|
||||
}
|
||||
|
||||
PEBComp::PEBComp(char op, PExpr*l, PExpr*r)
|
||||
: PEBinary(op, l, r)
|
||||
{
|
||||
}
|
||||
|
||||
PEBComp::~PEBComp()
|
||||
{
|
||||
}
|
||||
|
||||
PEBShift::PEBShift(char op, PExpr*l, PExpr*r)
|
||||
: PEBinary(op, l, r)
|
||||
{
|
||||
}
|
||||
|
||||
PEBShift::~PEBShift()
|
||||
{
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms)
|
||||
PECallFunction::PECallFunction(const hname_t&n, const svector<PExpr *> &parms)
|
||||
: path_(n), parms_(parms)
|
||||
{
|
||||
}
|
||||
|
||||
static pform_name_t pn_from_ps(perm_string n)
|
||||
{
|
||||
name_component_t tmp_name (n);
|
||||
pform_name_t tmp;
|
||||
tmp.push_back(tmp_name);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(perm_string n, const svector<PExpr*>&parms)
|
||||
: path_(pn_from_ps(n)), parms_(parms)
|
||||
{
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(perm_string n)
|
||||
: path_(pn_from_ps(n))
|
||||
PECallFunction::PECallFunction(const hname_t&n)
|
||||
: path_(n)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -129,6 +90,8 @@ bool PEConcat::is_constant(Module *mod) const
|
||||
{
|
||||
bool constant = repeat_? repeat_->is_constant(mod) : true;
|
||||
for (unsigned i = 0; constant && i < parms_.count(); ++i) {
|
||||
if (parms_[i] == 0)
|
||||
continue;
|
||||
constant = constant && parms_[i]->is_constant(mod);
|
||||
}
|
||||
return constant;
|
||||
@@ -178,32 +141,33 @@ bool PEFNumber::is_constant(Module*) const
|
||||
return true;
|
||||
}
|
||||
|
||||
PEIdent::PEIdent(const pform_name_t&that)
|
||||
: path_(that)
|
||||
PEIdent::PEIdent(const hname_t&s)
|
||||
: path_(s), msb_(0), lsb_(0), idx_(0)
|
||||
{
|
||||
}
|
||||
|
||||
PEIdent::PEIdent(perm_string s)
|
||||
{
|
||||
path_.push_back(name_component_t(s));
|
||||
}
|
||||
|
||||
PEIdent::~PEIdent()
|
||||
{
|
||||
}
|
||||
|
||||
const hname_t& PEIdent::path() const
|
||||
{
|
||||
return path_;
|
||||
}
|
||||
|
||||
/*
|
||||
* An identifier can be in a constant expression if (and only if) it is
|
||||
* a parameter.
|
||||
*
|
||||
* NOTE: This test does not work if the name is hierarchical!
|
||||
*/
|
||||
bool PEIdent::is_constant(Module*mod) const
|
||||
{
|
||||
if (mod == 0) return false;
|
||||
|
||||
/* */
|
||||
perm_string tmp = path_.back().name;
|
||||
/* This is a work-around for map not matching < even when
|
||||
there is a perm_string operator that can do the comprare.
|
||||
|
||||
The real fix is to make the path_ carry perm_strings. */
|
||||
perm_string tmp = perm_string::literal(path_.peek_name(0));
|
||||
|
||||
{ map<perm_string,Module::param_expr_t>::const_iterator cur;
|
||||
cur = mod->parameters.find(tmp);
|
||||
@@ -300,18 +264,8 @@ bool PEUnary::is_constant(Module*m) const
|
||||
|
||||
/*
|
||||
* $Log: PExpr.cc,v $
|
||||
* Revision 1.39 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.38 2006/10/30 05:44:49 steve
|
||||
* Expression widths with unsized literals are pseudo-infinite width.
|
||||
*
|
||||
* Revision 1.37 2005/10/04 04:09:25 steve
|
||||
* Add support for indexed select attached to parameters.
|
||||
*
|
||||
* Revision 1.36 2005/08/06 17:58:16 steve
|
||||
* Implement bi-directional part selects.
|
||||
* Revision 1.35.2.1 2006/02/07 22:46:23 steve
|
||||
* More robust test for concat constant-ness.
|
||||
*
|
||||
* Revision 1.35 2004/10/04 01:10:51 steve
|
||||
* Clean up spurious trailing white space.
|
||||
|
||||
@@ -19,15 +19,13 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PExpr.h,v 1.90 2007/06/04 19:14:06 steve Exp $"
|
||||
#ident "$Id: PExpr.h,v 1.66.2.2 2006/07/28 16:26:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
# include <vector>
|
||||
# include "netlist.h"
|
||||
# include "verinum.h"
|
||||
# include "LineInfo.h"
|
||||
# include "pform_types.h"
|
||||
|
||||
class Design;
|
||||
class Module;
|
||||
@@ -52,38 +50,11 @@ class PExpr : public LineInfo {
|
||||
|
||||
virtual void dump(ostream&) 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 it the
|
||||
// minimum width that this function should return. Initially
|
||||
// this is the same as the lval width.
|
||||
//
|
||||
// The "lval" is the width of the destination where this
|
||||
// result is going to go. This can be used to constrain the
|
||||
// amount that an expression can reasonably expand. For
|
||||
// example, there is no point expanding an addition to beyond
|
||||
// the lval. This extra bit of information allows the
|
||||
// expression to optimize itself a bit. If the lval==0, then
|
||||
// the subexpression should not make l-value related
|
||||
// optimizations.
|
||||
//
|
||||
// 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,
|
||||
bool&unsized_flag) const;
|
||||
|
||||
// Procedural elaboration of the expression. The expr_width is
|
||||
// the width of the context of the expression (i.e. the
|
||||
// l-value width of an assignment) or -1 if the expression is
|
||||
// self-determinted. The sys_task_arg flag is true if
|
||||
// expressions are allowed to be incomplete.
|
||||
// Procedural elaboration of the expression. Set the
|
||||
// bare_memory_ok flag if the result is allowed to be a
|
||||
// NetEMemory without an index.
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
bool sys_task_arg =false) const;
|
||||
|
||||
// Elaborate expressions that are the r-value of parameter
|
||||
// assignments. This elaboration follows the restrictions of
|
||||
@@ -95,37 +66,30 @@ class PExpr : public LineInfo {
|
||||
// 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,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0 =Link::STRONG,
|
||||
Link::strength_t drive1 =Link::STRONG)
|
||||
const;
|
||||
|
||||
// This method elaborates the expression as NetNet objects. It
|
||||
// only allows regs suitable for procedural continuous assignments.
|
||||
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) 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,
|
||||
bool implicit_net_ok =false) const;
|
||||
|
||||
// This is similar to elaborate_lnet, except that the
|
||||
// expression is evaluated to be bi-directional. This is
|
||||
// useful for arguments to inout ports of module instances and
|
||||
// ports of tran primitives.
|
||||
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
|
||||
|
||||
// Expressions that can be in the l-value of procedural
|
||||
// assignments can be elaborated with this method. If the
|
||||
// is_force flag is true, then the set of valid l-value types
|
||||
// is slightly modified to accomodate the Verilog force
|
||||
// statement
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
// assignments can be elaborated with this method.
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
|
||||
|
||||
// This attempts to evaluate a constant expression, and return
|
||||
// a verinum as a result. If the expression cannot be
|
||||
// evaluated, return 0.
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
|
||||
// This method returns true if that expression is the same as
|
||||
// this expression. This method is used for comparing
|
||||
@@ -151,31 +115,29 @@ class PEConcat : public PExpr {
|
||||
PEConcat(const svector<PExpr*>&p, PExpr*r =0);
|
||||
~PEConcat();
|
||||
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
// Concatenated Regs can be on the left of procedural
|
||||
// continuous assignments.
|
||||
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok =false) 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,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long 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;
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetEConcat*elaborate_pexpr(Design*des, NetScope*) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
private:
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok,
|
||||
bool bidirectional_flag) const;
|
||||
private:
|
||||
svector<PExpr*>parms_;
|
||||
PExpr*repeat_;
|
||||
@@ -222,23 +184,15 @@ class PEFNumber : public PExpr {
|
||||
/* The eval_const method as applied to a floating point number
|
||||
gets the *integer* value of the number. This accounts for
|
||||
any rounding that is needed to get the value. */
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
|
||||
/* 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;
|
||||
bool sys_task_arg =false) 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:
|
||||
@@ -248,41 +202,32 @@ class PEFNumber : public PExpr {
|
||||
class PEIdent : public PExpr {
|
||||
|
||||
public:
|
||||
explicit PEIdent(perm_string);
|
||||
explicit PEIdent(const pform_name_t&);
|
||||
explicit PEIdent(const hname_t&s);
|
||||
~PEIdent();
|
||||
|
||||
// Add another name to the string of heirarchy that is the
|
||||
// current identifier.
|
||||
void append_name(perm_string);
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
|
||||
// Regs can be on the left of procedural continuous assignments
|
||||
virtual NetNet* elaborate_anet(Design*des, NetScope*scope) const;
|
||||
|
||||
// Identifiers are allowed (with restrictions) is assign l-values.
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok =false) const;
|
||||
|
||||
virtual NetNet* elaborate_bi_net(Design*des, NetScope*scope) const;
|
||||
|
||||
// Identifiers are also allowed as procedural assignment l-values.
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) 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,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long 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;
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
|
||||
// Elaborate the PEIdent as a port to a module. This method
|
||||
@@ -290,86 +235,39 @@ class PEIdent : public PExpr {
|
||||
NetNet* elaborate_port(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
|
||||
const pform_name_t& path() const { return path_; }
|
||||
const hname_t& path() const;
|
||||
|
||||
private:
|
||||
pform_name_t path_;
|
||||
|
||||
private:
|
||||
// Common functions to calculate parts of part/bit selects.
|
||||
bool calculate_parts_(Design*, NetScope*, long&msb, long&lsb) const;
|
||||
bool calculate_up_do_width_(Design*, NetScope*, unsigned long&wid) const;
|
||||
|
||||
private:
|
||||
NetAssign_*elaborate_lval_net_word_(Design*, NetScope*, NetNet*) const;
|
||||
bool elaborate_lval_net_part_(Design*, NetScope*, NetAssign_*) const;
|
||||
bool elaborate_lval_net_idx_up_(Design*, NetScope*, NetAssign_*) const;
|
||||
bool elaborate_lval_net_idx_do_(Design*, NetScope*, NetAssign_*) const;
|
||||
|
||||
private:
|
||||
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_net(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found,
|
||||
bool sys_task_arg) const;
|
||||
NetExpr*elaborate_expr_net_word_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found,
|
||||
bool sys_task_arg) const;
|
||||
NetExpr*elaborate_expr_net_part_(Design*des,
|
||||
NetScope*scope,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net_idx_up_(Design*des,
|
||||
NetScope*scope,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net_bit_(Design*des,
|
||||
NetScope*scope,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
hname_t path_;
|
||||
|
||||
public:
|
||||
// Use these to support bit- and part-select operators.
|
||||
PExpr*msb_;
|
||||
PExpr*lsb_;
|
||||
|
||||
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;
|
||||
// If this is a reference to a memory, this is the index
|
||||
// expression.
|
||||
PExpr*idx_;
|
||||
|
||||
NetNet* elaborate_net_ram_(Design*des, NetScope*scope,
|
||||
NetMemory*mem, unsigned lwidth,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
|
||||
NetNet* elaborate_net_bitmux_(Design*des, NetScope*scope,
|
||||
NetNet*sig,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
private:
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok,
|
||||
bool bidirectional_flag) const;
|
||||
|
||||
NetNet*make_implicit_net_(Design*des, NetScope*scope) const;
|
||||
|
||||
bool eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
unsigned&midx, unsigned&lidx) const;
|
||||
NetNet*process_select_(Design*des, NetScope*scope, NetNet*sig) const;
|
||||
NetAssign_* elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
NetMemory*mem) const;
|
||||
|
||||
};
|
||||
|
||||
@@ -382,25 +280,19 @@ class PENumber : public PExpr {
|
||||
const verinum& value() const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool) const;
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
virtual NetAssign_* elaborate_lval(Design*des, NetScope*scope) const;
|
||||
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
|
||||
virtual bool is_the_same(const PExpr*that) const;
|
||||
virtual bool is_constant(Module*) const;
|
||||
@@ -424,22 +316,17 @@ class PEString : public PExpr {
|
||||
|
||||
string value() const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool) const;
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
verinum* eval_const(Design*, NetScope*) const;
|
||||
verinum* eval_const(const Design*, const NetScope*) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
@@ -454,18 +341,17 @@ class PEUnary : public PExpr {
|
||||
~PEUnary();
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long 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;
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
@@ -483,100 +369,65 @@ class PEBinary : public PExpr {
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
virtual NetEBinary*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
|
||||
protected:
|
||||
private:
|
||||
char op_;
|
||||
PExpr*left_;
|
||||
PExpr*right_;
|
||||
|
||||
NetEBinary*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
NetEBinary*elaborate_eval_expr_base_(Design*, NetExpr*lp, NetExpr*rp, int use_wid) const;
|
||||
NetEBinary*elaborate_expr_base_(Design*, NetExpr*lp, NetExpr*rp) const;
|
||||
|
||||
private:
|
||||
NetNet* elaborate_net_add_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_bit_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_cmp_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_div_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_mod_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_log_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_mul_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
NetNet* elaborate_net_shift_(Design*des, NetScope*scope,
|
||||
unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
};
|
||||
|
||||
/*
|
||||
* Here are a few specilized classes for handling specific binary
|
||||
* operators.
|
||||
*/
|
||||
class PEBComp : public PEBinary {
|
||||
|
||||
public:
|
||||
explicit PEBComp(char op, PExpr*l, PExpr*r);
|
||||
~PEBComp();
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
bool&flag) const;
|
||||
|
||||
NetEBinary* elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
};
|
||||
|
||||
class PEBShift : public PEBinary {
|
||||
|
||||
public:
|
||||
explicit PEBShift(char op, PExpr*l, PExpr*r);
|
||||
~PEBShift();
|
||||
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval, bool&flag) const;
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long decay) const;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -592,21 +443,17 @@ class PETernary : public PExpr {
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual unsigned test_width(Design*des, NetScope*scope,
|
||||
unsigned min, unsigned lval,
|
||||
bool&unsized_flag) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long 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;
|
||||
bool sys_task_arg =false) const;
|
||||
virtual NetETernary*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, const NetScope*sc) const;
|
||||
|
||||
private:
|
||||
PExpr*expr_;
|
||||
@@ -621,130 +468,37 @@ class PETernary : public PExpr {
|
||||
*/
|
||||
class PECallFunction : public PExpr {
|
||||
public:
|
||||
explicit PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms);
|
||||
// Call of system function (name is not heirarchical)
|
||||
explicit PECallFunction(perm_string n, const svector<PExpr *> &parms);
|
||||
explicit PECallFunction(perm_string n);
|
||||
explicit PECallFunction(const hname_t&n, const svector<PExpr *> &parms);
|
||||
explicit PECallFunction(const hname_t&n);
|
||||
~PECallFunction();
|
||||
|
||||
virtual void dump(ostream &) const;
|
||||
|
||||
virtual NetNet* elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned width,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
unsigned long rise,
|
||||
unsigned long fall,
|
||||
unsigned long 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;
|
||||
bool sys_task_arg =false) const;
|
||||
|
||||
private:
|
||||
pform_name_t path_;
|
||||
hname_t path_;
|
||||
svector<PExpr *> parms_;
|
||||
|
||||
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
|
||||
|
||||
NetExpr* elaborate_sfunc_(Design*des, NetScope*scope) 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;
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PExpr.h,v $
|
||||
* Revision 1.90 2007/06/04 19:14:06 steve
|
||||
* Build errors in picky GCC compilers.
|
||||
* Revision 1.66.2.2 2006/07/28 16:26:17 steve
|
||||
* Remove excess PEString:: prefix for stubborn compilers.
|
||||
*
|
||||
* Revision 1.89 2007/06/04 02:19:07 steve
|
||||
* Handle bit/part select of array words in nets.
|
||||
*
|
||||
* Revision 1.88 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.87 2007/01/16 05:44:14 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.86 2006/11/10 04:54:26 steve
|
||||
* Add test_width methods for PETernary and PEString.
|
||||
*
|
||||
* Revision 1.85 2006/11/04 06:19:24 steve
|
||||
* Remove last bits of relax_width methods, and use test_width
|
||||
* to calculate the width of an r-value expression that may
|
||||
* contain unsized numbers.
|
||||
*
|
||||
* Revision 1.84 2006/10/30 05:44:49 steve
|
||||
* Expression widths with unsized literals are pseudo-infinite width.
|
||||
*
|
||||
* Revision 1.83 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.82 2006/06/02 04:48:49 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.81 2006/04/28 04:28:35 steve
|
||||
* Allow concatenations as arguments to inout ports.
|
||||
*
|
||||
* Revision 1.80 2006/04/16 00:54:04 steve
|
||||
* Cleanup lval part select handling.
|
||||
*
|
||||
* Revision 1.79 2006/04/16 00:15:43 steve
|
||||
* Fix part selects in l-values.
|
||||
*
|
||||
* Revision 1.78 2006/03/25 02:36:26 steve
|
||||
* Get rid of excess PESTring:: prefix within class declaration.
|
||||
*
|
||||
* Revision 1.77 2006/02/02 02:43:57 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.76 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
* Revision 1.75 2005/12/07 04:04:23 steve
|
||||
* Allow constant concat expressions.
|
||||
*
|
||||
* Revision 1.74 2005/11/27 17:01:56 steve
|
||||
* Fix for stubborn compiler.
|
||||
*
|
||||
* Revision 1.73 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
* Revision 1.72 2005/11/10 13:28:11 steve
|
||||
* Reorganize signal part select handling, and add support for
|
||||
* indexed part selects.
|
||||
*
|
||||
* Expand expression constant propagation to eliminate extra
|
||||
* sums in certain cases.
|
||||
*
|
||||
* Revision 1.71 2005/10/04 04:09:25 steve
|
||||
* Add support for indexed select attached to parameters.
|
||||
*
|
||||
* Revision 1.70 2005/08/06 17:58:16 steve
|
||||
* Implement bi-directional part selects.
|
||||
*
|
||||
* Revision 1.69 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.68 2005/01/09 20:16:00 steve
|
||||
* Use PartSelect/PV and VP to handle part selects through ports.
|
||||
*
|
||||
* Revision 1.67 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
* Revision 1.66.2.1 2005/12/07 03:28:44 steve
|
||||
* Support constant concatenation of constants.
|
||||
*
|
||||
* Revision 1.66 2004/10/04 01:10:51 steve
|
||||
* Clean up spurious trailing white space.
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PGate.cc,v 1.18 2006/01/03 05:22:14 steve Exp $"
|
||||
#ident "$Id: PGate.cc,v 1.16 2004/02/18 17:11:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -90,69 +90,12 @@ void PGate::elaborate_scope(Design*, NetScope*) const
|
||||
* parameters. This method understands how to handle the different
|
||||
* numbers of expressions.
|
||||
*/
|
||||
|
||||
void PGate::eval_delays(Design*des, NetScope*scope,
|
||||
NetExpr*&rise_expr,
|
||||
NetExpr*&fall_expr,
|
||||
NetExpr*&decay_expr,
|
||||
bool as_net_flag) const
|
||||
{
|
||||
delay_.eval_delays(des, scope,
|
||||
rise_expr, fall_expr, decay_expr,
|
||||
as_net_flag);
|
||||
}
|
||||
|
||||
void PGate::eval_delays(Design*des, NetScope*scope,
|
||||
unsigned long&rise_time,
|
||||
unsigned long&fall_time,
|
||||
unsigned long&decay_time) const
|
||||
{
|
||||
NetExpr*rise_expr, *fall_expr, *decay_expr;
|
||||
delay_.eval_delays(des, scope, rise_expr, fall_expr, decay_expr);
|
||||
|
||||
if (rise_expr == 0) {
|
||||
rise_time = 0;
|
||||
fall_time = 0;
|
||||
decay_time = 0;
|
||||
}
|
||||
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*> (rise_expr)) {
|
||||
rise_time = tmp->value().as_ulong();
|
||||
|
||||
} else {
|
||||
cerr << get_line() << ": error: Delay expressions must be "
|
||||
<< "constant here." << endl;
|
||||
cerr << get_line() << ": : Cannot calculate "
|
||||
<< *rise_expr << endl;
|
||||
des->errors += 1;
|
||||
rise_time = 0;
|
||||
}
|
||||
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*> (fall_expr)) {
|
||||
fall_time = tmp->value().as_ulong();
|
||||
|
||||
} else {
|
||||
if (fall_expr != rise_expr) {
|
||||
cerr << get_line() << ": error: Delay expressions must be "
|
||||
<< "constant here." << endl;
|
||||
cerr << get_line() << ": : Cannot calculate "
|
||||
<< *rise_expr << endl;
|
||||
}
|
||||
des->errors += 1;
|
||||
fall_time = 0;
|
||||
}
|
||||
|
||||
if (NetEConst*tmp = dynamic_cast<NetEConst*> (decay_expr)) {
|
||||
decay_time = tmp->value().as_ulong();
|
||||
|
||||
} else {
|
||||
cerr << get_line() << ": error: Delay expressions must be "
|
||||
<< "constant here." << endl;
|
||||
cerr << get_line() << ": : Cannot calculate "
|
||||
<< *rise_expr << endl;
|
||||
des->errors += 1;
|
||||
decay_time = 0;
|
||||
}
|
||||
delay_.eval_delays(des, scope, rise_time, fall_time, decay_time);
|
||||
}
|
||||
|
||||
PGAssign::PGAssign(svector<PExpr*>*pins)
|
||||
@@ -248,12 +191,6 @@ perm_string PGModule::get_type()
|
||||
|
||||
/*
|
||||
* $Log: PGate.cc,v $
|
||||
* Revision 1.18 2006/01/03 05:22:14 steve
|
||||
* Handle complex net node delays.
|
||||
*
|
||||
* Revision 1.17 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
* Revision 1.16 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* 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 $"
|
||||
#ident "$Id: PGate.h,v 1.29 2004/10/04 01:10:52 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "svector.h"
|
||||
@@ -66,23 +66,11 @@ class PGate : public LineInfo {
|
||||
|
||||
perm_string get_name() const { return name_; }
|
||||
|
||||
// This method evaluates the delays all the way to an
|
||||
// integer. If the delay is non-constant, then set the times
|
||||
// to 0, print an error message and mark an error to the
|
||||
// design.
|
||||
void eval_delays(Design*des, NetScope*scope,
|
||||
unsigned long&rise_time,
|
||||
unsigned long&fall_time,
|
||||
unsigned long&decay_time) const;
|
||||
|
||||
// This evaluates the delays as far as possible, but returns
|
||||
// an expression, and do not signal errors.
|
||||
void eval_delays(Design*des, NetScope*scope,
|
||||
NetExpr*&rise_time,
|
||||
NetExpr*&fall_time,
|
||||
NetExpr*&decay_time,
|
||||
bool as_net_flag =false) const;
|
||||
|
||||
unsigned pin_count() const { return pins_? pins_->count() : 0; }
|
||||
const PExpr*pin(unsigned idx) const { return (*pins_)[idx]; }
|
||||
|
||||
@@ -94,7 +82,7 @@ class PGate : public LineInfo {
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind =4) const;
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*sc) const;
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
@@ -128,7 +116,7 @@ class PGAssign : public PGate {
|
||||
explicit PGAssign(svector<PExpr*>*pins, svector<PExpr*>*dels);
|
||||
~PGAssign();
|
||||
|
||||
void dump(ostream&out, unsigned ind =4) const;
|
||||
void dump(ostream&out) const;
|
||||
virtual void elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
@@ -165,7 +153,7 @@ class PGBuiltin : public PGate {
|
||||
Type type() const { return type_; }
|
||||
void set_range(PExpr*msb, PExpr*lsb);
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind =4) const;
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void elaborate(Design*, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
@@ -208,7 +196,7 @@ class PGModule : public PGate {
|
||||
// method to pass the range to the pform.
|
||||
void set_range(PExpr*msb, PExpr*lsb);
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind =4) const;
|
||||
virtual void dump(ostream&out) const;
|
||||
virtual void elaborate(Design*, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*sc) const;
|
||||
virtual bool elaborate_sig(Design*des, NetScope*scope) const;
|
||||
@@ -239,15 +227,6 @@ class PGModule : public PGate {
|
||||
|
||||
/*
|
||||
* $Log: PGate.h,v $
|
||||
* Revision 1.32 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.31 2006/01/03 05:22:14 steve
|
||||
* Handle complex net node delays.
|
||||
*
|
||||
* Revision 1.30 2006/01/02 05:33:19 steve
|
||||
* Node delays can be more general expressions in structural contexts.
|
||||
*
|
||||
* Revision 1.29 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* 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
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PGenerate.cc,v 1.4 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PGenerate.h"
|
||||
# include "PWire.h"
|
||||
|
||||
PGenerate::PGenerate(unsigned id)
|
||||
: id_number(id)
|
||||
{
|
||||
parent = 0;
|
||||
}
|
||||
|
||||
PGenerate::~PGenerate()
|
||||
{
|
||||
}
|
||||
|
||||
PWire* PGenerate::add_wire(PWire*wire)
|
||||
{
|
||||
PWire*&ep = wires[wire->path()];
|
||||
if (ep) return ep;
|
||||
|
||||
assert(ep == 0);
|
||||
ep = wire;
|
||||
return wire;
|
||||
}
|
||||
|
||||
PWire* PGenerate::get_wire(const pform_name_t&name) const
|
||||
{
|
||||
map<pform_name_t,PWire*>::const_iterator obj = wires.find(name);
|
||||
if (obj == wires.end())
|
||||
return 0;
|
||||
else
|
||||
return (*obj).second;
|
||||
}
|
||||
|
||||
void PGenerate::add_gate(PGate*gate)
|
||||
{
|
||||
gates.push_back(gate);
|
||||
}
|
||||
|
||||
void PGenerate::add_behavior(PProcess*proc)
|
||||
{
|
||||
behaviors.push_back(proc);
|
||||
}
|
||||
-100
@@ -1,100 +0,0 @@
|
||||
#ifndef __PGenerate_H
|
||||
#define __PGenerate_H
|
||||
/*
|
||||
* 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
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PGenerate.h,v 1.4 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include "StringHeap.h"
|
||||
# include "HName.h"
|
||||
# include <list>
|
||||
# include <map>
|
||||
# include "pform_types.h"
|
||||
|
||||
class Design;
|
||||
class NetScope;
|
||||
class PExpr;
|
||||
class PProcess;
|
||||
class PGate;
|
||||
class PWire;
|
||||
|
||||
/*
|
||||
* This represents a generate scheme.
|
||||
*/
|
||||
class PGenerate : public LineInfo {
|
||||
|
||||
public:
|
||||
PGenerate(unsigned id_number);
|
||||
~PGenerate();
|
||||
|
||||
// Generate schemes have an ID number, for when the scope is
|
||||
// implicit.
|
||||
const unsigned id_number;
|
||||
perm_string scope_name;
|
||||
|
||||
enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT};
|
||||
scheme_t scheme_type;
|
||||
|
||||
// generate loops have an index variable and three
|
||||
// expressions: for (index = <init>; <test>; index=<step>)
|
||||
perm_string loop_index;
|
||||
PExpr*loop_init;
|
||||
PExpr*loop_test;
|
||||
PExpr*loop_step;
|
||||
|
||||
map<pform_name_t,PWire*>wires;
|
||||
PWire* add_wire(PWire*);
|
||||
PWire* get_wire(const pform_name_t&name) const;
|
||||
|
||||
list<PGate*> gates;
|
||||
void add_gate(PGate*);
|
||||
|
||||
list<PProcess*> behaviors;
|
||||
void add_behavior(PProcess*behave);
|
||||
|
||||
list<PGenerate*> generates;
|
||||
PGenerate*parent;
|
||||
|
||||
// This method is called by the elaboration of a module to
|
||||
// generate scopes. the container is the scope that is to
|
||||
// contain the generated scope.
|
||||
bool generate_scope(Design*des, NetScope*container);
|
||||
|
||||
bool elaborate_sig(Design*des) const;
|
||||
bool elaborate(Design*des) const;
|
||||
|
||||
void dump(ostream&out, unsigned indent) const;
|
||||
|
||||
private:
|
||||
bool generate_scope_loop_(Design*des, NetScope*container);
|
||||
|
||||
// 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_(Design*des, NetScope*scope) const;
|
||||
|
||||
private: // not implemented
|
||||
PGenerate(const PGenerate&);
|
||||
PGenerate& operator= (const PGenerate&);
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -1,79 +0,0 @@
|
||||
#ifndef __PSpec_H
|
||||
#define __PSpec_H
|
||||
/*
|
||||
* 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
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PSpec.h,v 1.3 2007/04/13 02:34:35 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
# include "StringHeap.h"
|
||||
# include <vector>
|
||||
|
||||
class PExpr;
|
||||
|
||||
/*
|
||||
* The PSpecPath is the parse of a specify path, which is in its most
|
||||
* general form <path> = <delays>. The <delays> are collected into the
|
||||
* "delays" vector in all cases, and the variety is in the other
|
||||
* members.
|
||||
*
|
||||
* All paths also have a list of source names in the src vector, and a
|
||||
* list of destination names in the dst vector. These pairs are the
|
||||
* actual paths.
|
||||
*
|
||||
* If the path is a simple path, then:
|
||||
* condition == nil
|
||||
* edge == 0
|
||||
* data_source_expression == nil
|
||||
*
|
||||
* If the path is conditional, then conditional == true and condition
|
||||
* is the condition expression. If the condition expression is nil,
|
||||
* then this is an ifnone conditional path.
|
||||
*
|
||||
* If data_source_expression != nil, then the path is edge sensitive
|
||||
* and the edge might not be 0.
|
||||
*/
|
||||
class PSpecPath : public LineInfo {
|
||||
|
||||
public:
|
||||
PSpecPath(unsigned src_cnt, unsigned dst_cnt);
|
||||
~PSpecPath();
|
||||
|
||||
void elaborate(class Design*des, class NetScope*scope) const;
|
||||
|
||||
void dump(std::ostream&out, unsigned ind) const;
|
||||
|
||||
public:
|
||||
// Condition expression, if present.
|
||||
bool conditional;
|
||||
class PExpr* condition;
|
||||
// Edge specification (-1==negedge, 0 = no edge, 1==posedge)
|
||||
int edge;
|
||||
// Ordered set of source nodes of a path
|
||||
std::vector<perm_string> src;
|
||||
// Ordered set of destination nodes of a path
|
||||
std::vector<perm_string> dst;
|
||||
// Data source expression
|
||||
class PExpr* data_source_expression;
|
||||
|
||||
std::vector<class PExpr*>delays;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PTask.h,v 1.14 2007/03/06 05:22:49 steve Exp $"
|
||||
#ident "$Id: PTask.h,v 1.13.2.1 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
@@ -35,7 +35,6 @@ class PExpr;
|
||||
enum PTaskFuncEnum {
|
||||
PTF_NONE,
|
||||
PTF_REG,
|
||||
PTF_REG_S,
|
||||
PTF_INTEGER,
|
||||
PTF_REAL,
|
||||
PTF_REALTIME,
|
||||
@@ -71,7 +70,7 @@ class PTask : public LineInfo {
|
||||
// Elaborate the statement to finish off the task definition.
|
||||
void elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
void dump(std::ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
svector<PWire*>*ports_;
|
||||
@@ -107,7 +106,7 @@ class PFunction : public LineInfo {
|
||||
/* Elaborate the behavioral statement. */
|
||||
void elaborate(Design *des, NetScope*) const;
|
||||
|
||||
void dump(ostream&, unsigned) const;
|
||||
void dump(std::ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
@@ -118,8 +117,8 @@ class PFunction : public LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: PTask.h,v $
|
||||
* Revision 1.14 2007/03/06 05:22:49 steve
|
||||
* Support signed function return values.
|
||||
* Revision 1.13.2.1 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.13 2004/05/31 23:34:36 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* 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 $"
|
||||
#ident "$Id: PUdp.h,v 1.12.2.1 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <map>
|
||||
@@ -55,20 +55,20 @@ class PUdp {
|
||||
public:
|
||||
explicit PUdp(perm_string n, unsigned nports);
|
||||
|
||||
svector<string>ports;
|
||||
svector<std::string>ports;
|
||||
unsigned find_port(const char*name);
|
||||
|
||||
bool sequential;
|
||||
|
||||
svector<string>tinput;
|
||||
svector<std::string>tinput;
|
||||
svector<char> tcurrent;
|
||||
svector<char> toutput;
|
||||
|
||||
verinum::V initial;
|
||||
|
||||
map<string,PExpr*> attributes;
|
||||
std::map<std::string,PExpr*> attributes;
|
||||
|
||||
void dump(ostream&out) const;
|
||||
void dump(std::ostream&out) const;
|
||||
|
||||
perm_string name_;
|
||||
private:
|
||||
@@ -80,6 +80,9 @@ class PUdp {
|
||||
|
||||
/*
|
||||
* $Log: PUdp.h,v $
|
||||
* Revision 1.12.2.1 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.12 2004/03/08 00:47:44 steve
|
||||
* primitive ports can bind bi name.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2007 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,19 +17,26 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PWire.cc,v 1.14 2007/05/24 04:07:11 steve Exp $"
|
||||
#ident "$Id: PWire.cc,v 1.10 2002/08/12 01:34:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "PWire.h"
|
||||
# include <assert.h>
|
||||
|
||||
PWire::PWire(const pform_name_t&n,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt)
|
||||
: hname_(n), type_(t), port_type_(pt), data_type_(dt),
|
||||
signed_(false), isint_(false),
|
||||
PWire::PWire(const hname_t&n, NetNet::Type t, NetNet::PortType pt)
|
||||
: hname_(n), type_(t), port_type_(pt), signed_(false), isint_(false),
|
||||
lidx_(0), ridx_(0)
|
||||
{
|
||||
if (t == NetNet::INTEGER) {
|
||||
type_ = NetNet::REG;
|
||||
signed_ = true;
|
||||
isint_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
PWire::PWire(char*n, NetNet::Type t, NetNet::PortType pt)
|
||||
: hname_(n), type_(t), port_type_(pt), signed_(false), isint_(false),
|
||||
lidx_(0), ridx_(0)
|
||||
{
|
||||
if (t == NetNet::INTEGER) {
|
||||
@@ -44,7 +51,7 @@ NetNet::Type PWire::get_wire_type() const
|
||||
return type_;
|
||||
}
|
||||
|
||||
const pform_name_t& PWire::path() const
|
||||
const hname_t& PWire::path() const
|
||||
{
|
||||
return hname_;
|
||||
}
|
||||
@@ -101,19 +108,6 @@ bool PWire::set_port_type(NetNet::PortType pt)
|
||||
}
|
||||
}
|
||||
|
||||
bool PWire::set_data_type(ivl_variable_type_t dt)
|
||||
{
|
||||
if (data_type_ != IVL_VT_NO_TYPE)
|
||||
if (data_type_ != dt)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
|
||||
assert(data_type_ == IVL_VT_NO_TYPE);
|
||||
data_type_ = dt;
|
||||
return true;
|
||||
}
|
||||
|
||||
void PWire::set_signed(bool flag)
|
||||
{
|
||||
signed_ = flag;
|
||||
@@ -139,28 +133,13 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
|
||||
{
|
||||
assert(lidx_ == 0);
|
||||
assert(ridx_ == 0);
|
||||
assert(type_ == NetNet::REG);
|
||||
lidx_ = ldx;
|
||||
ridx_ = rdx;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PWire.cc,v $
|
||||
* Revision 1.14 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.13 2007/04/26 03:06:21 steve
|
||||
* Rework hname_t to use perm_strings.
|
||||
*
|
||||
* Revision 1.12 2007/01/16 05:44:14 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.11 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.10 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PWire_H
|
||||
#define __PWire_H
|
||||
/*
|
||||
* Copyright (c) 1998-2007 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -19,14 +19,13 @@
|
||||
* 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 $"
|
||||
#ident "$Id: PWire.h,v 1.17 2004/02/20 18:53:33 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
# include "LineInfo.h"
|
||||
# include <map>
|
||||
# include "svector.h"
|
||||
# include "StringHeap.h"
|
||||
|
||||
#ifdef HAVE_IOSFWD
|
||||
# include <iosfwd>
|
||||
@@ -43,21 +42,18 @@ class Design;
|
||||
* identifies a port by keeping it in its port list.
|
||||
*
|
||||
* The hname parameter to the constructor is a hierarchical name. It
|
||||
* is the name of the wire within a module, so does not include the
|
||||
* current scope or any instances. Modules contain all the wires, so
|
||||
* from that perspective, sub-scopes within the module are a part of
|
||||
* the wire name.
|
||||
* is an array of strings starting with the root, running towards
|
||||
* the base name, and terminated by a null pointer. The environment
|
||||
* allocates the memory for me.
|
||||
*/
|
||||
class PWire : public LineInfo {
|
||||
|
||||
public:
|
||||
PWire(const pform_name_t&hname,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt);
|
||||
PWire(const hname_t&hname, NetNet::Type t, NetNet::PortType pt);
|
||||
PWire(char*name, NetNet::Type t, NetNet::PortType pt);
|
||||
|
||||
// Return a hierarchical name.
|
||||
const pform_name_t&path() const;
|
||||
const hname_t&path() const;
|
||||
|
||||
NetNet::Type get_wire_type() const;
|
||||
bool set_wire_type(NetNet::Type);
|
||||
@@ -69,9 +65,6 @@ class PWire : public LineInfo {
|
||||
bool get_signed() const;
|
||||
bool get_isint() const;
|
||||
|
||||
bool set_data_type(ivl_variable_type_t dt);
|
||||
ivl_variable_type_t get_data_type() const;
|
||||
|
||||
void set_range(PExpr*msb, PExpr*lsb);
|
||||
|
||||
void set_memory_idx(PExpr*ldx, PExpr*rdx);
|
||||
@@ -79,15 +72,14 @@ class PWire : public LineInfo {
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
// Write myself to the specified stream.
|
||||
void dump(ostream&out, unsigned ind=4) const;
|
||||
void dump(ostream&out) const;
|
||||
|
||||
NetNet* elaborate_sig(Design*, NetScope*scope) const;
|
||||
void elaborate_sig(Design*, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
pform_name_t hname_;
|
||||
hname_t hname_;
|
||||
NetNet::Type type_;
|
||||
NetNet::PortType port_type_;
|
||||
ivl_variable_type_t data_type_;
|
||||
bool signed_;
|
||||
bool isint_; // original type of integer
|
||||
|
||||
@@ -108,19 +100,6 @@ class PWire : public LineInfo {
|
||||
|
||||
/*
|
||||
* $Log: PWire.h,v $
|
||||
* Revision 1.21 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.20 2007/04/26 03:06:22 steve
|
||||
* Rework hname_t to use perm_strings.
|
||||
*
|
||||
* Revision 1.19 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.18 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.17 2004/02/20 18:53:33 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
@@ -151,5 +130,40 @@ class PWire : public LineInfo {
|
||||
*
|
||||
* Revision 1.10 2001/01/16 02:44:18 steve
|
||||
* Use the iosfwd header if available.
|
||||
*
|
||||
* Revision 1.9 2000/12/11 00:31:43 steve
|
||||
* Add support for signed reg variables,
|
||||
* simulate in t-vvm signed comparisons.
|
||||
*
|
||||
* Revision 1.8 2000/05/02 16:27:38 steve
|
||||
* Move signal elaboration to a seperate pass.
|
||||
*
|
||||
* Revision 1.7 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.6 1999/11/27 19:07:57 steve
|
||||
* Support the creation of scopes.
|
||||
*
|
||||
* Revision 1.5 1999/06/17 05:34:42 steve
|
||||
* Clean up interface of the PWire class,
|
||||
* Properly match wire ranges.
|
||||
*
|
||||
* Revision 1.4 1999/06/02 15:38:46 steve
|
||||
* Line information with nets.
|
||||
*
|
||||
* Revision 1.3 1999/04/19 01:59:36 steve
|
||||
* Add memories to the parse and elaboration phases.
|
||||
*
|
||||
* Revision 1.2 1998/11/23 00:20:22 steve
|
||||
* NetAssign handles lvalues as pin links
|
||||
* instead of a signal pointer,
|
||||
* Wire attributes added,
|
||||
* Ability to parse UDP descriptions added,
|
||||
* XNF generates EXT records for signals with
|
||||
* the PAD attribute.
|
||||
*
|
||||
* Revision 1.1 1998/11/03 23:28:55 steve
|
||||
* Introduce verilog to CVS.
|
||||
*
|
||||
*/
|
||||
#endif
|
||||
|
||||
+51
-17
@@ -114,7 +114,7 @@ configure script that modify its behavior:
|
||||
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:
|
||||
somewhat more complex command:
|
||||
|
||||
./configure libdir64='$(prefix)/lib64' vpidir1=vpi64 vpidir2=. --enable-vvp32
|
||||
|
||||
@@ -359,8 +359,7 @@ constructs.
|
||||
Icarus Verilog includes some features that are not part of the
|
||||
IEEE1364 standard, but have well defined meaning, and also sometimes
|
||||
gives nonstandard (but extended) meanings to some features of the
|
||||
language that are defined. See the "extensions.txt" documentation for
|
||||
more details.
|
||||
language that are defined.
|
||||
|
||||
$is_signed(<expr>)
|
||||
This system function returns 1 if the expression contained is
|
||||
@@ -471,20 +470,6 @@ more details.
|
||||
combinational always blocks to be triggered when the values in
|
||||
the sensitivity list are initialized by initial threads.
|
||||
|
||||
Nets with Types
|
||||
|
||||
Icarus Verilog support an extension syntax that allows nets
|
||||
and regs to be explicitly typed. The currently supported types
|
||||
are logic, bool and real. This implies that "logic" and "bool"
|
||||
are new keywords. Typical syntax is:
|
||||
|
||||
wire real foo = 1.0;
|
||||
reg logic bar, bat;
|
||||
|
||||
... and so forth. The syntax can be turned off by using the
|
||||
-g2 flag to iverilog, and turned on explicitly with the -g2x
|
||||
flag to iverilog.
|
||||
|
||||
6.0 CREDITS
|
||||
|
||||
Except where otherwise noted, Icarus Verilog, ivl and ivlpp are
|
||||
@@ -494,3 +479,52 @@ Verilog guidance, and especially testing from many people. Testers in
|
||||
particular include a larger community of people interested in a GPL
|
||||
Verilog for Linux.
|
||||
|
||||
|
||||
6.1 PORT MAINTAINERS
|
||||
|
||||
This is a list of people who have created ports and precompiled
|
||||
packages for various operating systems. These folks have graciously
|
||||
taken on the task of building Icarus Verilog on their systems and
|
||||
bundled it into neat packages.(+) If you want to be added to the list (or
|
||||
removed from the list) send e-mail to me.
|
||||
|
||||
FreeBSD/{Intel,alpha}
|
||||
Ying-Chieh Liao <[email protected]>
|
||||
|
||||
Linux/{alpha,AMD64,Intel} (RPMS)
|
||||
Stephen Williams <[email protected]>
|
||||
|
||||
Linux/* (.debs)
|
||||
Hamish Moffatt <[email protected]>
|
||||
|
||||
Macintosh -- MacO/S
|
||||
Yasuhisa Kato <[email protected]>
|
||||
|
||||
Mac O/S X
|
||||
Timothy J. Wood <[email protected]>
|
||||
|
||||
NetBSD/*
|
||||
Dan McMahill <[email protected]>
|
||||
|
||||
Solaris/SPARC packages (.pkg)
|
||||
Dan McMahill <[email protected]>
|
||||
|
||||
Cygwin32/*
|
||||
Venkat Iyer <[email protected]>
|
||||
|
||||
Mingw32
|
||||
Venkat Iyer <[email protected]>
|
||||
|
||||
(+) These are not the only systems where Icarus Verilog has been run,
|
||||
just the systems where precompiled binaries are publicly available.
|
||||
|
||||
|
||||
6.2 TEST SUITE MANAGER
|
||||
|
||||
Steve Wilson <[email protected]> has taken on the large task of managing
|
||||
the test suite. He has maintained the regression test scripts, the
|
||||
driver list, received submissions from myself and others, and has
|
||||
written a great many tests on his own. Any compiler writer, for any
|
||||
language, will tell you that the test suite is at least as important
|
||||
as the compiler code itself.
|
||||
|
||||
|
||||
+5
-15
@@ -17,7 +17,7 @@
|
||||
* 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 $"
|
||||
#ident "$Id: Statement.cc,v 1.29 2004/02/18 17:11:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -107,22 +107,16 @@ PBlock::~PBlock()
|
||||
delete list_[idx];
|
||||
}
|
||||
|
||||
PCallTask::PCallTask(const pform_name_t&n, const svector<PExpr*>&p)
|
||||
PCallTask::PCallTask(const hname_t&n, const svector<PExpr*>&p)
|
||||
: path_(n), parms_(p)
|
||||
{
|
||||
}
|
||||
|
||||
PCallTask::PCallTask(perm_string n, const svector<PExpr*>&p)
|
||||
: parms_(p)
|
||||
{
|
||||
path_.push_back(name_component_t(n));
|
||||
}
|
||||
|
||||
PCallTask::~PCallTask()
|
||||
{
|
||||
}
|
||||
|
||||
const pform_name_t& PCallTask::path() const
|
||||
const hname_t& PCallTask::path() const
|
||||
{
|
||||
return path_;
|
||||
}
|
||||
@@ -184,7 +178,7 @@ PDelayStatement::~PDelayStatement()
|
||||
{
|
||||
}
|
||||
|
||||
PDisable::PDisable(const pform_name_t&sc)
|
||||
PDisable::PDisable(const hname_t&sc)
|
||||
: scope_(sc)
|
||||
{
|
||||
}
|
||||
@@ -279,7 +273,7 @@ PRepeat::~PRepeat()
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
PTrigger::PTrigger(const pform_name_t&e)
|
||||
PTrigger::PTrigger(const hname_t&e)
|
||||
: event_(e)
|
||||
{
|
||||
}
|
||||
@@ -301,10 +295,6 @@ PWhile::~PWhile()
|
||||
|
||||
/*
|
||||
* $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.
|
||||
*
|
||||
|
||||
+15
-29
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: Statement.h,v 1.44 2007/05/24 04:07:11 steve Exp $"
|
||||
#ident "$Id: Statement.h,v 1.40.2.1 2006/07/10 00:21:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -36,7 +36,6 @@ class Design;
|
||||
class NetAssign_;
|
||||
class NetCAssign;
|
||||
class NetDeassign;
|
||||
class NetForce;
|
||||
class NetScope;
|
||||
|
||||
/*
|
||||
@@ -55,8 +54,6 @@ class PProcess : public LineInfo {
|
||||
|
||||
virtual ~PProcess();
|
||||
|
||||
bool elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
Type type() const { return type_; }
|
||||
Statement*statement() { return statement_; }
|
||||
|
||||
@@ -74,12 +71,15 @@ class PProcess : public LineInfo {
|
||||
* fact, the Statement class is abstract and represents all the
|
||||
* possible kinds of statements that exist in Verilog.
|
||||
*/
|
||||
class Statement : public LineInfo {
|
||||
class Statement : public LineInfo, public Attrib {
|
||||
|
||||
public:
|
||||
Statement() { }
|
||||
virtual ~Statement() =0;
|
||||
|
||||
map<perm_string,PExpr*> attributes;
|
||||
|
||||
void dump_attributes(ostream&out, unsigned ind) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void elaborate_scope(Design*des, NetScope*scope) const;
|
||||
@@ -173,11 +173,10 @@ class PBlock : public Statement {
|
||||
class PCallTask : public Statement {
|
||||
|
||||
public:
|
||||
explicit PCallTask(const pform_name_t&n, const svector<PExpr*>&parms);
|
||||
explicit PCallTask(perm_string n, const svector<PExpr*>&parms);
|
||||
explicit PCallTask(const hname_t&n, const svector<PExpr*>&parms);
|
||||
~PCallTask();
|
||||
|
||||
const pform_name_t& path() const;
|
||||
const hname_t& path() const;
|
||||
|
||||
unsigned nparms() const { return parms_.count(); }
|
||||
|
||||
@@ -198,7 +197,7 @@ class PCallTask : public Statement {
|
||||
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
|
||||
NetProc* elaborate_usr(Design*des, NetScope*scope) const;
|
||||
|
||||
pform_name_t path_;
|
||||
hname_t path_;
|
||||
svector<PExpr*> parms_;
|
||||
};
|
||||
|
||||
@@ -297,14 +296,14 @@ class PDelayStatement : public Statement {
|
||||
class PDisable : public Statement {
|
||||
|
||||
public:
|
||||
explicit PDisable(const pform_name_t&sc);
|
||||
explicit PDisable(const hname_t&sc);
|
||||
~PDisable();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
pform_name_t scope_;
|
||||
hname_t scope_;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -349,7 +348,7 @@ class PForce : public Statement {
|
||||
explicit PForce(PExpr*l, PExpr*r);
|
||||
~PForce();
|
||||
|
||||
virtual NetForce* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
@@ -397,7 +396,6 @@ class PNoop : public Statement {
|
||||
|
||||
public:
|
||||
PNoop() { }
|
||||
~PNoop() { }
|
||||
};
|
||||
|
||||
class PRepeat : public Statement {
|
||||
@@ -434,14 +432,14 @@ class PRelease : public Statement {
|
||||
class PTrigger : public Statement {
|
||||
|
||||
public:
|
||||
explicit PTrigger(const pform_name_t&ev);
|
||||
explicit PTrigger(const hname_t&ev);
|
||||
~PTrigger();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
pform_name_t event_;
|
||||
hname_t event_;
|
||||
};
|
||||
|
||||
class PWhile : public Statement {
|
||||
@@ -461,20 +459,8 @@ class PWhile : public Statement {
|
||||
|
||||
/*
|
||||
* $Log: Statement.h,v $
|
||||
* Revision 1.44 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.43 2007/03/05 05:59:10 steve
|
||||
* Handle processes within generate loops.
|
||||
*
|
||||
* Revision 1.42 2005/12/05 21:21:18 steve
|
||||
* Fixes for stubborn compilers.
|
||||
*
|
||||
* Revision 1.41 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
* Revision 1.40.2.1 2006/07/10 00:21:49 steve
|
||||
* Add support for full_case attribute.
|
||||
*
|
||||
* Revision 1.40 2004/02/20 18:53:33 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
|
||||
+5
-2
@@ -17,7 +17,7 @@
|
||||
* 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 $"
|
||||
#ident "$Id: StringHeap.cc,v 1.6.2.1 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "StringHeap.h"
|
||||
@@ -131,7 +131,7 @@ perm_string StringHeapLex::make(const char*text)
|
||||
return perm_string(add(text));
|
||||
}
|
||||
|
||||
perm_string StringHeapLex::make(const string&text)
|
||||
perm_string StringHeapLex::make(const std::string&text)
|
||||
{
|
||||
return perm_string(add(text.c_str()));
|
||||
}
|
||||
@@ -181,6 +181,9 @@ bool operator < (perm_string a, perm_string b)
|
||||
|
||||
/*
|
||||
* $Log: StringHeap.cc,v $
|
||||
* Revision 1.6.2.1 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.6 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
||||
+7
-4
@@ -19,7 +19,7 @@
|
||||
* 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 $"
|
||||
#ident "$Id: StringHeap.h,v 1.5.2.2 2005/08/13 00:45:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -103,7 +103,7 @@ class StringHeapLex : private StringHeap {
|
||||
|
||||
const char*add(const char*);
|
||||
perm_string make(const char*);
|
||||
perm_string make(const string&);
|
||||
perm_string make(const std::string&);
|
||||
|
||||
unsigned add_count() const;
|
||||
unsigned add_hit_count() const;
|
||||
@@ -122,8 +122,11 @@ class StringHeapLex : private StringHeap {
|
||||
|
||||
/*
|
||||
* $Log: StringHeap.h,v $
|
||||
* Revision 1.6 2005/06/14 19:13:43 steve
|
||||
* gcc3/4 compile errors.
|
||||
* Revision 1.5.2.2 2005/08/13 00:45:53 steve
|
||||
* Fix compilation warnings/errors with newer compilers.
|
||||
*
|
||||
* Revision 1.5.2.1 2005/06/14 15:33:54 steve
|
||||
* Fix gcc4 build issues.
|
||||
*
|
||||
* Revision 1.5 2004/02/18 17:11:54 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
|
||||
+3
-6
@@ -19,7 +19,7 @@
|
||||
* 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 $"
|
||||
#ident "$Id: _pli_types.h.in,v 1.7 2003/11/12 02:38:44 steve Exp $"
|
||||
#endif
|
||||
|
||||
# undef HAVE_INTTYPES_H
|
||||
@@ -42,7 +42,7 @@ typedef int32_t PLI_INT32;
|
||||
|
||||
typedef signed short PLI_INT16;
|
||||
typedef unsigned short PLI_UINT16;
|
||||
typedef char PLI_BYTE8;
|
||||
typedef signed char PLI_BYTE8;
|
||||
typedef unsigned char PLI_UBYTE8;
|
||||
|
||||
# define PLI_UINT64_FMT PRIu64
|
||||
@@ -84,15 +84,12 @@ typedef signed int PLI_INT32;
|
||||
typedef unsigned int PLI_UINT32;
|
||||
typedef signed short PLI_INT16;
|
||||
typedef unsigned short PLI_UINT16;
|
||||
typedef char PLI_BYTE8;
|
||||
typedef signed 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.
|
||||
*
|
||||
|
||||
Vendored
+7
-11
@@ -14,7 +14,7 @@
|
||||
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 $"
|
||||
#ident "$Id: aclocal.m4,v 1.6.2.2 2007/05/16 23:51:42 steve Exp $"
|
||||
],[while (0) {}],
|
||||
[AS_VAR_SET(ax_cv_cpp_ident, yes)],
|
||||
[AS_VAR_SET(ax_cv_cpp_ident, no)])])
|
||||
@@ -91,13 +91,9 @@ AC_MSG_RESULT($WIN32)
|
||||
AC_DEFUN([AX_LD_EXTRALIBS],
|
||||
[AC_MSG_CHECKING([for extra libs needed])
|
||||
EXTRALIBS=
|
||||
case "${host}" in
|
||||
*-*-cygwin* )
|
||||
if test "$MINGW32" = "yes"; then
|
||||
EXTRALIBS="-liberty"
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
if test "$MINGW32" = "yes"; then
|
||||
EXTRALIBS="-liberty"
|
||||
fi
|
||||
AC_SUBST(EXTRALIBS)
|
||||
AC_MSG_RESULT($EXTRALIBS)
|
||||
])# AX_LD_EXTRALIBS
|
||||
@@ -109,7 +105,7 @@ AC_DEFUN([AX_LD_SHAREDLIB_OPTS],
|
||||
[AC_MSG_CHECKING([for shared library link flag])
|
||||
shared=-shared
|
||||
case "${host}" in
|
||||
*-*-cygwin*)
|
||||
*-*-cygwin* | *-*-mingw32*)
|
||||
shared="-shared -Wl,--enable-auto-image-base"
|
||||
;;
|
||||
|
||||
@@ -138,7 +134,7 @@ AC_DEFUN([AX_C_PICFLAG],
|
||||
PICFLAG=-fPIC
|
||||
case "${host}" in
|
||||
|
||||
*-*-cygwin*)
|
||||
*-*-cygwin* | *-*-mingw32*)
|
||||
PICFLAG=
|
||||
;;
|
||||
|
||||
@@ -173,7 +169,7 @@ case "${host}" in
|
||||
rdynamic=""
|
||||
;;
|
||||
|
||||
*-*-cygwin*)
|
||||
*-*-cygwin* | *-*-mingw32*)
|
||||
rdynamic=""
|
||||
;;
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* 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 $"
|
||||
#ident "$Id: async.cc,v 1.7.2.2 2007/05/30 17:48:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -66,6 +66,10 @@ bool NetEvWait::is_asynchronous()
|
||||
|
||||
NexusSet*inputs = statement_->nex_input();
|
||||
|
||||
/* All the inputs of the statement must be accounted for in
|
||||
the sensitivity list. Otherwise, there are inputs that can
|
||||
change without the event being triggered, and that implies
|
||||
a latch, not a combinational circuit. */
|
||||
if (! sense->contains(*inputs)) {
|
||||
delete sense;
|
||||
delete inputs;
|
||||
@@ -85,7 +89,7 @@ bool NetProc::is_asynchronous()
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NetProcTop::is_asynchronous()
|
||||
bool NetProcTop::is_asynchronous() const
|
||||
{
|
||||
if (type_ == NetProcTop::KINITIAL)
|
||||
return false;
|
||||
@@ -95,6 +99,12 @@ bool NetProcTop::is_asynchronous()
|
||||
|
||||
/*
|
||||
* $Log: async.cc,v $
|
||||
* Revision 1.7.2.2 2007/05/30 17:48:53 steve
|
||||
* Support Latch synthesis (Alan Feldstein)
|
||||
*
|
||||
* Revision 1.7.2.1 2006/05/21 21:58:46 steve
|
||||
* NetESignal input is only selected bits.
|
||||
*
|
||||
* Revision 1.7 2004/01/18 23:26:54 steve
|
||||
* The is_combinational function really need not recurse.
|
||||
*
|
||||
|
||||
@@ -70,6 +70,14 @@ warning.)
|
||||
|
||||
* Other Attributes
|
||||
|
||||
(* ivl_full_case *)
|
||||
|
||||
This attribute only has meaning when attached to case statements,
|
||||
and only when doing synthesis. The statement means to ignore the
|
||||
possibility that some cases are not defined. Presume that the
|
||||
device really is fully specified and do not emit any warnings
|
||||
about missing guards.
|
||||
|
||||
[ none defined yet ]
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -7,9 +7,9 @@
|
||||
# to just run this script to autoconf wherever needed.
|
||||
#
|
||||
echo "Autoconf in root..."
|
||||
autoconf -f
|
||||
autoconf
|
||||
|
||||
for dir in vpip vpi vvp tgt-vvp tgt-fpga tgt-stub libveriuser cadpli
|
||||
for dir in vpip vpi vvp tgt-vvp tgt-edif tgt-fpga libveriuser cadpli
|
||||
do
|
||||
echo "Autoconf in $dir..."
|
||||
( cd ./$dir ; autoconf -f --include=.. )
|
||||
|
||||
+7
-5
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.13 2007/02/06 05:07:31 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.11.2.1 2005/02/23 18:40:23 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -35,6 +35,8 @@ includedir = $(prefix)/include
|
||||
|
||||
vpidir = @libdir@/ivl/@vpidir1@
|
||||
|
||||
strip_dynamic=@strip_dynamic@
|
||||
|
||||
CC = @CC@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
@@ -43,6 +45,7 @@ INSTALL_DATA = @INSTALL_DATA@
|
||||
CPPFLAGS = @ident_support@ -I$(srcdir) -I$(srcdir)/.. -I.. @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
STRIP = @STRIP@
|
||||
|
||||
SHARED = @shared@
|
||||
|
||||
@@ -52,7 +55,7 @@ ifeq (@enable_vvp32@,yes)
|
||||
vpidir32 = $(libdir)/ivl/@vpidir2@
|
||||
ALL32 = all32
|
||||
INSTALL32 = install32
|
||||
UNINSTALL32 = uninstall32
|
||||
UNINSTALL32 = uninistall32
|
||||
include $(srcdir)/enable_vvp32.mk
|
||||
endif
|
||||
|
||||
@@ -71,7 +74,7 @@ dep:
|
||||
O = cadpli.o
|
||||
|
||||
SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi
|
||||
ifeq (@MING32@,yes)
|
||||
ifeq (@WIN32@,yes)
|
||||
SYSTEM_VPI_LDFLAGS += @EXTRALIBS@
|
||||
endif
|
||||
|
||||
@@ -83,6 +86,7 @@ clean:
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache
|
||||
rm -rf autom4te.cache
|
||||
|
||||
install: all installdirs $(vpidir)/cadpli.vpl $(INSTALL32)
|
||||
|
||||
@@ -95,8 +99,6 @@ installdirs: ../mkinstalldirs
|
||||
uninstall: $(UNINSTALL32)
|
||||
rm -f $(vpidir)/cadpli.vpl
|
||||
|
||||
uninstall32:
|
||||
|
||||
ifeq (@enable_vvp32@,yes)
|
||||
include $(srcdir)/enable_vvp32.mk
|
||||
endif
|
||||
|
||||
+21
-44
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: compiler.h,v 1.33 2007/04/19 02:52:53 steve Exp $"
|
||||
#ident "$Id: compiler.h,v 1.26.2.3 2006/06/12 00:16:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
@@ -32,8 +32,11 @@
|
||||
*/
|
||||
|
||||
|
||||
/* The integer_width is the width of integer variables. */
|
||||
extern unsigned integer_width;
|
||||
/* The INTEGER_WIDTH is the default width of integer variables, and
|
||||
the presumed width of unsigned literal numbers. */
|
||||
#ifndef INTEGER_WIDTH
|
||||
# define INTEGER_WIDTH 32
|
||||
#endif
|
||||
|
||||
/* The TIME_WIDTH is the width of time variables. */
|
||||
#ifndef TIME_WIDTH
|
||||
@@ -75,13 +78,17 @@ extern bool warn_timescale;
|
||||
/* Warn about legal but questionable module port bindings. */
|
||||
extern bool warn_portbinding;
|
||||
|
||||
/* Warn about unused or unassigned variables. */
|
||||
extern bool warn_unused;
|
||||
|
||||
/* This is true if verbose output is requested. */
|
||||
extern bool verbose_flag;
|
||||
|
||||
extern bool debug_scopes;
|
||||
extern bool debug_eval_tree;
|
||||
extern bool debug_elaborate;
|
||||
extern bool debug_synth2;
|
||||
extern bool debug_synth;
|
||||
extern bool debug_cprop;
|
||||
|
||||
/* Path to a directory useful for finding subcomponents. */
|
||||
extern const char*basedir;
|
||||
@@ -91,46 +98,28 @@ extern list<const char*>library_suff;
|
||||
extern int build_library_index(const char*path, bool key_case_sensitive);
|
||||
|
||||
/* This is the generation of Verilog that the compiler is asked to
|
||||
support. Then there are also more detailed controls for more
|
||||
specific language features. */
|
||||
support. */
|
||||
enum generation_t {
|
||||
GN_VER1995 = 1,
|
||||
GN_VER2001 = 2,
|
||||
GN_VER2001X = 3,
|
||||
GN_SYSVER30 = 3,
|
||||
GN_DEFAULT = 3
|
||||
};
|
||||
|
||||
extern generation_t generation_flag;
|
||||
|
||||
extern bool gn_cadence_types_flag;
|
||||
|
||||
/* These functions test that specific features are enabled. */
|
||||
inline bool gn_cadence_types_enabled()
|
||||
{ return gn_cadence_types_flag && generation_flag==GN_VER2001X; }
|
||||
|
||||
/* If this flag is true, then elaborate specify blocks. If this flag
|
||||
is false, then skip elaboration of specify behavior. */
|
||||
extern bool gn_specify_blocks_flag;
|
||||
|
||||
/* This is the string to use to invoke the preprocessor. */
|
||||
extern char*ivlpp_string;
|
||||
|
||||
extern map<perm_string,unsigned> missing_modules;
|
||||
|
||||
/* Files that are library files are in this map. The lexor compares
|
||||
file names as it processes `line directives, and if the file name
|
||||
matches an entry in this table, it will turn on the
|
||||
library_active_flag so that modules know that they are in a
|
||||
library. */
|
||||
extern map<string,bool> library_file_map;
|
||||
|
||||
/*
|
||||
* the lex_strings are perm_strings made up of tokens from the source
|
||||
* file. Identifiers are so likely to be used many times that it makes
|
||||
* much sense to use a StringHeapLex to hold them.
|
||||
*/
|
||||
extern StringHeapLex lex_strings;
|
||||
extern StringHeap misc_strings;
|
||||
|
||||
|
||||
/*
|
||||
* system task/function listings.
|
||||
@@ -142,7 +131,7 @@ extern StringHeap misc_strings;
|
||||
*/
|
||||
struct sfunc_return_type {
|
||||
const char* name;
|
||||
ivl_variable_type_t type;
|
||||
NetExpr::TYPE type;
|
||||
unsigned wid;
|
||||
int signed_flag;
|
||||
};
|
||||
@@ -152,26 +141,14 @@ extern int load_sys_func_table(const char*path);
|
||||
|
||||
/*
|
||||
* $Log: compiler.h,v $
|
||||
* Revision 1.33 2007/04/19 02:52:53 steve
|
||||
* Add support for -v flag in command file.
|
||||
* Revision 1.26.2.3 2006/06/12 00:16:50 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.32 2007/03/07 04:24:59 steve
|
||||
* Make integer width controllable.
|
||||
* Revision 1.26.2.2 2006/04/23 04:25:45 steve
|
||||
* Add cprop debugging.
|
||||
*
|
||||
* Revision 1.31 2006/09/28 04:35:18 steve
|
||||
* Support selective control of specify and xtypes features.
|
||||
*
|
||||
* Revision 1.30 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.29 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.28 2005/06/28 04:25:55 steve
|
||||
* Remove reference to SystemVerilog.
|
||||
*
|
||||
* Revision 1.27 2005/04/24 23:44:01 steve
|
||||
* Update DFF support to new data flow.
|
||||
* Revision 1.26.2.1 2006/04/01 01:37:24 steve
|
||||
* Add synth debug flag
|
||||
*
|
||||
* Revision 1.26 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
|
||||
+1
-9
@@ -19,7 +19,7 @@
|
||||
* 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 $"
|
||||
#ident "$Id: config.h.in,v 1.11 2004/10/04 01:10:52 steve Exp $"
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
@@ -37,7 +37,6 @@
|
||||
# undef HAVE_TIMES
|
||||
# undef HAVE_IOSFWD
|
||||
# undef HAVE_GETOPT_H
|
||||
# undef HAVE_INTTYPES_H
|
||||
# undef HAVE_LIBIBERTY_H
|
||||
# undef HAVE_MALLOC_H
|
||||
# undef HAVE_DLFCN_H
|
||||
@@ -49,15 +48,8 @@
|
||||
# undef HAVE_SYS_WAIT_H
|
||||
# undef WORDS_BIGENDIAN
|
||||
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
# include <inttypes.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $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.
|
||||
*
|
||||
|
||||
+5
-3
@@ -9,6 +9,9 @@ AC_PROG_CC
|
||||
AC_PROG_CXX
|
||||
AC_CHECK_TOOL(STRIP, strip, true)
|
||||
AC_CHECK_PROGS(XGPERF,gperf,none)
|
||||
AC_CHECK_PROGS(MAN,man,none)
|
||||
AC_CHECK_PROGS(PS2PDF,ps2pdf,none)
|
||||
|
||||
if test "$XGPERF" = "none"
|
||||
then
|
||||
echo ""
|
||||
@@ -141,7 +144,6 @@ AC_SUBST(vpidir1)
|
||||
AC_SUBST(vpidir2)
|
||||
AC_MSG_RESULT(${vpidir1} ${vpidir2})
|
||||
|
||||
# XXX disable tgt-fpga for the moment
|
||||
AC_CONFIG_SUBDIRS(vvp vpi tgt-stub tgt-null tgt-vvp libveriuser cadpli)
|
||||
AC_CONFIG_SUBDIRS(vvp vpi tgt-vvp tgt-edif tgt-fpga libveriuser cadpli)
|
||||
|
||||
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
|
||||
AC_OUTPUT(Makefile ivlpp/Makefile driver/Makefile driver-vpi/Makefile tgt-null/Makefile tgt-stub/Makefile tgt-verilog/Makefile tgt-pal/Makefile)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2005 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-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
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: cprop.cc,v 1.56 2007/03/07 00:38:15 steve Exp $"
|
||||
#ident "$Id: cprop.cc,v 1.47.2.7 2007/02/26 19:51:38 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -25,6 +25,7 @@
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "functor.h"
|
||||
# include "compiler.h"
|
||||
# include <assert.h>
|
||||
|
||||
|
||||
@@ -47,6 +48,9 @@ struct cprop_functor : public functor_t {
|
||||
virtual void lpm_ff(Design*des, NetFF*obj);
|
||||
virtual void lpm_logic(Design*des, NetLogic*obj);
|
||||
virtual void lpm_mux(Design*des, NetMux*obj);
|
||||
virtual void lpm_mux_large(Design*des, NetMux*obj);
|
||||
virtual void lpm_ram_dq(Design*des, NetRamDq*obj);
|
||||
bool lpm_ram_dq_const_address_(Design*des, NetRamDq*obj);
|
||||
};
|
||||
|
||||
void cprop_functor::signal(Design*des, NetNet*obj)
|
||||
@@ -55,6 +59,86 @@ void cprop_functor::signal(Design*des, NetNet*obj)
|
||||
|
||||
void cprop_functor::lpm_add_sub(Design*des, NetAddSub*obj)
|
||||
{
|
||||
// For now, only additions are handled.
|
||||
if (obj->attribute(perm_string::literal("LPM_Direction")) != verinum("ADD"))
|
||||
return;
|
||||
|
||||
// If the low bit on the A side is 0, then eliminate it from
|
||||
// the adder, and pass the B side directly to the
|
||||
// result. Don't reduce the adder smaller then a 1-bit
|
||||
// adder. These will be eliminated later.
|
||||
while ((obj->width() > 1)
|
||||
&& obj->pin_DataA(0).nexus()->drivers_constant()
|
||||
&& (obj->pin_DataA(0).nexus()->driven_value() == verinum::V0)) {
|
||||
|
||||
NetAddSub*tmp = 0;
|
||||
tmp = new NetAddSub(obj->scope(), obj->name(), obj->width()-1);
|
||||
//connect(tmp->pin_Aclr(), obj->pin_Aclr());
|
||||
//connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub());
|
||||
//connect(tmp->pin_Clock(), obj->pin_Clock());
|
||||
//connect(tmp->pin_Cin(), obj->pin_Cin());
|
||||
connect(tmp->pin_Cout(), obj->pin_Cout());
|
||||
//connect(tmp->pin_Overflow(), obj->pin_Overflow());
|
||||
for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) {
|
||||
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1));
|
||||
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1));
|
||||
connect(tmp->pin_Result(idx), obj->pin_Result(idx+1));
|
||||
}
|
||||
connect(obj->pin_Result(0), obj->pin_DataB(0));
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
obj = tmp;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
// Now do the same thing on the B side.
|
||||
while ((obj->width() > 1)
|
||||
&& obj->pin_DataB(0).nexus()->drivers_constant()
|
||||
&& (obj->pin_DataB(0).nexus()->driven_value() == verinum::V0)) {
|
||||
|
||||
NetAddSub*tmp = 0;
|
||||
tmp = new NetAddSub(obj->scope(), obj->name(), obj->width()-1);
|
||||
//connect(tmp->pin_Aclr(), obj->pin_Aclr());
|
||||
//connect(tmp->pin_Add_Sub(), obj->pin_Add_Sub());
|
||||
//connect(tmp->pin_Clock(), obj->pin_Clock());
|
||||
//connect(tmp->pin_Cin(), obj->pin_Cin());
|
||||
connect(tmp->pin_Cout(), obj->pin_Cout());
|
||||
//connect(tmp->pin_Overflow(), obj->pin_Overflow());
|
||||
for (unsigned idx = 0 ; idx < tmp->width() ; idx += 1) {
|
||||
connect(tmp->pin_DataA(idx), obj->pin_DataA(idx+1));
|
||||
connect(tmp->pin_DataB(idx), obj->pin_DataB(idx+1));
|
||||
connect(tmp->pin_Result(idx), obj->pin_Result(idx+1));
|
||||
}
|
||||
connect(obj->pin_Result(0), obj->pin_DataA(0));
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
obj = tmp;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
// If the adder is only 1 bit wide, then replace it with the
|
||||
// simple logic gate.
|
||||
if (obj->width() == 1) {
|
||||
NetLogic*tmp;
|
||||
if (obj->pin_Cout().is_linked()) {
|
||||
tmp = new NetLogic(obj->scope(),
|
||||
obj->scope()->local_symbol(),
|
||||
3, NetLogic::AND);
|
||||
connect(tmp->pin(0), obj->pin_Cout());
|
||||
connect(tmp->pin(1), obj->pin_DataA(0));
|
||||
connect(tmp->pin(2), obj->pin_DataB(0));
|
||||
des->add_node(tmp);
|
||||
}
|
||||
tmp = new NetLogic(obj->scope(), obj->name(), 3, NetLogic::XOR);
|
||||
connect(tmp->pin(0), obj->pin_Result(0));
|
||||
connect(tmp->pin(1), obj->pin_DataA(0));
|
||||
connect(tmp->pin(2), obj->pin_DataB(0));
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_compare(Design*des, NetCompare*obj)
|
||||
@@ -73,8 +157,6 @@ void cprop_functor::lpm_compare(Design*des, NetCompare*obj)
|
||||
|
||||
void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
|
||||
{
|
||||
#if 0
|
||||
/* XXXX Need to reimplement this code to account for vectors. */
|
||||
NetScope*scope = obj->scope();
|
||||
|
||||
unsigned const_count = 0;
|
||||
@@ -170,7 +252,7 @@ void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
|
||||
with a simple XOR gate. */
|
||||
if (top == 1) {
|
||||
NetLogic*tmp = new NetLogic(scope, obj->name(), 3,
|
||||
NetLogic::XNOR, 1);
|
||||
NetLogic::XNOR);
|
||||
connect(tmp->pin(0), obj->pin_AEB());
|
||||
connect(tmp->pin(1), obj->pin_DataA(0));
|
||||
connect(tmp->pin(2), obj->pin_DataB(0));
|
||||
@@ -193,7 +275,6 @@ void cprop_functor::lpm_compare_eq_(Design*des, NetCompare*obj)
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
count += 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_ff(Design*des, NetFF*obj)
|
||||
@@ -201,30 +282,63 @@ void cprop_functor::lpm_ff(Design*des, NetFF*obj)
|
||||
// Look for and count unlinked FF outputs. Note that if the
|
||||
// Data and Q pins are connected together, they can be removed
|
||||
// from the circuit, since it doesn't do anything.
|
||||
unsigned unlinked_count = 0;
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
if (connected(obj->pin_Data(idx), obj->pin_Q(idx))
|
||||
&& (! obj->pin_Sclr().is_linked())
|
||||
&& (! obj->pin_Sset().is_linked())
|
||||
&& (! obj->pin_Aclr().is_linked())
|
||||
&& (! obj->pin_Aset().is_linked())) {
|
||||
obj->pin_Data(idx).unlink();
|
||||
obj->pin_Q(idx).unlink();
|
||||
}
|
||||
if (! obj->pin_Q(idx).is_linked())
|
||||
unlinked_count += 1;
|
||||
}
|
||||
|
||||
if (connected(obj->pin_Data(), obj->pin_Q())
|
||||
&& (! obj->pin_Sclr().is_linked())
|
||||
&& (! obj->pin_Sset().is_linked())
|
||||
&& (! obj->pin_Aclr().is_linked())
|
||||
&& (! obj->pin_Aset().is_linked())) {
|
||||
obj->pin_Data().unlink();
|
||||
obj->pin_Q().unlink();
|
||||
// If the entire FF is unlinked, remove the whole thing.
|
||||
if (unlinked_count == obj->width()) {
|
||||
delete obj;
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// If some of the FFs are unconnected, make a new FF array
|
||||
// that does not include the useless FF devices.
|
||||
if (unlinked_count > 0) {
|
||||
NetFF*tmp = new NetFF(obj->scope(), obj->name(),
|
||||
obj->width()-unlinked_count);
|
||||
connect(tmp->pin_Clock(), obj->pin_Clock());
|
||||
connect(tmp->pin_Enable(), obj->pin_Enable());
|
||||
connect(tmp->pin_Aload(), obj->pin_Aload());
|
||||
connect(tmp->pin_Aset(), obj->pin_Aset());
|
||||
connect(tmp->pin_Aclr(), obj->pin_Aclr());
|
||||
connect(tmp->pin_Sload(), obj->pin_Sload());
|
||||
connect(tmp->pin_Sset(), obj->pin_Sset());
|
||||
connect(tmp->pin_Sclr(), obj->pin_Sclr());
|
||||
|
||||
unsigned tidx = 0;
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1)
|
||||
if (obj->pin_Q(idx).is_linked()) {
|
||||
connect(tmp->pin_Data(tidx), obj->pin_Data(idx));
|
||||
connect(tmp->pin_Q(tidx), obj->pin_Q(idx));
|
||||
tidx += 1;
|
||||
}
|
||||
|
||||
assert(tidx == obj->width() - unlinked_count);
|
||||
delete obj;
|
||||
des->add_node(tmp);
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
{
|
||||
#if 0
|
||||
NetScope*scope = obj->scope();
|
||||
#endif
|
||||
|
||||
switch (obj->type()) {
|
||||
#if 0
|
||||
/* XXXX This old code assumed that the individual bit
|
||||
slices could be replaced with different gates. They
|
||||
cannot when the device takes atomic vectors, so this
|
||||
needs to be rewritten. XXXX */
|
||||
|
||||
case NetLogic::NAND:
|
||||
case NetLogic::AND: {
|
||||
unsigned top = obj->pin_count();
|
||||
@@ -339,12 +453,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
case NetLogic::AND:
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::BUF, 1);
|
||||
NetLogic::BUF);
|
||||
break;
|
||||
case NetLogic::NAND:
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::NOT, 1);
|
||||
NetLogic::NOT);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
@@ -370,7 +484,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
if (top < obj->pin_count()) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
obj->name(), top,
|
||||
obj->type(), 1);
|
||||
obj->type());
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
@@ -387,12 +501,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
/* XXXX This old code assumed that the individual bit
|
||||
slices could be replaced with different gates. They
|
||||
cannot when the device takes atomic vectors, so this
|
||||
needs to be rewritten. XXXX */
|
||||
|
||||
|
||||
case NetLogic::NOR:
|
||||
case NetLogic::OR: {
|
||||
@@ -492,12 +601,12 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
case NetLogic::OR:
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::BUF, 1);
|
||||
NetLogic::BUF);
|
||||
break;
|
||||
case NetLogic::NOR:
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::NOT, 1);
|
||||
NetLogic::NOT);
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
@@ -514,7 +623,7 @@ void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
delete obj;
|
||||
count += 1;
|
||||
return;
|
||||
v }
|
||||
}
|
||||
|
||||
/* Finally, this cleans up the gate by creating a
|
||||
new [N]OR gate that has the right number of
|
||||
@@ -522,7 +631,7 @@ v }
|
||||
if (top < obj->pin_count()) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
obj->name(), top,
|
||||
obj->type(), 1);
|
||||
obj->type());
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
tmp->decay_time(obj->decay_time());
|
||||
@@ -539,12 +648,7 @@ v }
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
/* XXXX This old code assumed that the individual bit
|
||||
slices could be replaced with different gates. They
|
||||
cannot when the device takes atomic vectors, so this
|
||||
needs to be rewritten. XXXX */
|
||||
|
||||
case NetLogic::XNOR:
|
||||
case NetLogic::XOR: {
|
||||
unsigned top = obj->pin_count();
|
||||
@@ -666,11 +770,11 @@ v }
|
||||
if (obj->type() == NetLogic::XOR)
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::NOT, 1);
|
||||
NetLogic::NOT);
|
||||
else
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::BUF, 1);
|
||||
NetLogic::BUF);
|
||||
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
@@ -695,11 +799,11 @@ v }
|
||||
if (obj->type() == NetLogic::XOR)
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::BUF, 1);
|
||||
NetLogic::BUF);
|
||||
else
|
||||
tmp = new NetLogic(scope,
|
||||
obj->name(), 2,
|
||||
NetLogic::NOT, 1);
|
||||
NetLogic::NOT);
|
||||
|
||||
tmp->rise_time(obj->rise_time());
|
||||
tmp->fall_time(obj->fall_time());
|
||||
@@ -721,7 +825,7 @@ v }
|
||||
if (top < obj->pin_count()) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
obj->name(), top,
|
||||
obj->type(), 1);
|
||||
obj->type());
|
||||
des->add_node(tmp);
|
||||
tmp->pin(0).drive0(obj->pin(0).drive0());
|
||||
tmp->pin(0).drive1(obj->pin(0).drive1());
|
||||
@@ -734,54 +838,12 @@ v }
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
|
||||
{
|
||||
NetScope*scope = obj->scope();
|
||||
NetLogic*tmp = new NetLogic(obj->scope(),
|
||||
scope->local_symbol(),
|
||||
3, type, obj->width());
|
||||
|
||||
des->add_node(tmp);
|
||||
|
||||
connect(obj->pin_Result(), tmp->pin(0));
|
||||
connect(obj->pin_Data(type==NetLogic::BUFIF0? 0 : 1), tmp->pin(1));
|
||||
|
||||
if (obj->width() == 1) {
|
||||
/* Special case that the expression is 1 bit
|
||||
wide. Connect the select directly to the enable. */
|
||||
connect(obj->pin_Sel(), tmp->pin(2));
|
||||
|
||||
} else {
|
||||
/* General case that the expression is arbitrarily
|
||||
wide. Replicate the enable signal (which we
|
||||
assume is 1 bit wide) to match the expression,
|
||||
and connect the enable vector to the enable
|
||||
input of the gate. */
|
||||
NetReplicate*rtmp = new NetReplicate(scope,
|
||||
scope->local_symbol(),
|
||||
obj->width(),
|
||||
obj->width());
|
||||
des->add_node(rtmp);
|
||||
|
||||
connect(obj->pin_Sel(), rtmp->pin(1));
|
||||
connect(tmp->pin(2), rtmp->pin(0));
|
||||
|
||||
NetNet*rsig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, obj->width());
|
||||
rsig->local_flag(true);
|
||||
rsig->data_type(IVL_VT_LOGIC);
|
||||
connect(tmp->pin(2), rsig->pin(0));
|
||||
}
|
||||
|
||||
delete obj;
|
||||
}
|
||||
|
||||
/*
|
||||
* This detects the case where the mux selects between a value and
|
||||
* Vz. In this case, replace the device with a bufif with the sel
|
||||
@@ -789,49 +851,373 @@ static void replace_with_bufif(Design*des, NetMux*obj, NetLogic::TYPE type)
|
||||
*/
|
||||
void cprop_functor::lpm_mux(Design*des, NetMux*obj)
|
||||
{
|
||||
if (obj->size() > 2) {
|
||||
lpm_mux_large(des, obj);
|
||||
return;
|
||||
}
|
||||
if (obj->size() != 2)
|
||||
return;
|
||||
if (obj->sel_width() != 1)
|
||||
return;
|
||||
|
||||
/* If the first input is all constant Vz, then replace the
|
||||
NetMux with an array of BUFIF1 devices, with the enable
|
||||
connected to the select input. */
|
||||
NetScope*scope = obj->scope();
|
||||
|
||||
bool flag = true;
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
bool cflag_a = obj->pin_Data(idx, 0).nexus()->drivers_constant();
|
||||
bool cflag_b = obj->pin_Data(idx, 1).nexus()->drivers_constant();
|
||||
|
||||
if (! obj->pin_Data(0).nexus()->drivers_constant()) {
|
||||
/* If both data inputs are constant, we'll be able to do
|
||||
a substitution. */
|
||||
if (cflag_a && cflag_b)
|
||||
continue;
|
||||
|
||||
verinum::V va = cflag_a
|
||||
? obj->pin_Data(idx, 0).nexus()->driven_value()
|
||||
: verinum::Vx;
|
||||
verinum::V vb = cflag_b
|
||||
? obj->pin_Data(idx, 1).nexus()->driven_value()
|
||||
: verinum::Vx;
|
||||
|
||||
/* If only one Data input is constant, but a constant
|
||||
HiZ, then we will be able to to a bufif
|
||||
substitution. */
|
||||
if (cflag_a && va==verinum::Vz)
|
||||
continue;
|
||||
|
||||
if (cflag_b && vb==verinum::Vz)
|
||||
continue;
|
||||
|
||||
/* Otherwise, we cannot accurately do a substitution. If
|
||||
one input is non-constant, then that input may have a
|
||||
HiZ value, and there is no Verilog logic other then a
|
||||
MUX that can pass a HiZ value. */
|
||||
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;
|
||||
if (! flag) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create a temporary net to hold the result value that we
|
||||
build up. When we are done, we will connect this to the
|
||||
Result pins of the mux, then delete the mux *and* this
|
||||
net. That will cause all the proper connectivity to
|
||||
happen. */
|
||||
NetNet result_tmp(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, obj->width());
|
||||
|
||||
/* We know that every slice has at least one constant. Run
|
||||
through the slices again, creating boolean devices to
|
||||
replace the MUX slice. */
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1) {
|
||||
|
||||
/* If the Sel==0 input is constant Z, make a bufif1. */
|
||||
if (obj->pin_Data(idx, 0).nexus()->drivers_constant()
|
||||
&& obj->pin_Data(idx, 0).nexus()->driven_value()==verinum::Vz) {
|
||||
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::BUFIF1);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,1), tmp->pin(1));
|
||||
connect(obj->pin_Sel(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If the Sel==1 input is constant Z, make a bufif0. */
|
||||
if (obj->pin_Data(idx, 1).nexus()->drivers_constant()
|
||||
&& obj->pin_Data(idx, 1).nexus()->driven_value()==verinum::Vz) {
|
||||
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::BUFIF0);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,0), tmp->pin(1));
|
||||
connect(obj->pin_Sel(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* At this point, the only cases that are left are where
|
||||
the data inputs are both constant, and neither are
|
||||
HiZ. From this we know how to generate the output
|
||||
from only the S input. */
|
||||
if (! (obj->pin_Data(idx, 0).nexus()->drivers_constant()
|
||||
&& obj->pin_Data(idx, 1).nexus()->drivers_constant())) {
|
||||
cerr << obj->get_line() << ": internal error: "
|
||||
<< "Drivers not constant where expected?"
|
||||
<< " obj->width()=" << obj->width()
|
||||
<< " idx=" << idx
|
||||
<< endl;
|
||||
obj->dump_node(cerr, 4);
|
||||
}
|
||||
assert(obj->pin_Data(idx, 0).nexus()->drivers_constant()
|
||||
&& obj->pin_Data(idx, 1).nexus()->drivers_constant());
|
||||
|
||||
|
||||
verinum::V a = obj->pin_Data(idx, 0).nexus()->driven_value();
|
||||
verinum::V b = obj->pin_Data(idx, 1).nexus()->driven_value();
|
||||
|
||||
if (a == b) {
|
||||
connect(result_tmp.pin(idx), obj->pin_Data(idx,0));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (a == verinum::V0 && b == verinum::V1) {
|
||||
connect(result_tmp.pin(idx), obj->pin_Sel(0));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (a == verinum::V1 && b == verinum::V0) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
2, NetLogic::NOT);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Sel(0), tmp->pin(1));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* A==0: Q = B & S */
|
||||
if (a == verinum::V0) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::AND);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,1), tmp->pin(1));
|
||||
connect(obj->pin_Sel(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* B==1: Q = A | S */
|
||||
if (b == verinum::V1) {
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::OR);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,0), tmp->pin(1));
|
||||
connect(obj->pin_Sel(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
/* A==1: Q = B | ~S */
|
||||
if (a == verinum::V1) {
|
||||
NetLogic*inv = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
2, NetLogic::NOT);
|
||||
NetNet*invs = new NetNet(scope,
|
||||
scope->local_symbol(),
|
||||
NetNet::TRI, 1);
|
||||
invs->local_flag(true);
|
||||
connect(inv->pin(0), invs->pin(0));
|
||||
connect(inv->pin(1), obj->pin_Sel(0));
|
||||
des->add_node(inv);
|
||||
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::OR);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,1), tmp->pin(1));
|
||||
connect(inv->pin(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
/* B==0: Q = A & ~S */
|
||||
if (b == verinum::V0) {
|
||||
NetLogic*inv = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
2, NetLogic::NOT);
|
||||
NetNet*invs = new NetNet(scope,
|
||||
scope->local_symbol(),
|
||||
NetNet::TRI, 1);
|
||||
invs->local_flag(true);
|
||||
connect(inv->pin(0), invs->pin(0));
|
||||
connect(inv->pin(1), obj->pin_Sel(0));
|
||||
des->add_node(inv);
|
||||
|
||||
NetLogic*tmp = new NetLogic(scope,
|
||||
scope->local_symbol(),
|
||||
3, NetLogic::AND);
|
||||
connect(result_tmp.pin(idx), tmp->pin(0));
|
||||
connect(obj->pin_Data(idx,0), tmp->pin(1));
|
||||
connect(inv->pin(0), tmp->pin(2));
|
||||
des->add_node(tmp);
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(0);
|
||||
|
||||
/* If instead the second input is all constant Vz, replace the
|
||||
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;
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1)
|
||||
connect(result_tmp.pin(idx), obj->pin_Result(idx));
|
||||
|
||||
if (flag) {
|
||||
replace_with_bufif(des, obj, NetLogic::BUFIF0);
|
||||
count += 1;
|
||||
return;
|
||||
}
|
||||
delete obj;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_mux_large(Design*des, NetMux*obj)
|
||||
{
|
||||
NetScope*scope = obj->scope();
|
||||
unsigned width = obj->width();
|
||||
unsigned size = obj->size();
|
||||
|
||||
/* This test looks for bit slices that are constant
|
||||
throughout. If we find any, we can reduce the width of the
|
||||
MUX to eliminate the fixed value. */
|
||||
|
||||
/* After the following for loop, this array of bools will
|
||||
contain "true" for each bit slice that is constant and
|
||||
identical, and "false" otherwise. The reduce_width will
|
||||
count the number of true entries in the flags array. */
|
||||
bool*flags = new bool[width];
|
||||
unsigned reduce_width = 0;
|
||||
|
||||
for (unsigned bit = 0 ; bit < width ; bit += 1) {
|
||||
|
||||
flags[bit] = true;
|
||||
|
||||
/* If not even the first selection is constant, then the
|
||||
slice cannot be reduced. */
|
||||
if (! obj->pin_Data(bit, 0).nexus()->drivers_constant()) {
|
||||
flags[bit] = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If any of the remaining selections in non-consant, or
|
||||
constant with a different value, then this slice
|
||||
cannot be reduced. */
|
||||
verinum::V val = obj->pin_Data(bit, 0).nexus()->driven_value();
|
||||
|
||||
for (unsigned idx = 1; flags[bit] && idx < size ; idx += 1) {
|
||||
|
||||
if (!obj->pin_Data(bit,idx).nexus()->drivers_constant()) {
|
||||
flags[bit] = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (val != obj->pin_Data(bit,idx).nexus()->driven_value()) {
|
||||
flags[bit] = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (! flags[bit]) {
|
||||
/* This bit slice is too complex. Go on. */
|
||||
continue;
|
||||
}
|
||||
|
||||
reduce_width += 1;
|
||||
}
|
||||
|
||||
/* If no slices can be reduced, then we are finished. */
|
||||
if (reduce_width == 0) {
|
||||
delete[]flags;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Handle the very special case that all the slices can be
|
||||
reduced. We don't need a MUX at all! */
|
||||
if (reduce_width == width) {
|
||||
for (unsigned idx = 0 ; idx < width ; idx += 1)
|
||||
connect(obj->pin_Result(idx), obj->pin_Data(idx,0));
|
||||
|
||||
delete obj;
|
||||
count += 1;
|
||||
delete[]flags;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create a reduced mux with the same name and size, but fewer
|
||||
slices. Connect all the slices that we are keeping. */
|
||||
NetMux*tmp = new NetMux(scope, obj->name(),
|
||||
width-reduce_width, size, obj->sel_width());
|
||||
tmp->set_line(*obj);
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->sel_width() ; idx += 1)
|
||||
connect(obj->pin_Sel(idx), tmp->pin_Sel(idx));
|
||||
|
||||
unsigned dst_bit = 0;
|
||||
|
||||
for (unsigned bit = 0 ; bit < width ; bit += 1) {
|
||||
if (flags[bit]) {
|
||||
connect(obj->pin_Result(bit), obj->pin_Data(bit,0));
|
||||
continue;
|
||||
}
|
||||
|
||||
connect(obj->pin_Result(bit), tmp->pin_Result(dst_bit));
|
||||
|
||||
for (unsigned idx = 0 ; idx < size ; idx += 1)
|
||||
connect(obj->pin_Data(bit,idx), tmp->pin_Data(dst_bit,idx));
|
||||
|
||||
dst_bit += 1;
|
||||
}
|
||||
|
||||
/* Add the new node. Delete the old node. Signal that we
|
||||
change the design and may use a rescan. */
|
||||
des->add_node(tmp);
|
||||
delete obj;
|
||||
delete[]flags;
|
||||
count += 1;
|
||||
}
|
||||
|
||||
void cprop_functor::lpm_ram_dq(Design*des, NetRamDq*obj)
|
||||
{
|
||||
if (lpm_ram_dq_const_address_(des,obj))
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to evaluate a constant address input. If we find it, then
|
||||
* replace the NetRamDq with a direct link to the addressed word.
|
||||
*/
|
||||
bool cprop_functor::lpm_ram_dq_const_address_(Design*des, NetRamDq*obj)
|
||||
{
|
||||
NetMemory*mem = obj->mem();
|
||||
NetNet* reg = mem->reg_from_explode();
|
||||
|
||||
/* I only know how to do this on exploded memories. */
|
||||
if (reg == 0)
|
||||
return false;
|
||||
|
||||
verinum sel (0UL, obj->awidth());
|
||||
for (unsigned idx = 0 ; idx < obj->awidth() ; idx += 1) {
|
||||
if (! obj->pin_Address(idx).nexus()->drivers_constant())
|
||||
return false;
|
||||
|
||||
sel.set(idx, obj->pin_Address(idx).nexus()->driven_value());
|
||||
}
|
||||
|
||||
unsigned long address = sel.as_ulong();
|
||||
|
||||
/* If the address is outside the ram, then leave this to the
|
||||
code generator to figure out. */
|
||||
if (address >= obj->size())
|
||||
return false;
|
||||
|
||||
|
||||
unsigned base = address * obj->width();
|
||||
assert(base+obj->width() <= reg->pin_count());
|
||||
|
||||
for (unsigned idx = 0 ; idx < obj->width() ; idx += 1)
|
||||
connect(reg->pin(base+idx), obj->pin_Q(idx));
|
||||
|
||||
if (debug_cprop) {
|
||||
cerr << obj->get_line() << ": debug: Replace read port with"
|
||||
<< " fixed link to word " << address << "." << endl;
|
||||
}
|
||||
|
||||
delete obj;
|
||||
count += 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This functor looks to see if the constant is connected to nothing
|
||||
* but signals. If that is the case, delete the dangling constant and
|
||||
@@ -950,36 +1336,23 @@ void cprop(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: cprop.cc,v $
|
||||
* Revision 1.56 2007/03/07 00:38:15 steve
|
||||
* Lint fixes.
|
||||
* Revision 1.47.2.7 2007/02/26 19:51:38 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.55 2006/05/24 04:32:57 steve
|
||||
* Fix handling of ternary-to-bufif0 constant propagation.
|
||||
* Revision 1.47.2.6 2006/11/12 01:20:45 steve
|
||||
* Prevent constant mux outputs from confusing itself.
|
||||
*
|
||||
* Revision 1.54 2005/07/15 19:22:52 steve
|
||||
* bufif enable is LOGIC.
|
||||
* Revision 1.47.2.5 2006/04/23 04:26:13 steve
|
||||
* Constant propagate addresses through NetRamDq read ports.
|
||||
*
|
||||
* Revision 1.53 2005/05/15 04:44:30 steve
|
||||
* Disable obsolete logic constant fixup code.
|
||||
* Revision 1.47.2.4 2005/09/11 02:50:51 steve
|
||||
* Fix overly agressive constant propagation through MUX causing lost Z bits.
|
||||
*
|
||||
* Revision 1.52 2005/04/24 23:44:01 steve
|
||||
* Update DFF support to new data flow.
|
||||
* Revision 1.47.2.3 2005/08/28 22:00:39 steve
|
||||
* Reduce mux slices that are constant throughout range.
|
||||
*
|
||||
* Revision 1.51 2005/02/12 22:52:45 steve
|
||||
* Fix copyright notice.
|
||||
*
|
||||
* Revision 1.50 2005/02/12 06:25:40 steve
|
||||
* Restructure NetMux devices to pass vectors.
|
||||
* Generate NetMux devices from ternary expressions,
|
||||
* Reduce NetMux devices to bufif when appropriate.
|
||||
*
|
||||
* Revision 1.49 2005/01/16 04:20:32 steve
|
||||
* Implement LPM_COMPARE nodes as two-input vector functors.
|
||||
*
|
||||
* Revision 1.48 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
* Revision 1.47.2.2 2005/08/28 19:51:02 steve
|
||||
* More thorough constant propagation through MUX devices.
|
||||
*
|
||||
* Revision 1.47 2004/02/20 18:53:34 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
|
||||
+185
-351
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: design_dump.cc,v 1.176 2007/06/02 03:42:12 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.149.2.7 2006/08/23 04:09:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -29,8 +29,7 @@
|
||||
# include <iostream>
|
||||
# include <iomanip>
|
||||
# include "netlist.h"
|
||||
# include "compiler.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
|
||||
static ostream& operator<< (ostream&o, NetBlock::Type t)
|
||||
{
|
||||
@@ -69,77 +68,13 @@ ostream& operator << (ostream&o, Link::strength_t str)
|
||||
return o;
|
||||
}
|
||||
|
||||
ostream& operator << (ostream&o, ivl_variable_type_t val)
|
||||
{
|
||||
switch (val) {
|
||||
case IVL_VT_VOID:
|
||||
o << "void";
|
||||
break;
|
||||
case IVL_VT_NO_TYPE:
|
||||
o << "<no_type>";
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
o << "real";
|
||||
break;
|
||||
case IVL_VT_BOOL:
|
||||
o << "bool";
|
||||
break;
|
||||
case IVL_VT_LOGIC:
|
||||
o << "logic";
|
||||
break;
|
||||
}
|
||||
return o;
|
||||
}
|
||||
|
||||
static inline void dump_scope_path(ostream&o, const NetScope*scope)
|
||||
{
|
||||
if (const NetScope*parent = scope->parent()) {
|
||||
dump_scope_path(o, parent);
|
||||
o << ".";
|
||||
}
|
||||
const hname_t name = scope->fullname();
|
||||
o << name.peek_name();
|
||||
if (name.has_number())
|
||||
o << "[" << name.peek_number() << "]";
|
||||
}
|
||||
|
||||
ostream& operator <<(ostream&o, struct __ScopePathManip marg)
|
||||
{
|
||||
if (marg.scope != 0)
|
||||
dump_scope_path(o, marg.scope);
|
||||
return o;
|
||||
}
|
||||
|
||||
void NetDelaySrc::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "specify delay";
|
||||
if (posedge_) o << " posedge";
|
||||
if (negedge_) o << " negedge";
|
||||
o << " src "
|
||||
<< "(" << transition_delays_[IVL_PE_01]
|
||||
<< "," << transition_delays_[IVL_PE_10]
|
||||
<< "," << transition_delays_[IVL_PE_0z]
|
||||
<< "/" << transition_delays_[IVL_PE_z1]
|
||||
<< "," << transition_delays_[IVL_PE_1z]
|
||||
<< "," << transition_delays_[IVL_PE_z0]
|
||||
<< "/" << transition_delays_[IVL_PE_0x]
|
||||
<< "," << transition_delays_[IVL_PE_x1]
|
||||
<< "," << transition_delays_[IVL_PE_1x]
|
||||
<< "/" << transition_delays_[IVL_PE_x0]
|
||||
<< "," << transition_delays_[IVL_PE_xz]
|
||||
<< "," << transition_delays_[IVL_PE_zx]
|
||||
<< "): " << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
/* Dump a net. This can be a wire or register. */
|
||||
void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << type() << ": " << name()
|
||||
<< "[" << s0_ << ":" << e0_ << " count=" << pin_count() << "]";
|
||||
o << setw(ind) << "" << type() << ": " << name() << "[" <<
|
||||
pin_count() << "]";
|
||||
if (local_flag_)
|
||||
o << " (local)";
|
||||
o << " " << data_type_;
|
||||
if (signed_)
|
||||
o << " signed";
|
||||
switch (port_type_) {
|
||||
@@ -160,11 +95,9 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||
}
|
||||
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
|
||||
if (scope())
|
||||
o << " scope=" << scope_path(scope());
|
||||
o << " #(" << rise_time() << "," << fall_time() << ","
|
||||
<< decay_time() << ") vector_width=" << vector_width()
|
||||
<< " pin_count=" << pin_count()
|
||||
<< " init=";
|
||||
o << " scope=" << scope()->name();
|
||||
o << " #(" << rise_time() << "," << fall_time() << "," <<
|
||||
decay_time() << ") init=";
|
||||
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
|
||||
o << pin(idx-1).get_init();
|
||||
|
||||
@@ -181,15 +114,23 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||
o << setw(ind+4) << "" << "[" << idx << "]: " << nex
|
||||
<< " " << nex->name() << endl;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < delay_paths_.size() ; idx += 1) {
|
||||
const NetDelaySrc*cur = delay_paths_[idx];
|
||||
cur->dump(o, ind+4);
|
||||
}
|
||||
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetSubnet::dump_net(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "** " << name() << " is a NetSubnet **"
|
||||
<< endl;
|
||||
NetNet::dump_net(o, ind);
|
||||
}
|
||||
|
||||
void NetMemory::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << name_ << "[" << width_ << "] " <<
|
||||
"[" << idxh_ << ":" << idxl_ << "]" << endl;
|
||||
}
|
||||
|
||||
|
||||
/* Dump a NetNode and its pins. Dump what I know about the netnode on
|
||||
the first line, then list all the pins, with the name of the
|
||||
connected signal. */
|
||||
@@ -230,7 +171,8 @@ void NetObj::dump_node_pins(ostream&o, unsigned ind) const
|
||||
|
||||
if (pin(idx).is_linked()) {
|
||||
const Nexus*nex = pin(idx).nexus();
|
||||
o << nex << " " << nex->name();
|
||||
const char*nex_name = nex->name();
|
||||
o << nex << " " << (nex_name? nex_name : "????");
|
||||
}
|
||||
o << endl;
|
||||
|
||||
@@ -248,20 +190,16 @@ void NetObj::dump_obj_attr(ostream&o, unsigned ind) const
|
||||
|
||||
void NetAddSub::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Adder (NetAddSub): " << name()
|
||||
<< " width=" << width() << " pin_count=" << pin_count()
|
||||
<< endl;
|
||||
o << setw(ind) << "" << "Adder (NetAddSub): " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetArrayDq::dump_node(ostream&o, unsigned ind) const
|
||||
void NetCAssign::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetArrayDq: " << name()
|
||||
<< " array=" << mem_->name()
|
||||
<< endl;
|
||||
o << setw(ind) << "" << "Procedural continuous assign (NetCAssign): "
|
||||
<< name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCLShift::dump_node(ostream&o, unsigned ind) const
|
||||
@@ -279,12 +217,19 @@ void NetCompare::dump_node(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetConcat::dump_node(ostream&o, unsigned ind) const
|
||||
void NetDecode::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetConcat: "
|
||||
<< name()
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< " width=" << width_ << endl;
|
||||
o << setw(ind) << "" << "LPM_DECODE (NetDecode): " << name()
|
||||
<< " ff=" << ff_->name() << ", word width=" << width() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetDemux::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_DEMUX (NetDemux): " << name()
|
||||
<< " bus width=" << width() << ", address width=" << awidth()
|
||||
<< ", word count=" << size() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
@@ -296,6 +241,12 @@ void NetDivide::dump_node(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetForce::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "force " << lval_->name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetMult::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_MULT (NetMult): " << name() << endl;
|
||||
@@ -306,8 +257,8 @@ void NetMult::dump_node(ostream&o, unsigned ind) const
|
||||
void NetMux::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Multiplexer (NetMux): " << name()
|
||||
<< " width=" << width_ << " swidth=" << swidth_ << " size=" << size_
|
||||
<< " scope=" << scope_path(scope()) << endl;
|
||||
<< " scope=" << scope()->name() << endl;
|
||||
o << setw(ind+6) << "" << "source=" << get_line() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
@@ -315,26 +266,22 @@ void NetMux::dump_node(ostream&o, unsigned ind) const
|
||||
void NetBUFZ::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetBUFZ: " << name()
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< " scope=" << (scope()? scope()->name() : "")
|
||||
<< " delay=(" << rise_time() << "," << fall_time() << "," <<
|
||||
decay_time() << ") width=" << width() << endl;
|
||||
decay_time() << ")" << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCaseCmp::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
if (eeq_)
|
||||
o << setw(ind) << "" << "case compare === : " << name() << endl;
|
||||
else
|
||||
o << setw(ind) << "" << "case compare !== : " << name() << endl;
|
||||
|
||||
o << setw(ind) << "" << "case compare === : " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetConst::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "constant " << width_ << "'b";
|
||||
for (unsigned idx = width_ ; idx > 0 ; idx -= 1)
|
||||
o << setw(ind) << "" << "constant ";
|
||||
for (unsigned idx = pin_count() ; idx > 0 ; idx -= 1)
|
||||
o << value_[idx-1];
|
||||
o << ": " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
@@ -343,20 +290,18 @@ void NetConst::dump_node(ostream&o, unsigned ind) const
|
||||
void NetFF::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_FF: " << name()
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< " aset_value=" << aset_value_ << endl;
|
||||
<< " scope=" << (scope()? scope()->name() : "")
|
||||
<< " aset_value=" << aset_value_
|
||||
<< " sset_value=" << sset_value_;
|
||||
|
||||
if (demux_) o << " demux=" << demux_->name();
|
||||
|
||||
o << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetLiteral::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "constant real " << real_
|
||||
<< ": " << name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
}
|
||||
|
||||
void NetLogic::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "logic: ";
|
||||
@@ -418,7 +363,7 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const
|
||||
}
|
||||
o << " #(" << rise_time()
|
||||
<< "," << fall_time() << "," << decay_time() << ") " << name()
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< " scope=" << (scope()? scope()->name() : "")
|
||||
<< endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
@@ -432,88 +377,25 @@ void NetModulo::dump_node(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetPartSelect::dump_node(ostream&o, unsigned ind) const
|
||||
void NetRamDq::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
const char*pt = "";
|
||||
switch (dir_) {
|
||||
case VP:
|
||||
pt = "VP";
|
||||
break;
|
||||
case PV:
|
||||
pt = "PV";
|
||||
break;
|
||||
case BI:
|
||||
pt = "BI";
|
||||
break;
|
||||
}
|
||||
o << setw(ind) << "" << "NetPartSelect(" << pt << "): "
|
||||
<< name() << " off=" << off_ << " wid=" << wid_ <<endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
o << setw(ind) << "" << "LPM_RAM_DQ (";
|
||||
|
||||
void NetReplicate::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetReplicate: "
|
||||
<< name() << " wid=" << width_ << ", repeat_=" << repeat_
|
||||
<< ", input wid=" << width_/repeat_ << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
if (mem_)
|
||||
if (NetNet*tmp = mem_->reg_from_explode())
|
||||
o << "exploded mem=" << tmp->name();
|
||||
else
|
||||
o << "mem=" << mem_->name();
|
||||
|
||||
void NetSignExtend::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetSignExtend: "
|
||||
<< name() << " output width=" << width_ << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
o << "): " << name() << endl;
|
||||
|
||||
void NetUReduce::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "reduction logic: ";
|
||||
switch (type_) {
|
||||
case NONE:
|
||||
o << "NONE";
|
||||
break;
|
||||
case AND:
|
||||
o << "and";
|
||||
break;
|
||||
case OR:
|
||||
o << "or";
|
||||
break;
|
||||
case XOR:
|
||||
o << "xor";
|
||||
break;
|
||||
case NAND:
|
||||
o << "nand";
|
||||
break;
|
||||
case NOR:
|
||||
o << "nor";
|
||||
break;
|
||||
case XNOR:
|
||||
o << "xnor";
|
||||
break;
|
||||
}
|
||||
o << " #(" << rise_time()
|
||||
<< "," << fall_time() << "," << decay_time() << ") " << name()
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetSysFunc::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << def_->name << "(...)" << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetUserFunc::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << scope_path(def_) << "(";
|
||||
o << setw(ind) << "" << def_->name() << "(";
|
||||
o << ")" << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
@@ -521,7 +403,7 @@ void NetUserFunc::dump_node(ostream&o, unsigned ind) const
|
||||
|
||||
void NetTaskDef::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "task " << scope_path(scope_) << ";" << endl;
|
||||
o << setw(ind) << "" << "task " << name_ << ";" << endl;
|
||||
|
||||
for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) {
|
||||
o << setw(ind+4) << "";
|
||||
@@ -563,11 +445,11 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
|
||||
switch (type_) {
|
||||
case NetProcTop::KINITIAL:
|
||||
o << "initial /* " << get_line() << " in "
|
||||
<< scope_path(scope_) << " */" << endl;
|
||||
<< scope_->name() << " */" << endl;
|
||||
break;
|
||||
case NetProcTop::KALWAYS:
|
||||
o << "always /* " << get_line() << " in "
|
||||
<< scope_path(scope_) << " */" << endl;
|
||||
<< scope_->name() << " */" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -583,12 +465,22 @@ void NetAssign_::dump_lval(ostream&o) const
|
||||
{
|
||||
if (sig_) {
|
||||
o << sig_->name();
|
||||
if (word_) {
|
||||
o << "[word=" << *word_ << "]";
|
||||
}
|
||||
if (base_) {
|
||||
o << "[" << *base_ << " +: " << lwid_ << "]";
|
||||
if (bmux_) {
|
||||
o << "[" << *bmux_ << "]";
|
||||
|
||||
} else {
|
||||
o << "[" << (loff_+lwid_-1) << ":" << loff_ << "]";
|
||||
}
|
||||
} else if (mem_) {
|
||||
// Is there an obvious way to flag memories in the dump
|
||||
// as different from the _real_ bit mux case?
|
||||
// o << "**memory**";
|
||||
o << mem_->name() << "[";
|
||||
if (bmux_) o << *bmux_;
|
||||
else o << "**oops**";
|
||||
o << "]";
|
||||
} else if (var_) {
|
||||
o << "<real " << var_->basename() << ">";
|
||||
} else {
|
||||
o << "";
|
||||
}
|
||||
@@ -614,10 +506,10 @@ void NetAssign::dump(ostream&o, unsigned ind) const
|
||||
dump_lval(o);
|
||||
|
||||
o << " = ";
|
||||
|
||||
if (const NetExpr*de = get_delay())
|
||||
o << "#(" << *de << ") ";
|
||||
|
||||
#if 0
|
||||
if (l_val(0)->rise_time())
|
||||
o << "#" << l_val(0)->rise_time() << " ";
|
||||
#endif
|
||||
o << *rval() << ";" << endl;
|
||||
}
|
||||
|
||||
@@ -627,10 +519,10 @@ void NetAssignNB::dump(ostream&o, unsigned ind) const
|
||||
dump_lval(o);
|
||||
|
||||
o << " <= ";
|
||||
|
||||
if (const NetExpr*de = get_delay())
|
||||
o << "#(" << *de << ") ";
|
||||
|
||||
#if 0
|
||||
if (l_val(0)->rise_time())
|
||||
o << "#" << l_val(0)->rise_time() << " ";
|
||||
#endif
|
||||
o << *rval() << ";" << endl;
|
||||
|
||||
}
|
||||
@@ -649,7 +541,7 @@ void NetBlock::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << type_;
|
||||
if (subscope_)
|
||||
o << " : " << scope_path(subscope_);
|
||||
o << " : " << subscope_->name();
|
||||
o << endl;
|
||||
|
||||
if (last_) {
|
||||
@@ -677,6 +569,8 @@ void NetCase::dump(ostream&o, unsigned ind) const
|
||||
break;
|
||||
}
|
||||
|
||||
dump_proc_attr(o, ind+2);
|
||||
|
||||
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
|
||||
o << setw(ind+2) << "";
|
||||
if (items_[idx].guard)
|
||||
@@ -697,9 +591,8 @@ void NetCase::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetCAssign::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "cassign ";
|
||||
dump_lval(o);
|
||||
o << " = " << *rval() << "; /* " << get_line() << " */" << endl;
|
||||
o << setw(ind) << "" << "cassign " << lval_->name() << " = "
|
||||
<< name() << ";" << endl;
|
||||
}
|
||||
|
||||
void NetCondit::dump(ostream&o, unsigned ind) const
|
||||
@@ -719,14 +612,13 @@ void NetCondit::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetDeassign::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "deassign ";
|
||||
dump_lval(o);
|
||||
o << "; /* " << get_line() << " */" << endl;
|
||||
o << setw(ind) << "" << "deassign " << lval_->name() << "; "
|
||||
<< "/* " << get_line() << " */" << endl;
|
||||
}
|
||||
|
||||
void NetDisable::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "disable " << scope_path(target_) << "; "
|
||||
o << setw(ind) << "" << "disable " << target_->name() << "; "
|
||||
<< "/* " << get_line() << " */" << endl;
|
||||
}
|
||||
|
||||
@@ -745,7 +637,7 @@ void NetEvProbe::dump_node(ostream&o, unsigned ind) const
|
||||
o << "negedge ";
|
||||
break;
|
||||
}
|
||||
o << setw(ind) << "" << "-> " << event_->name() << "; " << endl;
|
||||
o << setw(ind) << "" << "-> " << event_->full_name() << "; " << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
@@ -758,13 +650,11 @@ void NetEvTrig::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetEvWait::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) <<"" << "@(";
|
||||
|
||||
if (nevents() > 0)
|
||||
o << event(0)->name();
|
||||
assert(nevents() > 0);
|
||||
o << setw(ind) <<"" << "@(" << event(0)->full_name();
|
||||
|
||||
for (unsigned idx = 1 ; idx < nevents() ; idx += 1)
|
||||
o << " or " << event(idx)->name();
|
||||
o << " or " << event(idx)->full_name();
|
||||
|
||||
o << ") // " << get_line() << endl;
|
||||
|
||||
@@ -776,9 +666,8 @@ void NetEvWait::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetForce::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "force ";
|
||||
dump_lval(o);
|
||||
o << " = " << *rval() << "; /* " << get_line() << " */" << endl;
|
||||
o << setw(ind) << "" << "force " << lval_->name() << " = "
|
||||
<< name() << ";" << endl;
|
||||
}
|
||||
|
||||
void NetForever::dump(ostream&o, unsigned ind) const
|
||||
@@ -789,10 +678,14 @@ void NetForever::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetFuncDef::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "function " << scope_path(scope_) << endl;
|
||||
o << setw(ind) << "" << "function " << scope_->name() << endl;
|
||||
if (result_sig_)
|
||||
o << setw(ind+2) << "" << "Return signal: "
|
||||
<< result_sig_->name() << endl;
|
||||
if (result_var_)
|
||||
o << setw(ind+2) << "" << "Return variable: "
|
||||
<< result_var_->basename() << endl;
|
||||
|
||||
if (statement_)
|
||||
statement_->dump(o, ind+2);
|
||||
else
|
||||
@@ -818,9 +711,12 @@ void NetPDelay::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetRelease::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "release ";
|
||||
dump_lval(o);
|
||||
o << "; /* " << get_line() << " */" << endl;
|
||||
if (lval_)
|
||||
o << setw(ind) << "" << "release " << lval_->name() << "; "
|
||||
<< "/* " << get_line() << " */" << endl;
|
||||
else
|
||||
o << setw(ind) << "" << "release (null); "
|
||||
<< "/* " << get_line() << " */" << endl;
|
||||
}
|
||||
|
||||
void NetRepeat::dump(ostream&o, unsigned ind) const
|
||||
@@ -832,7 +728,7 @@ void NetRepeat::dump(ostream&o, unsigned ind) const
|
||||
void NetScope::dump(ostream&o) const
|
||||
{
|
||||
/* This is a constructed hierarchical name. */
|
||||
o << scope_path(this);
|
||||
o << name();
|
||||
|
||||
switch (type_) {
|
||||
case BEGIN_END:
|
||||
@@ -850,9 +746,6 @@ void NetScope::dump(ostream&o) const
|
||||
case TASK:
|
||||
o << " task";
|
||||
break;
|
||||
case GENBLOCK:
|
||||
o << " generate block";
|
||||
break;
|
||||
}
|
||||
o << endl;
|
||||
|
||||
@@ -890,7 +783,7 @@ void NetScope::dump(ostream&o) const
|
||||
|
||||
/* Dump the saved defparam assignments here. */
|
||||
{
|
||||
map<pform_name_t,NetExpr*>::const_iterator pp;
|
||||
map<hname_t,NetExpr*>::const_iterator pp;
|
||||
for (pp = defparams.begin()
|
||||
; pp != defparams.end() ; pp ++ ) {
|
||||
o << " defparam " << (*pp).first << " = " <<
|
||||
@@ -898,11 +791,15 @@ void NetScope::dump(ostream&o) const
|
||||
}
|
||||
}
|
||||
|
||||
for (NetVariable*cur = vars_ ; cur ; cur = cur->snext_) {
|
||||
o << " real " << cur->basename() << " // "
|
||||
<< cur->get_line() << endl;
|
||||
}
|
||||
|
||||
/* Dump the events in this scope. */
|
||||
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) {
|
||||
o << " event " << cur->name() << "; nprobe="
|
||||
<< cur->nprobe() << " scope=" << scope_path(cur->scope())
|
||||
<< " // " << cur->get_line() << endl;
|
||||
<< cur->nprobe() << " // " << cur->get_line() << endl;
|
||||
}
|
||||
|
||||
// Dump the signals,
|
||||
@@ -914,25 +811,13 @@ void NetScope::dump(ostream&o) const
|
||||
} while (cur != signals_->sig_next_);
|
||||
}
|
||||
|
||||
// Dump specparams
|
||||
typedef map<perm_string,spec_val_t>::const_iterator specparam_it_t;
|
||||
for (specparam_it_t cur = specparams.begin()
|
||||
; cur != specparams.end() ; cur ++ ) {
|
||||
o << " specparam " << (*cur).first
|
||||
<< " = ";
|
||||
spec_val_t value = (*cur).second;
|
||||
switch (value.type) {
|
||||
case IVL_VT_REAL:
|
||||
o << "R:" << value.real_val;
|
||||
break;
|
||||
case IVL_VT_BOOL:
|
||||
o << "I:" << value.integer;
|
||||
break;
|
||||
default:
|
||||
o << "<bad type>";
|
||||
break;
|
||||
}
|
||||
o << endl;
|
||||
// Dump the memories,
|
||||
if (memories_) {
|
||||
NetMemory*cur = memories_->snext_;
|
||||
do {
|
||||
cur->dump(o, 4);
|
||||
cur = cur->snext_;
|
||||
} while (cur != memories_->snext_);
|
||||
}
|
||||
|
||||
switch (type_) {
|
||||
@@ -976,7 +861,7 @@ void NetSTask::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetUTask::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << scope_path(task_) << ";" << endl;
|
||||
o << setw(ind) << "" << task_->name() << ";" << endl;
|
||||
}
|
||||
|
||||
void NetWhile::dump(ostream&o, unsigned ind) const
|
||||
@@ -991,6 +876,15 @@ void NetProc::dump(ostream&o, unsigned ind) const
|
||||
o << setw(ind) << "" << "// " << typeid(*this).name() << endl;
|
||||
}
|
||||
|
||||
void NetProc::dump_proc_attr(ostream&o, unsigned ind) const
|
||||
{
|
||||
unsigned idx;
|
||||
for (idx = 0 ; idx < attr_cnt() ; idx += 1) {
|
||||
o << setw(ind) << "" << "(* " << attr_key(idx) << " = "
|
||||
<< attr_value(idx) << " *)" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/* Dump an expression that no one wrote a dump method for. */
|
||||
void NetExpr::dump(ostream&o) const
|
||||
{
|
||||
@@ -1036,9 +930,6 @@ void NetEBinary::dump(ostream&o) const
|
||||
case 'O':
|
||||
o << "~|";
|
||||
break;
|
||||
case 'p':
|
||||
o << "**";
|
||||
break;
|
||||
case 'r':
|
||||
o << ">>";
|
||||
break;
|
||||
@@ -1089,7 +980,7 @@ void NetEConstParam::dump(ostream&o) const
|
||||
{
|
||||
o << "<" << name_ << "=";
|
||||
NetEConst::dump(o);
|
||||
o << ", wid=" << expr_width() << ">";
|
||||
o << ">";
|
||||
}
|
||||
|
||||
void NetECReal::dump(ostream&o) const
|
||||
@@ -1111,7 +1002,7 @@ void NetEEvent::dump(ostream&o) const
|
||||
|
||||
void NetEScope::dump(ostream&o) const
|
||||
{
|
||||
o << "<scope=" << scope_path(scope_) << ">";
|
||||
o << "<scope=" << scope_->name() << ">";
|
||||
}
|
||||
|
||||
void NetESelect::dump(ostream&o) const
|
||||
@@ -1147,19 +1038,30 @@ void NetESignal::dump(ostream&o) const
|
||||
{
|
||||
if (has_sign())
|
||||
o << "+";
|
||||
o << name();
|
||||
if (word_) o << "[word=" << *word_ << "]";
|
||||
o << "[" << msi()<<":"<<lsi() << "]";
|
||||
o << name() << "[" << msi_<<":"<<lsi_ << "]";
|
||||
}
|
||||
|
||||
void NetEBitSel::dump(ostream&o) const
|
||||
{
|
||||
sig_->dump(o);
|
||||
o << "[";
|
||||
idx_->dump(o);
|
||||
o << "]";
|
||||
}
|
||||
|
||||
void NetEMemory::dump(ostream&o) const
|
||||
{
|
||||
o << mem_->name() << "[";
|
||||
if (idx_) idx_->dump(o);
|
||||
o << "]";
|
||||
}
|
||||
|
||||
void NetEParam::dump(ostream&o) const
|
||||
{
|
||||
if (scope_ != 0)
|
||||
o << "<" << scope_path(scope_) << "." << name_ << ">";
|
||||
else if (name_)
|
||||
o << "<" << name_ << ">";
|
||||
o << "<" << scope_->name() << "." << name_ << ">";
|
||||
else
|
||||
o << "<" "???" ">";
|
||||
o << "<" << name_ << ">";
|
||||
}
|
||||
|
||||
void NetETernary::dump(ostream&o) const
|
||||
@@ -1170,7 +1072,7 @@ void NetETernary::dump(ostream&o) const
|
||||
|
||||
void NetEUFunc::dump(ostream&o) const
|
||||
{
|
||||
o << func_->basename() << "(";
|
||||
o << name() << "(";
|
||||
if (parms_.count() > 0) {
|
||||
parms_[0]->dump(o);
|
||||
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
|
||||
@@ -1196,6 +1098,11 @@ void NetEUnary::dump(ostream&o) const
|
||||
o << ")";
|
||||
}
|
||||
|
||||
void NetEVariable::dump(ostream&o) const
|
||||
{
|
||||
o << var_->basename();
|
||||
}
|
||||
|
||||
void Design::dump(ostream&o) const
|
||||
{
|
||||
o << "DESIGN TIME PRECISION: 10e" << get_precision() << endl;
|
||||
@@ -1225,99 +1132,26 @@ void Design::dump(ostream&o) const
|
||||
|
||||
/*
|
||||
* $Log: design_dump.cc,v $
|
||||
* Revision 1.176 2007/06/02 03:42:12 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
* Revision 1.149.2.7 2006/08/23 04:09:14 steve
|
||||
* missing sig diagnostics.
|
||||
*
|
||||
* Revision 1.175 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.149.2.6 2006/07/10 00:21:50 steve
|
||||
* Add support for full_case attribute.
|
||||
*
|
||||
* Revision 1.174 2007/03/02 06:13:22 steve
|
||||
* Add support for edge sensitive spec paths.
|
||||
* Revision 1.149.2.5 2006/04/16 19:26:37 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.173 2007/02/01 03:14:33 steve
|
||||
* Detect and report arrays without index in net contexts.
|
||||
* Revision 1.149.2.4 2006/03/26 23:09:21 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.172 2007/01/16 05:44:14 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
* Revision 1.149.2.3 2006/03/12 07:34:16 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.171 2006/10/30 05:44:49 steve
|
||||
* Expression widths with unsized literals are pseudo-infinite width.
|
||||
* Revision 1.149.2.2 2006/02/19 00:11:31 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.170 2006/10/03 05:06:00 steve
|
||||
* Support real valued specify delays, properly scaled.
|
||||
*
|
||||
* Revision 1.169 2006/09/26 19:48:40 steve
|
||||
* Missing PSpec.cc file.
|
||||
*
|
||||
* Revision 1.168 2006/09/23 04:57:19 steve
|
||||
* Basic support for specify timing.
|
||||
*
|
||||
* Revision 1.167 2006/07/31 03:50:17 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.166 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.165 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.164 2006/02/02 02:43:57 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.163 2005/08/27 04:32:08 steve
|
||||
* Handle synthesis of fully packed case statements.
|
||||
*
|
||||
* Revision 1.162 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.161 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.160 2005/05/24 01:44:27 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.159 2005/05/17 20:56:55 steve
|
||||
* Parameters cannot have their width changed.
|
||||
*
|
||||
* Revision 1.158 2005/05/07 03:13:30 steve
|
||||
* Include delay expressions for assignments in dump.
|
||||
*
|
||||
* Revision 1.157 2005/03/09 05:52:03 steve
|
||||
* Handle case inequality in netlists.
|
||||
*
|
||||
* Revision 1.156 2005/02/08 00:12:36 steve
|
||||
* Add the NetRepeat node, and code generator support.
|
||||
*
|
||||
* Revision 1.155 2005/02/03 04:56:20 steve
|
||||
* laborate reduction gates into LPM_RED_ nodes.
|
||||
*
|
||||
* Revision 1.154 2005/01/24 05:28:30 steve
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
*
|
||||
* Revision 1.153 2005/01/22 18:16:00 steve
|
||||
* Remove obsolete NetSubnet class.
|
||||
*
|
||||
* Revision 1.152 2005/01/09 20:16:00 steve
|
||||
* Use PartSelect/PV and VP to handle part selects through ports.
|
||||
*
|
||||
* Revision 1.151 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.150 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
* Revision 1.149.2.1 2006/01/18 01:23:23 steve
|
||||
* Rework l-value handling to allow for more l-value type flexibility.
|
||||
*
|
||||
* Revision 1.149 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
|
||||
@@ -16,12 +16,12 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.7 2004/10/13 22:01:34 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.7.2.1 2006/10/04 17:08:59 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
|
||||
VERSION = 0.8
|
||||
VERSION = 0.8.3
|
||||
|
||||
prefix = @prefix@
|
||||
exec_prefix = @exec_prefix@
|
||||
|
||||
+1
-8
@@ -277,7 +277,6 @@ static int parse(int argc, char *argv[])
|
||||
|
||||
char dot_c_ext[] = ".c";
|
||||
char dot_cc_ext[] = ".cc";
|
||||
char dot_cpp_ext[] = ".cpp";
|
||||
char dot_o_ext[] = ".o";
|
||||
char name_option[] = "--name=";
|
||||
char lib_option[] = "-l";
|
||||
@@ -302,13 +301,6 @@ static int parse(int argc, char *argv[])
|
||||
if (!*gstr.pOUT)
|
||||
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_cc_ext));
|
||||
}
|
||||
else if (endsIn(dot_cpp_ext,argv[idx])) { /* check for C++ source files */
|
||||
++srcFileCnt;
|
||||
append(&gstr.pCXSRC,argv[idx]);
|
||||
append(&gstr.pCXSRC," ");
|
||||
if (!*gstr.pOUT)
|
||||
assignn(&gstr.pOUT,argv[idx],strlen(argv[idx])-strlen(dot_cpp_ext));
|
||||
}
|
||||
else if (endsIn(dot_o_ext,argv[idx])) { /* check for compiled object files */
|
||||
++srcFileCnt;
|
||||
append(&gstr.pOBJ,argv[idx]);
|
||||
@@ -570,4 +562,5 @@ int main(int argc, char *argv[])
|
||||
compile_and_link();
|
||||
|
||||
myExit(0);
|
||||
return 0; // eliminate warnings.
|
||||
}
|
||||
|
||||
+19
-8
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.26 2007/02/06 05:07:31 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.24.2.3 2007/05/30 17:48:26 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -40,6 +40,8 @@ CC = @CC@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
MAN = @MAN@
|
||||
PS2PDF = @PS2PDF@
|
||||
|
||||
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) -DVERSION='"$(VERSION)"' @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
@@ -50,10 +52,11 @@ all: iverilog@EXEEXT@
|
||||
clean:
|
||||
rm -f *.o lexor.c parse.c parse.h parse.output
|
||||
rm -f cflexor.c cfparse.c cfparse.h cfparse.output
|
||||
rm -f iverilog@EXEEXT@ iverilog.pdf iverilog.ps
|
||||
rm -f iverilog@EXEEXT@
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
rm -rf autom4te.cache
|
||||
|
||||
O = main.o substit.o cflexor.o cfparse.o
|
||||
|
||||
@@ -68,22 +71,30 @@ cfparse.h cfparse.c: cfparse.y
|
||||
|
||||
|
||||
main.o: main.c globals.h
|
||||
$(CC) $(CPPFLAGS) $(CFLAGS) -c -DIVL_ROOT='"@libdir@/ivl"' -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@"' $(DEBUGFLAGS) $(srcdir)/main.c
|
||||
|
||||
build_string.o: build_string.c globals.h
|
||||
cflexor.o: cflexor.c cfparse.h cfparse_misc.h globals.h
|
||||
cfparse.o: cfparse.c globals.h cfparse_misc.h
|
||||
|
||||
iverilog.ps: $(srcdir)/iverilog.man
|
||||
man -t $(srcdir)/iverilog.man > iverilog.ps
|
||||
$(MAN) -t $(srcdir)/iverilog.man > iverilog.ps
|
||||
|
||||
iverilog.pdf: iverilog.ps
|
||||
ps2pdf iverilog.ps iverilog.pdf
|
||||
$(PS2PDF) iverilog.ps iverilog.pdf
|
||||
|
||||
ifeq (@MING32@,yes)
|
||||
ifeq (@WIN32@,yes)
|
||||
ifeq ($(MAN),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog.1
|
||||
else
|
||||
ifeq ($(PS2PDF),none)
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog.1
|
||||
else
|
||||
INSTALL_DOC = $(prefix)/iverilog.pdf $(mandir)/man1/iverilog.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
all: iverilog.pdf
|
||||
endif
|
||||
endif
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
else
|
||||
INSTALL_DOC = $(mandir)/man1/iverilog.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
@@ -105,4 +116,4 @@ installdirs: ../mkinstalldirs
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/iverilog@EXEEXT@
|
||||
rm -f $(mandir)/man1/iverilog.1 $(prefix)/iverilog.pdf
|
||||
rm -f $(mandir)/man1/iverilog.1
|
||||
|
||||
+6
-42
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: cflexor.lex,v 1.11 2007/03/22 16:08:18 steve Exp $"
|
||||
#ident "$Id: cflexor.lex,v 1.8 2004/10/04 01:10:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "cfparse.h"
|
||||
@@ -37,14 +37,12 @@
|
||||
YYLTYPE yylloc;
|
||||
|
||||
static int comment_enter;
|
||||
static char* trim_trailing_white(char*txt, int trim);
|
||||
|
||||
%}
|
||||
|
||||
%x CCOMMENT
|
||||
%x LCOMMENT
|
||||
%x PLUS_ARGS
|
||||
%x FILE_NAME
|
||||
|
||||
%%
|
||||
|
||||
@@ -78,7 +76,6 @@ static int comment_enter;
|
||||
|
||||
"+libext+" { BEGIN(PLUS_ARGS); return TOK_LIBEXT; }
|
||||
|
||||
"+integer-width+" { BEGIN(PLUS_ARGS); return TOK_INTEGER_WIDTH; }
|
||||
|
||||
/* If it is not any known plus-flag, return the generic form. */
|
||||
"+"[^\n \t\b\f\r+]* {
|
||||
@@ -115,50 +112,17 @@ static int comment_enter;
|
||||
/* This rule matches paths and strings that may be file names. This
|
||||
is a little bit tricky, as we don't want to mistake a comment for
|
||||
a string word. */
|
||||
"/"[\r\n] { /* Special case of file name "/" */
|
||||
cflval.text = trim_trailing_white(yytext, 0);
|
||||
return TOK_STRING; }
|
||||
"/"[^\*\/] { /* A file name that starts with "/". */
|
||||
yymore();
|
||||
BEGIN(FILE_NAME); }
|
||||
[^/\n \t\b\r+-][^/\n\r]* { /* A file name that starts with other than "/" */
|
||||
yymore();
|
||||
BEGIN(FILE_NAME); }
|
||||
"/"[^\*\/].* { cflval.text = strdup(yytext);
|
||||
return TOK_STRING; }
|
||||
|
||||
[^/\n \t\b\r+-].* { cflval.text = strdup(yytext);
|
||||
return TOK_STRING; }
|
||||
|
||||
<FILE_NAME>"//" {
|
||||
/* Found a trailing comment. Returning the terminated name. */
|
||||
cflval.text = trim_trailing_white(yytext, 2);
|
||||
BEGIN(LCOMMENT);
|
||||
return TOK_STRING; }
|
||||
<FILE_NAME>"/"?[^/\n\r]* {
|
||||
yymore();
|
||||
/* not a comment... continuing */; }
|
||||
<FILE_NAME>[\n\r] {
|
||||
/* No trailing comment. Return the file name. */
|
||||
cflval.text = trim_trailing_white(yytext, 0);
|
||||
BEGIN(0);
|
||||
return TOK_STRING; }
|
||||
|
||||
/* Fallback match. */
|
||||
. { return yytext[0]; }
|
||||
|
||||
%%
|
||||
|
||||
static char* trim_trailing_white(char*text, int trim)
|
||||
{
|
||||
char*cp = text + strlen(text);
|
||||
while (cp > text && trim > 0) {
|
||||
trim -= 1;
|
||||
cp -= 1;
|
||||
*cp = 0;
|
||||
}
|
||||
while (cp > text && strchr("\n\r\t\b", cp[-1]))
|
||||
cp -= 1;
|
||||
|
||||
cp[0] = 0;
|
||||
return strdup(text);
|
||||
}
|
||||
|
||||
int yywrap()
|
||||
{
|
||||
return 1;
|
||||
|
||||
+5
-13
@@ -18,7 +18,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: cfparse.y,v 1.12 2007/04/19 02:52:53 steve Exp $"
|
||||
#ident "$Id: cfparse.y,v 1.10 2003/09/26 21:25:58 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -62,7 +62,6 @@ static void translate_file_name(char*text)
|
||||
|
||||
%token TOK_Da TOK_Dv TOK_Dy
|
||||
%token TOK_DEFINE TOK_INCDIR TOK_LIBDIR TOK_LIBDIR_NOCASE TOK_LIBEXT
|
||||
%token TOK_INTEGER_WIDTH
|
||||
%token <text> TOK_PLUSARG TOK_PLUSWORD TOK_STRING
|
||||
|
||||
%%
|
||||
@@ -84,7 +83,7 @@ item
|
||||
: TOK_STRING
|
||||
{ char*tmp = substitutions($1);
|
||||
translate_file_name(tmp);
|
||||
process_file_name(tmp, 0);
|
||||
process_file_name(tmp);
|
||||
free($1);
|
||||
free(tmp);
|
||||
}
|
||||
@@ -99,7 +98,9 @@ item
|
||||
| TOK_Dv TOK_STRING
|
||||
{ char*tmp = substitutions($2);
|
||||
translate_file_name(tmp);
|
||||
process_file_name(tmp, 1);
|
||||
process_file_name(tmp);
|
||||
fprintf(stderr, "%s:%u: Ignoring -v in front of %s\n",
|
||||
@1.text, @1.first_line, $2);
|
||||
free($2);
|
||||
free(tmp);
|
||||
}
|
||||
@@ -144,15 +145,6 @@ item
|
||||
|
||||
| TOK_LIBEXT libext_args
|
||||
|
||||
/* These are various misc flags that are supported. */
|
||||
|
||||
| TOK_INTEGER_WIDTH TOK_PLUSARG
|
||||
{ char*tmp = substitutions($2);
|
||||
free($2);
|
||||
integer_width = strtoul(tmp,0,10);
|
||||
free(tmp);
|
||||
}
|
||||
|
||||
/* The +<word> tokens that are not otherwise matched, are
|
||||
ignored. The skip_args rule arranges for all the argument words
|
||||
to be consumed. */
|
||||
|
||||
+2
-11
@@ -19,7 +19,7 @@
|
||||
* 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 $"
|
||||
#ident "$Id: globals.h,v 1.19 2003/11/18 06:31:46 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stddef.h>
|
||||
@@ -49,14 +49,11 @@ extern int synth_flag;
|
||||
/* This is the name of the selected target. */
|
||||
extern const char*targ;
|
||||
|
||||
/* This is the integer-width argument that will be passed to ivl. */
|
||||
extern unsigned integer_width;
|
||||
|
||||
/* Perform variable substitutions on the string. */
|
||||
extern char* substitutions(const char*str);
|
||||
|
||||
/* Add the name to the list of source files. */
|
||||
extern void process_file_name(const char*name, int lib_flag);
|
||||
extern void process_file_name(const char*name);
|
||||
|
||||
/* Add the name to the list of library directories. */
|
||||
extern void process_library_switch(const char*name);
|
||||
@@ -80,12 +77,6 @@ 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.
|
||||
*
|
||||
|
||||
+13
-30
@@ -1,10 +1,10 @@
|
||||
.TH iverilog 1 "$Date: 2007/06/05 01:56:12 $" Version "$Date: 2007/06/05 01:56:12 $"
|
||||
.TH iverilog 1 "$Date: 2006/06/12 00:16:53 $" Version "$Date: 2006/06/12 00:16:53 $"
|
||||
.SH NAME
|
||||
iverilog - Icarus Verilog compiler
|
||||
|
||||
.SH SYNOPSIS
|
||||
.B iverilog
|
||||
[-ESVv] [-Bpath] [-ccmdfile] [-g1|-g2|-g2x|-gspecify-gxtypes] [-Dmacro[=defn]] [-pflag=value]
|
||||
[-ESVv] [-Bpath] [-ccmdfile] [-g1|-g2|-g3.0] [-Dmacro[=defn]] [-pflag=value]
|
||||
[-Iincludedir] [-mmodule] [-Mfile] [-Nfile] [-ooutputfilename]
|
||||
[-stopmodule] [-ttype] [-Tmin/typ/max] [-Wclass] [-ypath] sourcefile
|
||||
|
||||
@@ -48,30 +48,15 @@ is the Verilog input, but with file inclusions and macro references
|
||||
expanded and removed. This is useful, for example, to preprocess
|
||||
Verilog source for use by other compilers.
|
||||
.TP 8
|
||||
.B -g1\fI|\fP-g2\fI|\fP-g2x
|
||||
.B -g1\fI|\fP-g2\fI|\fP-g3.0
|
||||
Select the Verilog language \fIgeneration\fP to support in the
|
||||
compiler. This selects between \fIIEEE1364-1995\fP(1),
|
||||
\fIIEEE1364-2001\fP(2), or \fIVerilog with extension\fP(2x). Normally,
|
||||
\fIIEEE1364-2001\fP(2), or \fISystemVerilog 3.0\fP(3.0). Normally,
|
||||
Icarus Verilog defaults to the latest known generation of the
|
||||
language. This flag is most useful to restrict the language to a set
|
||||
supported by tools of specific generations, for compatibility with
|
||||
other tools.
|
||||
.TP 8
|
||||
.B -gspecify\fI|\fP-gno-specify
|
||||
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
|
||||
simulation. However, disabling specify blocks reduces accuracy of
|
||||
full-timing simulations.
|
||||
.TP 8
|
||||
.B -gxtypes\fI|\fP-gno-xtypes
|
||||
Enable (default) or disable support for extended types. Enabling
|
||||
extended types allows for new types that are supported by Icarus
|
||||
Verilog as extensions beyond the baseline Verilog. It may be necessary
|
||||
to disable extended types if compiling code that clashes with the few
|
||||
new keywords used to implement the type system.
|
||||
.TP 8
|
||||
.B -I\fIincludedir\fP
|
||||
Append directory \fIincludedir\fP to list of directories searched
|
||||
for Verilog include files. The \fB-I\fP switch may be used many times
|
||||
@@ -89,8 +74,6 @@ leading or trailing space.
|
||||
Add this module to the list of VPI modules to be loaded by the
|
||||
simulation. Many modules can be specified, and all will be loaded, in
|
||||
the order specified. The system module is implicit and always included.
|
||||
If a System Function Table file (<module>.sft) exists for the module it
|
||||
will be loaded automatically.
|
||||
.TP 8
|
||||
.B -N\fIpath\fP
|
||||
This is used for debugging the compiler proper. Dump the final netlist
|
||||
@@ -201,7 +184,7 @@ implies the synthesis \fB-S\fP flag.
|
||||
|
||||
.SH "WARNING TYPES"
|
||||
These are the types of warnings that can be selected by the \fB-W\fP
|
||||
switch. All the warning types (other than \fBall\fP) can also be
|
||||
switch. All the warning types (other then \fBall\fP) can also be
|
||||
prefixed with \fBno-\fP to turn off that warning. This is most useful
|
||||
after a \fB-Wall\fP argument to suppress isolated warning types.
|
||||
|
||||
@@ -229,6 +212,12 @@ inherit timescale from another file. Both probably mean that
|
||||
timescales are inconsistent, and simulation timing can be confusing
|
||||
and dependent on compilation order.
|
||||
|
||||
.TP 8
|
||||
.B unused
|
||||
This enables warnings for unused variables. This may detect variables
|
||||
that are not assigned, or variables and nets that are not used, or
|
||||
similar possible misuses of variables and nets.
|
||||
|
||||
.SH "SYSTEM FUNCTION TABLE FILES"
|
||||
If the source file name as a \fB.sft\fP suffix, then it is taken to be
|
||||
a system function table file. A System function table file is used to
|
||||
@@ -266,7 +255,7 @@ well as # comments, if the # starts the line.
|
||||
.I "file name"
|
||||
A simple file name or file path is taken to be the name of a Verilog
|
||||
source file. The path starts with the first non-white-space
|
||||
character. Variables are substituted in file names.
|
||||
character. Variables are substitued in file names.
|
||||
|
||||
.TP 8
|
||||
.B -y\ \fIlibdir\fP
|
||||
@@ -321,19 +310,13 @@ become munged.
|
||||
.B +tolower-filename\fP
|
||||
This is similar to the \fB+toupper-filename\fP hack described above.
|
||||
|
||||
.TP 8
|
||||
.B +integer-width+\fIvalue\fP
|
||||
This allows the programmer to select the width for integer variables
|
||||
in the Verilog source. The default is 32, the value can be any desired
|
||||
integer value.
|
||||
|
||||
.SH "VARIABLES IN COMMAND FILES"
|
||||
|
||||
In certain cases, iverilog supports variables in command files. These
|
||||
are strings of the form "$(\fIvarname\fP)", where \fIvarname\fP is the
|
||||
name of the environment variable to read. The entire string is
|
||||
replaced with the contents of that variable. Variables are only
|
||||
substituted in contexts that explicitly support them, including file
|
||||
substitued in contexts that explicitly support them, including file
|
||||
and directory strings.
|
||||
|
||||
Variable values come from the operating system environment, and not
|
||||
|
||||
+195
-171
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2005 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2000-2001 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: main.c,v 1.76 2007/06/05 01:56:12 steve Exp $"
|
||||
#ident "$Id: main.c,v 1.65.2.6 2007/05/30 17:48:26 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -39,7 +39,7 @@ const char NOTICE[] =
|
||||
;
|
||||
|
||||
const char HELP[] =
|
||||
"Usage: iverilog [-ESvV] [-B base] [-c cmdfile] [-g1|-g2|-g2x]\n"
|
||||
"Usage: iverilog [-ESvV] [-B base] [-c cmdfile] [-g1|-g2|-g3.0]\n"
|
||||
" [-D macro[=defn]] [-I includedir] [-M depfile] [-m module]\n"
|
||||
" [-N file] [-o filename] [-p flag=value]\n"
|
||||
" [-s topmodule] [-t target] [-T min|typ|max]\n"
|
||||
@@ -88,6 +88,10 @@ extern const char*optarg;
|
||||
# define IVL_ROOT "."
|
||||
#endif
|
||||
|
||||
#ifndef IVL_ROOT_VARIABLE
|
||||
# define IVL_ROOT_VARIABLE "IVERILOG_ROOT"
|
||||
#endif
|
||||
|
||||
# include "globals.h"
|
||||
#include "cfparse_misc.h" /* cfparse() */
|
||||
|
||||
@@ -107,14 +111,12 @@ const char*npath = 0;
|
||||
const char*targ = "vvp";
|
||||
const char*depfile = 0;
|
||||
|
||||
const char*generation = "2x";
|
||||
const char*gen_specify = "specify";
|
||||
const char*gen_xtypes = "xtypes";
|
||||
const char*generation = "3.0";
|
||||
|
||||
char warning_flags[16] = "";
|
||||
|
||||
unsigned integer_width = 32;
|
||||
|
||||
char*inc_list = 0;
|
||||
char*def_list = 0;
|
||||
char*mod_list = 0;
|
||||
char*command_filename = 0;
|
||||
|
||||
@@ -125,9 +127,6 @@ char*source_path = 0;
|
||||
FILE*source_file = 0;
|
||||
unsigned source_count = 0;
|
||||
|
||||
char*defines_path = 0;
|
||||
FILE*defines_file = 0;
|
||||
|
||||
char*iconfig_path = 0;
|
||||
FILE*iconfig_file = 0;
|
||||
|
||||
@@ -136,6 +135,7 @@ char*iconfig_common_path = iconfig_common_path_buf;
|
||||
|
||||
int synth_flag = 0;
|
||||
int verbose_flag = 0;
|
||||
int command_file = 0;
|
||||
|
||||
FILE *fp;
|
||||
|
||||
@@ -144,48 +144,6 @@ char tmp[MAXSIZE];
|
||||
|
||||
static char ivl_root[MAXSIZE];
|
||||
|
||||
/* Structure to keep a FIFO list of the command files */
|
||||
typedef struct t_command_file {
|
||||
char *filename;
|
||||
struct t_command_file *next;
|
||||
} s_command_file, *p_command_file;
|
||||
p_command_file cmd_file_head = NULL; /* The FIFO head */
|
||||
p_command_file cmd_file_tail = NULL; /* The FIFO tail */
|
||||
|
||||
/* Function to add a comamnd file name to the FIFO. */
|
||||
void add_cmd_file(const char* filename)
|
||||
{
|
||||
p_command_file new;
|
||||
|
||||
new = (p_command_file) malloc(sizeof(s_command_file));
|
||||
new->filename = strdup(filename);
|
||||
new->next = NULL;
|
||||
if (cmd_file_head == NULL) {
|
||||
cmd_file_head = new;
|
||||
cmd_file_tail = new;
|
||||
} else {
|
||||
cmd_file_tail->next = new;
|
||||
cmd_file_tail = new;
|
||||
}
|
||||
}
|
||||
|
||||
/* Function to return the top comamnd file name from the FIFO. */
|
||||
char *get_cmd_file()
|
||||
{
|
||||
char *filename;
|
||||
|
||||
if (cmd_file_head == NULL) filename = NULL;
|
||||
else {
|
||||
p_command_file head;
|
||||
|
||||
filename = cmd_file_head->filename;
|
||||
head = cmd_file_head;
|
||||
cmd_file_head = cmd_file_head->next;
|
||||
free(head);
|
||||
}
|
||||
return filename;
|
||||
}
|
||||
|
||||
#ifdef __MINGW32__
|
||||
# include <io.h>
|
||||
# include <fcntl.h>
|
||||
@@ -308,18 +266,69 @@ static int t_default(char*cmd, unsigned ncmd)
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
char *original_cmd = malloc( strlen( cmd ) + (size_t)1 );
|
||||
strcpy( original_cmd, cmd );
|
||||
|
||||
cmd = realloc( cmd, strlen( original_cmd ) + (size_t)19 ); /* more than enough memory for the ivlpp command and ">/tmp/ivlpp_stdout" */
|
||||
if( cmd == NULL ){
|
||||
exit( EXIT_FAILURE );
|
||||
}
|
||||
|
||||
char *debug_ivl = malloc( strlen( original_cmd ) + (size_t)5 ); /* more than enough memory for "gdb " and ivl program_name */
|
||||
strcpy( debug_ivl, "gdb " );
|
||||
|
||||
static char whitespace[] = " \t\f\r\v\n";
|
||||
char *token;
|
||||
int found_pipe = 0;
|
||||
unsigned long token_counter = 0UL;
|
||||
|
||||
strcpy( cmd, "" );
|
||||
for( token = strtok( original_cmd, whitespace ); token != NULL; token = strtok( NULL, whitespace ) ){
|
||||
|
||||
if( strcmp( token, "|" ) == 0 ){
|
||||
found_pipe = 1;
|
||||
}
|
||||
|
||||
if( found_pipe ){
|
||||
token_counter++;
|
||||
}
|
||||
|
||||
if( token_counter == 0UL ){
|
||||
strcat( cmd, token );
|
||||
strcat( cmd, " " ); /* harmless space after last token, and it was already there anyway */
|
||||
}
|
||||
|
||||
if( token_counter == 2UL ){
|
||||
strcat( debug_ivl, token );
|
||||
}
|
||||
|
||||
if( token_counter > 2UL ){
|
||||
printf( "%s\n", token );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
free( original_cmd );
|
||||
strcat( cmd, ">/tmp/ivlpp_stdout" );
|
||||
#endif
|
||||
|
||||
if (verbose_flag)
|
||||
printf("translate: %s\n", cmd);
|
||||
|
||||
|
||||
rc = system(cmd);
|
||||
if ( ! getenv("IVERILOG_ICONFIG")) {
|
||||
remove(source_path);
|
||||
remove(iconfig_path);
|
||||
remove(defines_path);
|
||||
#ifdef DEBUG
|
||||
if( verbose_flag ){
|
||||
printf( "%s\n", debug_ivl );
|
||||
}
|
||||
|
||||
system( debug_ivl ); /* For simplicity, ignore any return value, which is implementation dependent anyway. */
|
||||
free( debug_ivl );
|
||||
#endif
|
||||
remove(source_path);
|
||||
if ( ! getenv("IVERILOG_ICONFIG"))
|
||||
remove(iconfig_path);
|
||||
if (rc != 0) {
|
||||
if (rc == 127) {
|
||||
fprintf(stderr, "Failed to execute: %s\n", cmd);
|
||||
@@ -340,7 +349,7 @@ static int t_default(char*cmd, unsigned ncmd)
|
||||
static void process_warning_switch(const char*name)
|
||||
{
|
||||
if (strcmp(name,"all") == 0) {
|
||||
strcat(warning_flags, "ipt");
|
||||
strcat(warning_flags, "iptu");
|
||||
|
||||
} else if (strcmp(name,"implicit") == 0) {
|
||||
if (! strchr(warning_flags+2, 'i'))
|
||||
@@ -351,6 +360,9 @@ static void process_warning_switch(const char*name)
|
||||
} else if (strcmp(name,"timescale") == 0) {
|
||||
if (! strchr(warning_flags+2, 't'))
|
||||
strcat(warning_flags, "t");
|
||||
} else if (strcmp(name,"unused") == 0) {
|
||||
if (! strchr(warning_flags+2, 'u'))
|
||||
strcat(warning_flags, "u");
|
||||
} else if (strcmp(name,"no-implicit") == 0) {
|
||||
char*cp = strchr(warning_flags+2, 'i');
|
||||
if (cp) while (*cp) {
|
||||
@@ -369,6 +381,12 @@ static void process_warning_switch(const char*name)
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
} else if (strcmp(name,"no-unused") == 0) {
|
||||
char*cp = strchr(warning_flags+2, 'u');
|
||||
if (cp) while (*cp) {
|
||||
cp[0] = cp[1];
|
||||
cp += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,12 +407,32 @@ void process_library2_switch(const char *name)
|
||||
|
||||
void process_include_dir(const char *name)
|
||||
{
|
||||
fprintf(defines_file, "I:%s\n", name);
|
||||
if (inc_list == 0) {
|
||||
inc_list = malloc(strlen(" -I")+strlen(name)+1);
|
||||
strcpy(inc_list, " -I");
|
||||
strcat(inc_list, name);
|
||||
} else {
|
||||
inc_list = realloc(inc_list, strlen(inc_list)
|
||||
+ strlen(" -I")
|
||||
+ strlen(name) + 1);
|
||||
strcat(inc_list, " -I");
|
||||
strcat(inc_list, name);
|
||||
}
|
||||
}
|
||||
|
||||
void process_define(const char*name)
|
||||
{
|
||||
fprintf(defines_file,"D:%s\n", name);
|
||||
if (def_list == 0) {
|
||||
def_list = malloc(strlen(" -D")+strlen(name)+1);
|
||||
strcpy(def_list, " -D");
|
||||
strcat(def_list, name);
|
||||
} else {
|
||||
def_list = realloc(def_list, strlen(def_list)
|
||||
+ strlen(" -D")
|
||||
+ strlen(name) + 1);
|
||||
strcat(def_list, " -D");
|
||||
strcat(def_list, name);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -403,7 +441,7 @@ void process_define(const char*name)
|
||||
* .sft suffix, and if so pass that as a sys_func file. Otherwise, it
|
||||
* is a Verilog source file to be written into the file list.
|
||||
*/
|
||||
void process_file_name(const char*name, int lib_flag)
|
||||
void process_file_name(const char*name)
|
||||
{
|
||||
if (strlen(name) > 4 && strcasecmp(".sft", name+strlen(name)-4) == 0) {
|
||||
fprintf(iconfig_file,"sys_func:%s\n", name);
|
||||
@@ -411,8 +449,6 @@ void process_file_name(const char*name, int lib_flag)
|
||||
} else {
|
||||
fprintf(source_file, "%s\n", name);
|
||||
source_count += 1;
|
||||
if (lib_flag)
|
||||
fprintf(iconfig_file,"library_file:%s\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,20 +460,8 @@ int process_generation(const char*name)
|
||||
else if (strcmp(name,"2") == 0)
|
||||
generation = "2";
|
||||
|
||||
else if (strcmp(name,"2x") == 0)
|
||||
generation = "2x";
|
||||
|
||||
else if (strcmp(name,"xtypes") == 0)
|
||||
gen_xtypes = "xtypes";
|
||||
|
||||
else if (strcmp(name,"no-xtypes") == 0)
|
||||
gen_xtypes = "no-xtypes";
|
||||
|
||||
else if (strcmp(name,"specify") == 0)
|
||||
gen_specify = "specify";
|
||||
|
||||
else if (strcmp(name,"no-specify") == 0)
|
||||
gen_specify = "no-specify";
|
||||
else if (strcmp(name,"3.0") == 0)
|
||||
generation = "3.0";
|
||||
|
||||
else {
|
||||
fprintf(stderr, "Unknown/Unsupported Language generation "
|
||||
@@ -445,10 +469,7 @@ int process_generation(const char*name)
|
||||
fprintf(stderr, "Supported generations are:\n");
|
||||
fprintf(stderr, " 1 -- IEEE1364-1995 (Verilog 1)\n"
|
||||
" 2 -- IEEE1364-2001 (Verilog 2001)\n"
|
||||
" 2x -- Verilog with extensions\n"
|
||||
"Other generation flags:\n"
|
||||
" specify | no-specify\n"
|
||||
" xtypes | no-xtypes\n");
|
||||
" 3.0 -- SystemVerilog 3.0\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -456,27 +477,12 @@ int process_generation(const char*name)
|
||||
}
|
||||
|
||||
/*
|
||||
* If it exists add the SFT file for the given module.
|
||||
* This function fills in th ivl_root directory with the appropriate
|
||||
* path, based on operating system, build time configuration, and
|
||||
* environment.
|
||||
*/
|
||||
void add_sft_file(const char *module)
|
||||
static char* get_root_dir()
|
||||
{
|
||||
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)
|
||||
fprintf(iconfig_file, "sys_func:%s\n", file);
|
||||
free(file);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char*cmd;
|
||||
unsigned ncmd;
|
||||
int e_flag = 0;
|
||||
int version_flag = 0;
|
||||
int opt, idx, rc;
|
||||
|
||||
#ifdef __MINGW32__
|
||||
{ char * s;
|
||||
char basepath[1024];
|
||||
@@ -503,16 +509,56 @@ int main(int argc, char **argv)
|
||||
s = strrchr(ivl_root, sep);
|
||||
if (s) *s = 0;
|
||||
strcat(ivl_root, "\\lib\\ivl");
|
||||
|
||||
base = ivl_root;
|
||||
}
|
||||
|
||||
#else
|
||||
/* In a UNIX environment, the IVL_ROOT from the Makefile is
|
||||
dependable. It points to the $prefix/lib/ivl directory,
|
||||
where the sub-parts are installed. */
|
||||
strcpy(ivl_root, IVL_ROOT);
|
||||
base = ivl_root;
|
||||
|
||||
{ char*var = 0;
|
||||
|
||||
/* In other systems, use the configured root. */
|
||||
strcpy(ivl_root, IVL_ROOT);
|
||||
|
||||
/* In any case, the IVL_ROOT variable can be used to override
|
||||
the install location at run time. If it is set, use that
|
||||
value instead. */
|
||||
if ( (var = getenv(IVL_ROOT_VARIABLE)) ) {
|
||||
strncpy(ivl_root, var, MAXSIZE);
|
||||
strcat(ivl_root, "/lib/ivl");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return ivl_root;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char*cmd;
|
||||
unsigned ncmd;
|
||||
int e_flag = 0;
|
||||
int version_flag = 0;
|
||||
int opt, idx, rc;
|
||||
|
||||
base = get_root_dir();
|
||||
|
||||
#ifdef __MINGW32__
|
||||
/* Under Windows, there is no point checking the root
|
||||
directory. */
|
||||
#else
|
||||
/* On other systems, check that the root directory seems
|
||||
reasonable. */
|
||||
{ size_t tmp_len = strlen(base) + 16;
|
||||
char* tmp = malloc(tmp_len);
|
||||
snprintf(tmp, tmp_len, "%s%civl", base, sep);
|
||||
|
||||
if (0 != access(tmp, F_OK)) {
|
||||
fprintf(stderr, "%s: INSTALLATION ERROR: Directory %s"
|
||||
" does not contain ivl files.\n", argv[0], base);
|
||||
fprintf(stderr, "%s: : Check installation"
|
||||
" or set " IVL_ROOT_VARIABLE " correctly.\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
free(tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Create a temporary file for communicating input parameters
|
||||
@@ -525,19 +571,6 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
defines_path = strdup(my_tempfile("ivrlg2", &defines_file));
|
||||
if (NULL == defines_file) {
|
||||
fprintf(stderr, "%s: Error opening temporary file %s\n",
|
||||
argv[0], defines_path);
|
||||
fprintf(stderr, "%s: Please check TMP or TMPDIR.\n", argv[0]);
|
||||
|
||||
fclose(source_file);
|
||||
remove(source_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
fprintf(defines_file, "D:__ICARUS__=1\n");
|
||||
|
||||
/* Create another temporary file for passing configuration
|
||||
information to ivl. */
|
||||
|
||||
@@ -558,9 +591,6 @@ int main(int argc, char **argv)
|
||||
fprintf(stderr, "%s: Please check TMP or TMPDIR.\n", argv[0]);
|
||||
fclose(source_file);
|
||||
remove(source_path);
|
||||
|
||||
fclose(defines_file);
|
||||
remove(defines_path);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -579,7 +609,8 @@ int main(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
add_cmd_file(optarg);
|
||||
command_filename = malloc(strlen(optarg)+1);
|
||||
strcpy(command_filename, optarg);
|
||||
break;
|
||||
case 'D':
|
||||
process_define(optarg);
|
||||
@@ -612,7 +643,6 @@ int main(int argc, char **argv)
|
||||
|
||||
case 'm':
|
||||
fprintf(iconfig_file, "module:%s\n", optarg);
|
||||
add_sft_file(optarg);
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
@@ -692,13 +722,11 @@ int main(int argc, char **argv)
|
||||
|
||||
if (mtm != 0) fprintf(iconfig_file, "-T:%s\n", mtm);
|
||||
fprintf(iconfig_file, "generation:%s\n", generation);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_specify);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_xtypes);
|
||||
fprintf(iconfig_file, "warnings:%s\n", warning_flags);
|
||||
fprintf(iconfig_file, "out:%s\n", opath);
|
||||
if (depfile) fprintf(iconfig_file, "depfile:%s\n", depfile);
|
||||
|
||||
while ( (command_filename = get_cmd_file()) ) {
|
||||
if (command_filename) {
|
||||
int rc;
|
||||
|
||||
if (( fp = fopen(command_filename, "r")) == NULL ) {
|
||||
@@ -714,25 +742,17 @@ int main(int argc, char **argv)
|
||||
command_filename);
|
||||
return 1;
|
||||
}
|
||||
free(command_filename);
|
||||
}
|
||||
|
||||
if (depfile) {
|
||||
fprintf(defines_file, "M:%s\n", depfile);
|
||||
}
|
||||
|
||||
/* Finally, process all the remaining words on the command
|
||||
line as file names. */
|
||||
for (idx = optind ; idx < argc ; idx += 1)
|
||||
process_file_name(argv[idx], 0);
|
||||
process_file_name(argv[idx]);
|
||||
|
||||
|
||||
fclose(source_file);
|
||||
source_file = 0;
|
||||
|
||||
fclose(defines_file);
|
||||
defines_file = 0;
|
||||
|
||||
if (source_count == 0) {
|
||||
fprintf(stderr, "%s: No input files.\n", argv[0]);
|
||||
fprintf(stderr, "%s\n", HELP);
|
||||
@@ -742,14 +762,33 @@ int main(int argc, char **argv)
|
||||
|
||||
/* Start building the preprocess command line. */
|
||||
|
||||
sprintf(tmp, "%s%civlpp %s%s -F%s -f%s ", pbase,sep,
|
||||
sprintf(tmp, "%s%civlpp %s%s -D__ICARUS__=1 -f%s ", pbase,sep,
|
||||
verbose_flag?" -v":"",
|
||||
e_flag?"":" -L", defines_path, source_path);
|
||||
e_flag?"":" -L", source_path);
|
||||
|
||||
ncmd = strlen(tmp);
|
||||
cmd = malloc(ncmd + 1);
|
||||
strcpy(cmd, tmp);
|
||||
|
||||
if (inc_list) {
|
||||
cmd = realloc(cmd, ncmd + strlen(inc_list) + 1);
|
||||
strcat(cmd, inc_list);
|
||||
ncmd += strlen(inc_list);
|
||||
}
|
||||
|
||||
if (def_list) {
|
||||
cmd = realloc(cmd, ncmd + strlen(def_list) + 1);
|
||||
strcat(cmd, def_list);
|
||||
ncmd += strlen(def_list);
|
||||
}
|
||||
|
||||
if (depfile) {
|
||||
cmd = realloc(cmd, ncmd + strlen(depfile) + 5);
|
||||
strcat(cmd, " -M ");
|
||||
strcat(cmd, depfile);
|
||||
ncmd += strlen(depfile) + 4;
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
@@ -784,13 +823,13 @@ int main(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(iconfig_file, "iwidth:%u\n", integer_width);
|
||||
|
||||
/* Write the preprocessor command needed to preprocess a
|
||||
single file. This may be used to preprocess library
|
||||
files. */
|
||||
fprintf(iconfig_file, "ivlpp:%s%civlpp -L -F%s\n",
|
||||
pbase, sep, defines_path);
|
||||
fprintf(iconfig_file, "ivlpp:%s%civlpp -D__ICARUS__ -L %s %s\n",
|
||||
pbase, sep,
|
||||
inc_list? inc_list : "",
|
||||
def_list? def_list : "");
|
||||
|
||||
/* Done writing to the iconfig file. Close it now. */
|
||||
fclose(iconfig_file);
|
||||
@@ -802,38 +841,23 @@ int main(int argc, char **argv)
|
||||
|
||||
/*
|
||||
* $Log: main.c,v $
|
||||
* Revision 1.76 2007/06/05 01:56:12 steve
|
||||
* Bring in .SFT file automatically if -m used.
|
||||
* Revision 1.65.2.6 2007/05/30 17:48:26 steve
|
||||
* DEBUG aids. (Alan Feldstein)
|
||||
*
|
||||
* Revision 1.75 2007/04/19 02:52:53 steve
|
||||
* Add support for -v flag in command file.
|
||||
* Revision 1.65.2.5 2006/07/07 21:31:50 steve
|
||||
* Root dir variable does not include lib/ivl components.
|
||||
*
|
||||
* Revision 1.74 2007/04/18 03:23:38 steve
|
||||
* Add support for multiple command files. (Cary R.)
|
||||
* Revision 1.65.2.4 2006/06/27 01:30:20 steve
|
||||
* Fix unused var warning for mingw32 build.
|
||||
*
|
||||
* Revision 1.73 2007/03/07 04:24:59 steve
|
||||
* Make integer width controllable.
|
||||
* Revision 1.65.2.3 2006/06/14 03:01:49 steve
|
||||
* Remove redundant call to get_root_dir.
|
||||
*
|
||||
* Revision 1.72 2006/10/02 18:15:47 steve
|
||||
* Fix handling of dep path in new argument passing method.
|
||||
* Revision 1.65.2.2 2006/06/12 00:16:53 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.71 2006/09/28 04:35:18 steve
|
||||
* Support selective control of specify and xtypes features.
|
||||
*
|
||||
* Revision 1.70 2006/09/20 22:30:52 steve
|
||||
* Do not pass -D__ICARUS__ to ivlpp.
|
||||
*
|
||||
* Revision 1.69 2006/07/26 00:11:40 steve
|
||||
* Pass depfiles through temp defines file.
|
||||
*
|
||||
* Revision 1.68 2006/07/26 00:02:48 steve
|
||||
* Pass defines and includes through temp file.
|
||||
*
|
||||
* Revision 1.67 2005/07/14 23:38:44 steve
|
||||
* Display as version 0.9.devel
|
||||
*
|
||||
* Revision 1.66 2005/06/28 04:25:55 steve
|
||||
* Remove reference to SystemVerilog.
|
||||
* Revision 1.65.2.1 2006/03/26 21:47:26 steve
|
||||
* More installation directory flexibility.
|
||||
*
|
||||
* Revision 1.65 2004/06/17 14:47:22 steve
|
||||
* Add a .sft file for the system functions.
|
||||
|
||||
+21
-14
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: dup_expr.cc,v 1.21 2006/11/04 06:10:13 steve Exp $"
|
||||
#ident "$Id: dup_expr.cc,v 1.18.2.2 2006/11/02 02:13:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -29,6 +29,7 @@ NetEBComp* NetEBComp::dup_expr() const
|
||||
{
|
||||
NetEBComp*result = new NetEBComp(op_, left_->dup_expr(),
|
||||
right_->dup_expr());
|
||||
result->set_line(*this);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -67,8 +68,7 @@ NetEScope* NetEScope::dup_expr() const
|
||||
|
||||
NetESelect* NetESelect::dup_expr() const
|
||||
{
|
||||
return new NetESelect(expr_->dup_expr(),
|
||||
base_? base_->dup_expr() : 0,
|
||||
return new NetESelect(expr_->dup_expr(), base_->dup_expr(),
|
||||
expr_width());
|
||||
}
|
||||
|
||||
@@ -88,9 +88,10 @@ NetESFunc* NetESFunc::dup_expr() const
|
||||
|
||||
NetESignal* NetESignal::dup_expr() const
|
||||
{
|
||||
NetESignal*tmp = new NetESignal(net_);
|
||||
NetESignal*tmp = new NetESignal(net_, msi_, lsi_);
|
||||
assert(tmp);
|
||||
tmp->expr_width(expr_width());
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -112,9 +113,14 @@ NetEUFunc* NetEUFunc::dup_expr() const
|
||||
tmp_parms[idx] = parms_[idx]->dup_expr();
|
||||
}
|
||||
|
||||
tmp = new NetEUFunc(func_, result_sig_->dup_expr(), tmp_parms);
|
||||
tmp = 0;
|
||||
if (result_sig_)
|
||||
tmp = new NetEUFunc(func_, result_sig_->dup_expr(), tmp_parms);
|
||||
if (result_var_)
|
||||
tmp = new NetEUFunc(func_, result_var_->dup_expr(), tmp_parms);
|
||||
|
||||
assert(tmp);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -132,18 +138,19 @@ NetEUReduce* NetEUReduce::dup_expr() const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetEVariable* NetEVariable::dup_expr() const
|
||||
{
|
||||
NetEVariable*tmp = new NetEVariable(var_);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: dup_expr.cc,v $
|
||||
* Revision 1.21 2006/11/04 06:10:13 steve
|
||||
* Handle dup of pad as well as normal select.
|
||||
* Revision 1.18.2.2 2006/11/02 02:13:15 steve
|
||||
* Error message for condit expression not synthesized.
|
||||
*
|
||||
* Revision 1.20 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.19 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
* Revision 1.18.2.1 2006/06/12 00:16:50 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.18 2004/06/17 16:06:18 steve
|
||||
* Help system function signedness survive elaboration.
|
||||
|
||||
+4
-15
@@ -17,7 +17,7 @@
|
||||
* 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 $"
|
||||
#ident "$Id: elab_anet.cc,v 1.10 2004/10/04 01:10:52 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -84,18 +84,15 @@ NetNet* PEConcat::elaborate_anet(Design*des, NetScope*scope) const
|
||||
concat operator from least significant to most significant,
|
||||
which is opposite from how they are given in the list.
|
||||
|
||||
Allow for a repeat count other than 1 by repeating the
|
||||
Allow for a repeat count other then 1 by repeating the
|
||||
connect loop as many times as necessary. */
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT_REG, pins);
|
||||
/* Assume that all the data types are the same. */
|
||||
osig->data_type(nets[0]->data_type());
|
||||
|
||||
pins = 0;
|
||||
for (unsigned idx = nets.count() ; idx > 0 ; idx -= 1) {
|
||||
NetNet*cur = nets[idx-1];
|
||||
assert(cur->data_type() == osig->data_type());
|
||||
for (unsigned pin = 0; pin < cur->pin_count(); pin += 1) {
|
||||
connect(osig->pin(pins), cur->pin(pin));
|
||||
pins += 1;
|
||||
@@ -112,10 +109,11 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
|
||||
|
||||
NetNet* sig = 0;
|
||||
NetMemory* mem = 0;
|
||||
NetVariable* var = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(des, scope, path_, sig, mem, par, eve);
|
||||
symbol_search(des, scope, path_, sig, mem, var, par, eve);
|
||||
|
||||
|
||||
if (mem != 0) {
|
||||
@@ -169,15 +167,6 @@ NetNet* PEIdent::elaborate_anet(Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $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.
|
||||
*
|
||||
|
||||
+379
-1173
File diff suppressed because it is too large
Load Diff
+196
-314
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2006 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_lval.cc,v 1.44 2007/06/02 03:42:12 steve Exp $"
|
||||
#ident "$Id: elab_lval.cc,v 1.29 2004/10/04 01:10:52 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -25,9 +25,8 @@
|
||||
# include "PExpr.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "compiler.h"
|
||||
|
||||
# include <iostream>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
/*
|
||||
* These methods generate a NetAssign_ object for the l-value of the
|
||||
@@ -67,9 +66,7 @@
|
||||
* is to try to make a net elaboration, and see if the result is
|
||||
* suitable for assignment.
|
||||
*/
|
||||
NetAssign_* PExpr::elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const
|
||||
NetAssign_* PExpr::elaborate_lval(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetNet*ll = 0;
|
||||
if (ll == 0) {
|
||||
@@ -95,9 +92,7 @@ NetAssign_* PExpr::elaborate_lval(Design*des,
|
||||
* a is the MSB and b the LSB. Connect the LSB to the low pins of the
|
||||
* NetAssign_ object.
|
||||
*/
|
||||
NetAssign_* PEConcat::elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const
|
||||
NetAssign_* PEConcat::elaborate_lval(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (repeat_) {
|
||||
cerr << get_line() << ": error: Repeat concatenations make "
|
||||
@@ -117,7 +112,7 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
|
||||
continue;
|
||||
}
|
||||
|
||||
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope, is_force);
|
||||
NetAssign_*tmp = parms_[idx]->elaborate_lval(des, scope);
|
||||
|
||||
/* If the l-value doesn't elaborate, the error was
|
||||
already detected and printed. We just skip it and let
|
||||
@@ -145,68 +140,41 @@ NetAssign_* PEConcat::elaborate_lval(Design*des,
|
||||
* Handle the ident as an l-value. This includes bit and part selects
|
||||
* of that ident.
|
||||
*/
|
||||
NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
NetScope*scope,
|
||||
bool is_force) const
|
||||
NetAssign_* PEIdent::elaborate_lval(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetNet* reg = 0;
|
||||
NetMemory* mem = 0;
|
||||
NetVariable* var = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(des, scope, path_, reg, par, eve);
|
||||
symbol_search(des, scope, path_, reg, mem, var, par, eve);
|
||||
|
||||
if (mem) {
|
||||
return elaborate_mem_lval_(des, scope, mem);
|
||||
}
|
||||
|
||||
if (var) {
|
||||
NetAssign_*cur = new NetAssign_(var);
|
||||
return cur;
|
||||
}
|
||||
|
||||
if (reg == 0) {
|
||||
cerr << get_line() << ": error: Could not find variable ``"
|
||||
<< path_ << "'' in ``" << scope_path(scope) <<
|
||||
<< path_ << "'' in ``" << scope->name() <<
|
||||
"''" << endl;
|
||||
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
ivl_assert(*this, reg);
|
||||
|
||||
const name_component_t&name_tail = path_.back();
|
||||
|
||||
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
|
||||
if (!name_tail.index.empty())
|
||||
use_sel = name_tail.index.back().sel;
|
||||
|
||||
// This is the special case that the l-value is an entire
|
||||
// memory. This is, in fact, an error.
|
||||
if (reg->array_dimensions() > 0 && name_tail.index.empty()) {
|
||||
cerr << get_line() << ": error: Cannot assign to array "
|
||||
<< path_ << ". Did you forget a word index?" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (reg->array_dimensions() > 0)
|
||||
return elaborate_lval_net_word_(des, scope, reg);
|
||||
|
||||
if (use_sel == index_component_t::SEL_PART) {
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_part_(des, scope, lv);
|
||||
return lv;
|
||||
}
|
||||
|
||||
if (use_sel == index_component_t::SEL_IDX_UP) {
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_idx_up_(des, scope, lv);
|
||||
return lv;
|
||||
}
|
||||
|
||||
if (use_sel == index_component_t::SEL_IDX_DO) {
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
elaborate_lval_net_idx_do_(des, scope, lv);
|
||||
return lv;
|
||||
}
|
||||
assert(reg);
|
||||
|
||||
/* Get the signal referenced by the identifier, and make sure
|
||||
it is a register. Wires are not allows in this context,
|
||||
unless this is the l-value of a force. */
|
||||
if ((reg->type() != NetNet::REG) && !is_force) {
|
||||
it is a register. (Wires are not allows in this context. */
|
||||
if (reg->type() != NetNet::REG) {
|
||||
cerr << get_line() << ": error: " << path_ <<
|
||||
" is not a valid l-value in " << scope_path(scope) <<
|
||||
" is not a reg/integer/time in " << scope->name() <<
|
||||
"." << endl;
|
||||
cerr << reg->get_line() << ": : " << path_ <<
|
||||
" is declared here as " << reg->type() << "." << endl;
|
||||
@@ -217,29 +185,57 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
long msb, lsb;
|
||||
NetExpr*mux;
|
||||
|
||||
if (use_sel == index_component_t::SEL_BIT) {
|
||||
if (msb_ && lsb_) {
|
||||
/* This handles part selects. In this case, there are
|
||||
two bit select expressions, and both must be
|
||||
constant. Evaluate them and pass the results back to
|
||||
the caller. */
|
||||
verinum*vl = lsb_->eval_const(des, scope);
|
||||
if (vl == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
"Part select expressions must be constant."
|
||||
<< endl;
|
||||
cerr << lsb_->get_line() << ": : This lsb expression "
|
||||
"violates the rule: " << *lsb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
verinum*vm = msb_->eval_const(des, scope);
|
||||
if (vm == 0) {
|
||||
cerr << msb_->get_line() << ": error: "
|
||||
"Part select expressions must be constant."
|
||||
<< endl;
|
||||
cerr << msb_->get_line() << ": : This msb expression "
|
||||
"violates the rule: " << *msb_ << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
ivl_assert(*this, index_tail.lsb == 0);
|
||||
msb = vm->as_long();
|
||||
lsb = vl->as_long();
|
||||
mux = 0;
|
||||
|
||||
} else if (msb_) {
|
||||
|
||||
/* 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 {
|
||||
assert(lsb_ == 0);
|
||||
verinum*v = msb_->eval_const(des, scope);
|
||||
if (v == 0) {
|
||||
NetExpr*m = msb_->elaborate_expr(des, scope);
|
||||
assert(m);
|
||||
msb = 0;
|
||||
lsb = 0;
|
||||
mux = index_expr;
|
||||
mux = m;
|
||||
|
||||
} else {
|
||||
|
||||
msb = v->as_long();
|
||||
lsb = v->as_long();
|
||||
mux = 0;
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -247,6 +243,8 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
/* No select expressions, so presume a part select the
|
||||
width of the register. */
|
||||
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
msb = reg->msb();
|
||||
lsb = reg->lsb();
|
||||
mux = 0;
|
||||
@@ -261,19 +259,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
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);
|
||||
lv->set_bmux(mux);
|
||||
|
||||
} else {
|
||||
|
||||
@@ -297,7 +283,7 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
converted to normalized form so is relative the
|
||||
variable pins. */
|
||||
|
||||
if ((wid + loff) > reg->vector_width()) {
|
||||
if ((wid + loff) > reg->pin_count()) {
|
||||
cerr << get_line() << ": error: bit/part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
@@ -306,191 +292,57 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
}
|
||||
|
||||
lv = new NetAssign_(reg);
|
||||
lv->set_part(new NetEConst(verinum(loff)), wid);
|
||||
lv->set_part(loff, wid);
|
||||
|
||||
assert(moff < reg->pin_count());
|
||||
}
|
||||
|
||||
|
||||
return lv;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*reg) const
|
||||
NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
NetMemory*mem) const
|
||||
{
|
||||
const name_component_t&name_tail = path_.back();
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
|
||||
const index_component_t&index_head = name_tail.index.front();
|
||||
ivl_assert(*this, index_head.sel == index_component_t::SEL_BIT);
|
||||
ivl_assert(*this, index_head.msb != 0);
|
||||
ivl_assert(*this, index_head.lsb == 0);
|
||||
|
||||
NetExpr*word = elab_and_eval(des, scope, index_head.msb, -1);
|
||||
|
||||
// If there is a non-zero base to the memory, then build an
|
||||
// expression to calculate the canonical address.
|
||||
if (long base = reg->array_first()) {
|
||||
|
||||
word = make_add_expr(word, 0-base);
|
||||
if (NetExpr*tmp = word->eval_tree()) {
|
||||
word = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
lv->set_word(word);
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: Set array word=" << *word << endl;
|
||||
|
||||
// Test for the case that the index is a constant, and is out
|
||||
// of bounds. The "word" expression is the word index already
|
||||
// converted to canonical address, so this just needs to check
|
||||
// that the address is not too big.
|
||||
if (NetEConst*word_const = dynamic_cast<NetEConst*>(word)) {
|
||||
verinum word_val = word_const->value();
|
||||
long index = word_val.as_long();
|
||||
if (index < 0 || index >= reg->array_count()) {
|
||||
cerr << get_line() << ": warning: Constant array index "
|
||||
<< (index + reg->array_first())
|
||||
<< " is out of range for array "
|
||||
<< reg->name() << "." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
/* An array word may also have part selects applied to them. */
|
||||
|
||||
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
|
||||
if (name_tail.index.size() > 1)
|
||||
use_sel = name_tail.index.back().sel;
|
||||
|
||||
if (use_sel == index_component_t::SEL_PART)
|
||||
elaborate_lval_net_part_(des, scope, lv);
|
||||
|
||||
if (use_sel == index_component_t::SEL_IDX_UP)
|
||||
elaborate_lval_net_idx_up_(des, scope, lv);
|
||||
|
||||
if (use_sel == index_component_t::SEL_IDX_DO)
|
||||
elaborate_lval_net_idx_do_(des, scope, lv);
|
||||
|
||||
return lv;
|
||||
}
|
||||
|
||||
bool PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
NetScope*scope,
|
||||
NetAssign_*lv) const
|
||||
{
|
||||
long msb, lsb;
|
||||
bool flag = calculate_parts_(des, scope, msb, lsb);
|
||||
if (!flag)
|
||||
return false;
|
||||
|
||||
NetNet*reg = lv->sig();
|
||||
assert(reg);
|
||||
|
||||
if (msb == reg->msb() && lsb == reg->lsb()) {
|
||||
|
||||
/* No bit select, and part select covers the entire
|
||||
vector. Simplest case. */
|
||||
|
||||
} 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_line() << ": error: part select "
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is reversed." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 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_line() << ": 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);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PEIdent::elaborate_lval_net_idx_up_(Design*des,
|
||||
NetScope*scope,
|
||||
NetAssign_*lv) const
|
||||
{
|
||||
const name_component_t&name_tail = path_.back();;
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
ivl_assert(*this, index_tail.lsb != 0);
|
||||
|
||||
NetNet*reg = lv->sig();
|
||||
assert(reg);
|
||||
|
||||
if (reg->type() != NetNet::REG) {
|
||||
cerr << get_line() << ": error: " << path_ <<
|
||||
" is not a reg/integer/time in " << scope_path(scope) <<
|
||||
"." << endl;
|
||||
cerr << reg->get_line() << ": : " << path_ <<
|
||||
" is declared here as " << reg->type() << "." << endl;
|
||||
if (msb_ == 0) {
|
||||
cerr << get_line() << ": error: Assign to memory \""
|
||||
<< mem->name() << "\" requires a word select index."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned long wid;
|
||||
calculate_up_do_width_(des, scope, wid);
|
||||
if (msb_ && lsb_) {
|
||||
cerr << get_line() << ": error: Cannot use part select on "
|
||||
<< "memory \"" << mem->name() << ".\"" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
assert(msb_ && !lsb_);
|
||||
|
||||
/* Correct the mux for the range of the vector. */
|
||||
if (reg->msb() < reg->lsb())
|
||||
base = make_sub_expr(reg->lsb(), base);
|
||||
else if (reg->lsb() != 0)
|
||||
base = make_add_expr(base, - reg->lsb());
|
||||
NetExpr*ix = msb_->elaborate_expr(des, scope);
|
||||
if (ix == 0)
|
||||
return 0;
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: Set part select width="
|
||||
<< wid << ", base=" << *base << endl;
|
||||
/* Evaluate the memory index expression down as must as
|
||||
possible. Ideally, we can get it down to a constant. */
|
||||
if (! dynamic_cast<NetEConst*>(ix)) {
|
||||
NetExpr*tmp = ix->eval_tree();
|
||||
if (tmp) {
|
||||
tmp->set_line(*ix);
|
||||
delete ix;
|
||||
ix = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
lv->set_part(base, wid);
|
||||
|
||||
return true;
|
||||
NetAssign_*lv = new NetAssign_(mem);
|
||||
lv->set_bmux(ix);
|
||||
lv->set_part(0, mem->width());
|
||||
return lv;
|
||||
}
|
||||
|
||||
bool PEIdent::elaborate_lval_net_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
NetAssign_*lv) const
|
||||
{
|
||||
const name_component_t&name_tail = path_.back();;
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
ivl_assert(*this, index_tail.lsb != 0);
|
||||
|
||||
cerr << get_line() << ": internal error: don't know how to "
|
||||
"deal with SEL_IDX_DO in lval?" << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
|
||||
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*) const
|
||||
{
|
||||
cerr << get_line() << ": error: Constant values not allowed "
|
||||
<< "in l-value expressions." << endl;
|
||||
@@ -500,66 +352,6 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
|
||||
|
||||
/*
|
||||
* $Log: elab_lval.cc,v $
|
||||
* Revision 1.44 2007/06/02 03:42:12 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.43 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.42 2007/03/14 05:06:49 steve
|
||||
* Replace some asserts with ivl_asserts.
|
||||
*
|
||||
* Revision 1.41 2007/03/05 05:59:10 steve
|
||||
* Handle processes within generate loops.
|
||||
*
|
||||
* Revision 1.40 2007/02/27 05:14:38 steve
|
||||
* Detect and warn about lval array index out fo bounds.
|
||||
*
|
||||
* Revision 1.39 2007/02/01 05:25:26 steve
|
||||
* Error message better reflects more general reality.
|
||||
*
|
||||
* Revision 1.38 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.37 2006/11/04 06:19:25 steve
|
||||
* Remove last bits of relax_width methods, and use test_width
|
||||
* to calculate the width of an r-value expression that may
|
||||
* contain unsized numbers.
|
||||
*
|
||||
* Revision 1.36 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.35 2006/04/16 00:54:04 steve
|
||||
* Cleanup lval part select handling.
|
||||
*
|
||||
* Revision 1.34 2006/04/16 00:15:43 steve
|
||||
* Fix part selects in l-values.
|
||||
*
|
||||
* Revision 1.33 2006/02/02 02:43:57 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.32 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.31 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.30 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.29 2004/10/04 01:10:52 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
@@ -568,5 +360,95 @@ NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
|
||||
*
|
||||
* Revision 1.27 2003/09/19 03:30:05 steve
|
||||
* Fix name search in elab_lval.
|
||||
*
|
||||
* Revision 1.26 2003/01/27 05:09:17 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.25 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.24 2003/01/19 00:35:39 steve
|
||||
* Detect null arguments to concatenation operator.
|
||||
*
|
||||
* Revision 1.23 2002/11/21 23:27:51 steve
|
||||
* Precalculate indices to l-value arrays.
|
||||
*
|
||||
* Revision 1.22 2002/11/21 18:15:40 steve
|
||||
* Fix const test of msb in assignment l-values.
|
||||
*
|
||||
* Revision 1.21 2002/11/02 01:10:49 steve
|
||||
* Detect memories without work index in l-value.
|
||||
*
|
||||
* Revision 1.20 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.19 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.18 2002/03/09 04:02:26 steve
|
||||
* Constant expressions are not l-values for task ports.
|
||||
*
|
||||
* Revision 1.17 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
*
|
||||
* Revision 1.16 2001/11/08 05:15:50 steve
|
||||
* Remove string paths from PExpr elaboration.
|
||||
*
|
||||
* Revision 1.15 2001/11/07 04:01:59 steve
|
||||
* eval_const uses scope instead of a string path.
|
||||
*
|
||||
* Revision 1.14 2001/08/25 23:50:02 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.13 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.12 2001/02/09 03:16:48 steve
|
||||
* Report bit/part select out of range errors. (PR#133)
|
||||
*
|
||||
* Revision 1.11 2001/01/10 03:13:23 steve
|
||||
* Build task outputs as lval instead of nets. (PR#98)
|
||||
*
|
||||
* Revision 1.10 2001/01/06 06:31:58 steve
|
||||
* declaration initialization for time variables.
|
||||
*
|
||||
* Revision 1.9 2001/01/06 02:29:36 steve
|
||||
* Support arrays of integers.
|
||||
*
|
||||
* Revision 1.8 2000/12/12 06:14:51 steve
|
||||
* sorry for concatenated memories in l-values. (PR#76)
|
||||
*
|
||||
* Revision 1.7 2000/12/01 02:55:37 steve
|
||||
* Detect part select errors on l-values.
|
||||
*
|
||||
* Revision 1.6 2000/10/31 17:49:02 steve
|
||||
* Support time variables.
|
||||
*
|
||||
* Revision 1.5 2000/10/26 17:09:46 steve
|
||||
* Fix handling of errors in behavioral lvalues. (PR#28)
|
||||
*
|
||||
* Revision 1.4 2000/09/10 15:43:59 steve
|
||||
* Some error checking.
|
||||
*
|
||||
* Revision 1.3 2000/09/10 03:59:59 steve
|
||||
* Agressively merge NetAssign_ within concatenations.
|
||||
*
|
||||
* Revision 1.2 2000/09/10 02:18:16 steve
|
||||
* elaborate complex l-values
|
||||
*
|
||||
* Revision 1.1 2000/09/09 15:21:26 steve
|
||||
* move lval elaboration to PExpr virtual methods.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+1115
-1648
File diff suppressed because it is too large
Load Diff
+20
-58
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_pexpr.cc,v 1.28 2007/06/02 03:42:12 steve Exp $"
|
||||
#ident "$Id: elab_pexpr.cc,v 1.21 2004/02/20 06:22:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -25,7 +25,6 @@
|
||||
# include "PExpr.h"
|
||||
# include "compiler.h"
|
||||
# include "util.h"
|
||||
# include "netmisc.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
@@ -54,7 +53,7 @@ NetExpr*PEBinary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp, -1);
|
||||
NetEBinary*tmp = elaborate_expr_base_(des, lp, rp);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
@@ -120,7 +119,7 @@ NetEConcat* PEConcat::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
|
||||
NetExpr*PEFNumber::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
return elaborate_expr(des, scope, -1, false);
|
||||
return elaborate_expr(des, scope);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -131,53 +130,42 @@ NetExpr*PEFNumber::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
*/
|
||||
NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
pform_name_t path = path_;
|
||||
name_component_t name_tail = path_.back();
|
||||
path.pop_back();
|
||||
hname_t path = path_;
|
||||
char*name = path.remove_tail_name();
|
||||
|
||||
NetScope*pscope = scope;
|
||||
if (path_.size() > 0) {
|
||||
list<hname_t> tmp = eval_scope_path(des, scope, path);
|
||||
pscope = des->find_scope(scope, tmp);
|
||||
}
|
||||
if (path.peek_name(0))
|
||||
pscope = des->find_scope(scope, path);
|
||||
|
||||
const NetExpr*ex_msb;
|
||||
const NetExpr*ex_lsb;
|
||||
const NetExpr*ex = pscope->get_parameter(name_tail.name, ex_msb, ex_lsb);
|
||||
perm_string perm_name = lex_strings.make(name);
|
||||
delete name;
|
||||
|
||||
const NetExpr*ex = pscope->get_parameter(perm_name);
|
||||
if (ex == 0) {
|
||||
cerr << get_line() << ": error: identifier ``" << name_tail.name <<
|
||||
"'' is not a parameter in "<< scope_path(scope)<< "." << endl;
|
||||
cerr << get_line() << ": error: identifier ``" << path_ <<
|
||||
"'' is not a parameter in " << scope->name() << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr*res = new NetEParam(des, pscope, name_tail.name);
|
||||
NetExpr*res = new NetEParam(des, pscope, perm_name);
|
||||
res->set_line(*this);
|
||||
assert(res);
|
||||
|
||||
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
|
||||
if (!name_tail.index.empty())
|
||||
use_sel = name_tail.index.back().sel;
|
||||
|
||||
switch (use_sel) {
|
||||
case index_component_t::SEL_NONE:
|
||||
break;
|
||||
default:
|
||||
case index_component_t::SEL_PART:
|
||||
assert(idx_ == 0);
|
||||
if (msb_ && lsb_) {
|
||||
cerr << get_line() << ": sorry: Cannot part select "
|
||||
"bits of parameters." << endl;
|
||||
des->errors += 1;
|
||||
break;
|
||||
|
||||
case index_component_t::SEL_BIT:
|
||||
} else if (msb_) {
|
||||
|
||||
/* We have here a bit select. Insert a NetESelect node
|
||||
to handle it. */
|
||||
NetExpr*tmp = name_tail.index.back().msb->elaborate_pexpr(des, scope);
|
||||
NetExpr*tmp = msb_->elaborate_pexpr(des, scope);
|
||||
if (tmp != 0) {
|
||||
res = new NetESelect(res, tmp, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -188,13 +176,13 @@ NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
*/
|
||||
NetExpr*PENumber::elaborate_pexpr(Design*des, NetScope*sc) const
|
||||
{
|
||||
return elaborate_expr(des, sc, -1, false);
|
||||
return elaborate_expr(des, sc);
|
||||
}
|
||||
|
||||
|
||||
NetEConst* PEString::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
return elaborate_expr(des, scope, -1, false);
|
||||
return elaborate_expr(des, scope);
|
||||
}
|
||||
|
||||
NetETernary* PETernary::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
@@ -243,32 +231,6 @@ NetExpr*PEUnary::elaborate_pexpr (Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_pexpr.cc,v $
|
||||
* Revision 1.28 2007/06/02 03:42:12 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.27 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.26 2007/04/26 03:06:22 steve
|
||||
* Rework hname_t to use perm_strings.
|
||||
*
|
||||
* Revision 1.25 2006/11/04 06:19:25 steve
|
||||
* Remove last bits of relax_width methods, and use test_width
|
||||
* to calculate the width of an r-value expression that may
|
||||
* contain unsized numbers.
|
||||
*
|
||||
* Revision 1.24 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.23 2006/02/02 02:43:58 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
* Revision 1.22 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
* Revision 1.21 2004/02/20 06:22:56 steve
|
||||
* parameter keys are per_strings.
|
||||
*
|
||||
|
||||
+75
-232
@@ -17,12 +17,11 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_scope.cc,v 1.46 2007/06/02 03:42:12 steve Exp $"
|
||||
#ident "$Id: elab_scope.cc,v 1.35 2004/09/10 00:15:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "compiler.h"
|
||||
# include "netmisc.h"
|
||||
# include <iostream>
|
||||
# include <stdio.h>
|
||||
|
||||
@@ -34,10 +33,10 @@
|
||||
*/
|
||||
|
||||
# include "Module.h"
|
||||
# include "PData.h"
|
||||
# include "PEvent.h"
|
||||
# include "PExpr.h"
|
||||
# include "PGate.h"
|
||||
# include "PGenerate.h"
|
||||
# include "PTask.h"
|
||||
# include "PWire.h"
|
||||
# include "Statement.h"
|
||||
@@ -46,12 +45,11 @@
|
||||
# include <typeinfo>
|
||||
# include <assert.h>
|
||||
|
||||
bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
const replace_t&replacements) const
|
||||
bool Module::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (debug_scopes) {
|
||||
cerr << get_line() << ": debug: Elaborate scope "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
<< scope->name() << "." << endl;
|
||||
}
|
||||
|
||||
// Generate all the parameters that this instance of this
|
||||
@@ -66,7 +64,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
// place of the elaborated expression.
|
||||
|
||||
typedef map<perm_string,param_expr_t>::const_iterator mparm_it_t;
|
||||
typedef map<pform_name_t,PExpr*>::const_iterator pform_parm_it_t;
|
||||
typedef map<hname_t,PExpr*>::const_iterator hparm_it_t;
|
||||
|
||||
|
||||
// This loop scans the parameters in the module, and creates
|
||||
@@ -77,7 +75,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
|
||||
NetEParam*tmp = new NetEParam;
|
||||
tmp->set_line(*((*cur).second.expr));
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
if ((*cur).second.msb)
|
||||
tmp->cast_signed( (*cur).second.signed_flag );
|
||||
|
||||
scope->set_parameter((*cur).first, tmp, 0, 0, false);
|
||||
}
|
||||
@@ -108,7 +107,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
NetExpr*val = ex->elaborate_pexpr(des, scope);
|
||||
NetExpr*msb = 0;
|
||||
NetExpr*lsb = 0;
|
||||
bool signed_flag = (*cur).second.signed_flag;
|
||||
bool signed_flag = false;
|
||||
|
||||
/* If the parameter declaration includes msb and lsb,
|
||||
then use them to calculate a width for the
|
||||
@@ -119,47 +118,16 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
msb = (*cur).second.msb ->elaborate_pexpr(des, scope);
|
||||
assert(msb);
|
||||
lsb = (*cur).second.lsb ->elaborate_pexpr(des, scope);
|
||||
signed_flag = (*cur).second.signed_flag;
|
||||
}
|
||||
|
||||
if (signed_flag) {
|
||||
/* If explicitly signed, then say so. */
|
||||
val->cast_signed(true);
|
||||
} else if ((*cur).second.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->cast_signed(signed_flag);
|
||||
val = scope->set_parameter((*cur).first, val,
|
||||
msb, lsb, signed_flag);
|
||||
assert(val);
|
||||
delete val;
|
||||
}
|
||||
|
||||
/* run parameter replacements that were collected from the
|
||||
containing scope and meant for me. */
|
||||
for (replace_t::const_iterator cur = replacements.begin()
|
||||
; cur != replacements.end() ; cur ++) {
|
||||
|
||||
NetExpr*val = (*cur).second;
|
||||
if (debug_scopes) {
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Replace " << (*cur).first
|
||||
<< " with expression " << *val
|
||||
<< " from " << val->get_line() << "." << endl;
|
||||
}
|
||||
bool flag = scope->replace_parameter((*cur).first, val);
|
||||
if (! flag) {
|
||||
cerr << val->get_line() << ": warning: parameter "
|
||||
<< (*cur).first << " not found in "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
for (mparm_it_t cur = localparams.begin()
|
||||
; cur != localparams.end() ; cur ++) {
|
||||
|
||||
@@ -200,7 +168,7 @@ 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.
|
||||
|
||||
for (pform_parm_it_t cur = defparms.begin()
|
||||
for (hparm_it_t cur = defparms.begin()
|
||||
; cur != defparms.end() ; cur ++ ) {
|
||||
|
||||
PExpr*ex = (*cur).second;
|
||||
@@ -221,17 +189,6 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
|
||||
delete[]attr;
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
||||
// Tasks introduce new scopes, so scan the tasks in this
|
||||
// module. Create a scope for the task and pass that to the
|
||||
@@ -243,8 +200,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
for (tasks_it_t cur = tasks_.begin()
|
||||
; cur != tasks_.end() ; cur ++ ) {
|
||||
|
||||
hname_t use_name( (*cur).first );
|
||||
NetScope*task_scope = new NetScope(scope, use_name,
|
||||
NetScope*task_scope = new NetScope(scope, (*cur).first,
|
||||
NetScope::TASK);
|
||||
(*cur).second->elaborate_scope(des, task_scope);
|
||||
}
|
||||
@@ -259,8 +215,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
for (funcs_it_t cur = funcs_.begin()
|
||||
; cur != funcs_.end() ; cur ++ ) {
|
||||
|
||||
hname_t use_name( (*cur).first );
|
||||
NetScope*func_scope = new NetScope(scope, use_name,
|
||||
NetScope*func_scope = new NetScope(scope, (*cur).first,
|
||||
NetScope::FUNC);
|
||||
(*cur).second->elaborate_scope(des, func_scope);
|
||||
}
|
||||
@@ -290,7 +245,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
}
|
||||
|
||||
// Scan through all the named events in this scope. We do not
|
||||
// need anything more than the current scope to do this
|
||||
// need anything more then the current scope to do this
|
||||
// elaboration, so do it now. This allows for normal
|
||||
// elaboration to reference these events.
|
||||
|
||||
@@ -300,119 +255,15 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
(*et).second->elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
for (map<hname_t,PData*>::const_iterator cur = datum.begin()
|
||||
; cur != datum.end() ; cur ++ ) {
|
||||
|
||||
(*cur).second->elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
return des->errors == 0;
|
||||
}
|
||||
|
||||
bool PGenerate::generate_scope(Design*des, NetScope*container)
|
||||
{
|
||||
switch (scheme_type) {
|
||||
case GS_LOOP:
|
||||
return generate_scope_loop_(des, container);
|
||||
|
||||
default:
|
||||
cerr << get_line() << ": sorry: Generate of this sort"
|
||||
<< " is not supported yet!" << endl;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the elaborate scope method for a generate loop.
|
||||
*/
|
||||
bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
{
|
||||
// We're going to need a genvar...
|
||||
int genvar;
|
||||
|
||||
// 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 paramter value is evaluated.
|
||||
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1);
|
||||
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
|
||||
if (init == 0) {
|
||||
cerr << get_line() << ": error: Cannot evaluate genvar"
|
||||
<< " init expression: " << *loop_init << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
genvar = init->value().as_long();
|
||||
delete init_ex;
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: genvar init = " << genvar << endl;
|
||||
|
||||
container->genvar_tmp = loop_index;
|
||||
container->genvar_tmp_val = 0;
|
||||
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
|
||||
assert(test);
|
||||
while (test->value().as_long()) {
|
||||
|
||||
// The actual name of the scope includes the genvar so
|
||||
// that each instance has a unique name in the
|
||||
// container. The format of using [] is part of the
|
||||
// Verilog standard.
|
||||
hname_t use_name (scope_name, genvar);
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Create generated scope " << use_name << endl;
|
||||
|
||||
NetScope*scope = new NetScope(container, use_name,
|
||||
NetScope::GENBLOCK);
|
||||
|
||||
// Set in the scope a localparam for the value of the
|
||||
// genvar within this instance of the generate
|
||||
// block. Code within this scope thus has access to the
|
||||
// genvar as a constant.
|
||||
{
|
||||
verinum genvar_verinum(genvar);
|
||||
genvar_verinum.has_sign(true);
|
||||
NetEConstParam*gp = new NetEConstParam(scope,
|
||||
loop_index,
|
||||
genvar_verinum);
|
||||
scope->set_localparam(loop_index, gp);
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Create implicit localparam "
|
||||
<< loop_index << " = " << genvar_verinum << endl;
|
||||
}
|
||||
|
||||
// Scan the generated scope for gates that may create
|
||||
// their own scopes.
|
||||
typedef list<PGate*>::const_iterator pgate_list_it_t;
|
||||
for (pgate_list_it_t cur = gates.begin()
|
||||
; cur != gates.end() ; cur ++) {
|
||||
(*cur) ->elaborate_scope(des, scope);
|
||||
}
|
||||
|
||||
scope_list_.push_back(scope);
|
||||
|
||||
// Calculate the step for the loop variable.
|
||||
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1);
|
||||
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
|
||||
assert(step);
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: genvar step from "
|
||||
<< genvar << " to " << step->value().as_long() << endl;
|
||||
|
||||
genvar = step->value().as_long();
|
||||
container->genvar_tmp_val = genvar;
|
||||
delete step;
|
||||
delete test_ex;
|
||||
test_ex = elab_and_eval(des, container, loop_test, -1);
|
||||
test = dynamic_cast<NetEConst*>(test_ex);
|
||||
assert(test);
|
||||
}
|
||||
|
||||
// Clear the genvar_tmp field in the scope to reflect that the
|
||||
// genvar is no longer value for evaluating expressions.
|
||||
container->genvar_tmp = perm_string();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
{
|
||||
if (get_name() == "") {
|
||||
@@ -429,7 +280,7 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
// about to create, and if I find it then somebody beat me to
|
||||
// it.
|
||||
|
||||
if (sc->child(hname_t(get_name()))) {
|
||||
if (sc->child(get_name())) {
|
||||
cerr << get_line() << ": error: Instance/Scope name " <<
|
||||
get_name() << " already used in this context." <<
|
||||
endl;
|
||||
@@ -452,17 +303,15 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
<< "module " << mod->mod_name() << " within itself." << endl;
|
||||
|
||||
cerr << get_line() << ": : The offending instance is "
|
||||
<< scope_path(sc) << "." << get_name() << " within "
|
||||
<< scope_path(scn) << "." << endl;
|
||||
<< sc->name() << "." << get_name() << " within "
|
||||
<< scn->name() << "." << endl;
|
||||
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
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);
|
||||
NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
|
||||
verinum*msb = msb_ ? msb_->eval_const(des, sc) : 0;
|
||||
verinum*lsb = lsb_ ? lsb_->eval_const(des, sc) : 0;
|
||||
|
||||
assert( (msb == 0) || (lsb != 0) );
|
||||
|
||||
@@ -473,15 +322,12 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
|
||||
if (msb) {
|
||||
instance_array = true;
|
||||
instance_high = msb->value().as_long();
|
||||
instance_low = lsb->value().as_long();
|
||||
instance_high = msb->as_long();
|
||||
instance_low = lsb->as_long();
|
||||
if (instance_high > instance_low)
|
||||
instance_count = instance_high - instance_low + 1;
|
||||
else
|
||||
instance_count = instance_low - instance_high + 1;
|
||||
|
||||
delete mse;
|
||||
delete lse;
|
||||
}
|
||||
|
||||
NetScope::scope_vec_t instances (instance_count);
|
||||
@@ -496,21 +342,24 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
// instantiation line.
|
||||
for (int idx = 0 ; idx < instance_count ; idx += 1) {
|
||||
|
||||
hname_t use_name (get_name());
|
||||
perm_string use_name = get_name();
|
||||
|
||||
if (instance_array) {
|
||||
char name_buf[128];
|
||||
int instance_idx = idx;
|
||||
if (instance_low < instance_high)
|
||||
instance_idx = instance_low + idx;
|
||||
else
|
||||
instance_idx = instance_low - idx;
|
||||
|
||||
use_name = hname_t(get_name(), instance_idx);
|
||||
snprintf(name_buf, sizeof name_buf,
|
||||
"%s[%d]", get_name().str(), instance_idx);
|
||||
use_name = lex_strings.make(name_buf);
|
||||
}
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << get_line() << ": debug: Module instance " << use_name
|
||||
<< " becomes child of " << scope_path(sc)
|
||||
<< " becomes child of " << sc->name()
|
||||
<< "." << endl;
|
||||
}
|
||||
|
||||
@@ -526,6 +375,13 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
my_scope->time_precision(mod->time_precision);
|
||||
des->set_precision(mod->time_precision);
|
||||
|
||||
// This call actually arranges for the description of the
|
||||
// module type to process this instance and handle parameters
|
||||
// and sub-scopes that might occur. Parameters are also
|
||||
// created in that scope, as they exist. (I'll override them
|
||||
// later.)
|
||||
mod->elaborate_scope(des, my_scope);
|
||||
|
||||
// Look for module parameter replacements. The "replace" map
|
||||
// maps parameter name to replacement expression that is
|
||||
// passed. It is built up by the ordered overrides or named
|
||||
@@ -568,8 +424,6 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
}
|
||||
|
||||
|
||||
Module::replace_t replace_net;
|
||||
|
||||
// And here we scan the replacements we collected. Elaborate
|
||||
// the expression in my context, then replace the sub-scope
|
||||
// parameter value with the new expression.
|
||||
@@ -579,16 +433,13 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
|
||||
PExpr*tmp = (*cur).second;
|
||||
NetExpr*val = tmp->elaborate_pexpr(des, sc);
|
||||
replace_net[(*cur).first] = val;
|
||||
bool flag = my_scope->replace_parameter((*cur).first, val);
|
||||
if (! flag) {
|
||||
cerr << val->get_line() << ": warning: parameter "
|
||||
<< (*cur).first << " not found in "
|
||||
<< sc->name() << "." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
// This call actually arranges for the description of the
|
||||
// module type to process this instance and handle parameters
|
||||
// and sub-scopes that might occur. Parameters are also
|
||||
// created in that scope, as they exist. (I'll override them
|
||||
// later.)
|
||||
mod->elaborate_scope(des, my_scope, replace_net);
|
||||
|
||||
}
|
||||
|
||||
/* Stash the instance array of scopes into the parent
|
||||
@@ -597,6 +448,34 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
sc->instance_arrays[get_name()] = instances;
|
||||
}
|
||||
|
||||
/*
|
||||
* Elaborate the datum within the module. This variable may be
|
||||
* within a subscope (i.e., a function or task) so use the components
|
||||
* of the name to find the precise scope where this item goes.
|
||||
*/
|
||||
void PData::elaborate_scope(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetScope*sub_scope = scope;
|
||||
for (unsigned idx = 0 ; idx < (hname_.component_count()-1); idx += 1) {
|
||||
sub_scope = sub_scope->child(hname_.peek_name(idx));
|
||||
|
||||
if (sub_scope == 0) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Could not find sub-scope "
|
||||
<< hname_.peek_name(idx) << " of "
|
||||
<< hname_ << " in module " << scope->name()
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
const char*basename = hname_.peek_tail_name();
|
||||
NetVariable*tmp = new NetVariable(lex_strings.make(basename));
|
||||
tmp->set_line(*this);
|
||||
sub_scope->add_variable(tmp);
|
||||
}
|
||||
|
||||
/*
|
||||
* The isn't really able to create new scopes, but it does create the
|
||||
* event name in the current scope, so can be done during the
|
||||
@@ -647,7 +526,7 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
|
||||
NetScope*my_scope = scope;
|
||||
|
||||
if (name_ != 0) {
|
||||
my_scope = new NetScope(scope, hname_t(name_), bl_type_==BL_PAR
|
||||
my_scope = new NetScope(scope, name_, bl_type_==BL_PAR
|
||||
? NetScope::FORK_JOIN
|
||||
: NetScope::BEGIN_END);
|
||||
}
|
||||
@@ -756,42 +635,6 @@ void PWhile::elaborate_scope(Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: elab_scope.cc,v $
|
||||
* Revision 1.46 2007/06/02 03:42:12 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.45 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.44 2007/03/22 16:08:15 steve
|
||||
* Spelling fixes from Larry
|
||||
*
|
||||
* Revision 1.43 2007/03/08 06:11:35 steve
|
||||
* Elaborate scopes of modules instantated in generate loops.
|
||||
*
|
||||
* Revision 1.42 2007/03/05 05:59:10 steve
|
||||
* Handle processes within generate loops.
|
||||
*
|
||||
* Revision 1.41 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.40 2006/04/12 05:05:03 steve
|
||||
* Use elab_and_eval to evaluate genvar expressions.
|
||||
*
|
||||
* Revision 1.39 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.38 2006/03/30 01:49:07 steve
|
||||
* Fix instance arrays indexed by overridden parameters.
|
||||
*
|
||||
* Revision 1.37 2006/03/18 22:53:38 steve
|
||||
* Support more parameter syntax.
|
||||
*
|
||||
* Revision 1.36 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.35 2004/09/10 00:15:17 steve
|
||||
* Missing stdio.h header for warnings.
|
||||
*
|
||||
|
||||
+90
-288
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_sig.cc,v 1.52 2007/06/02 03:42:12 steve Exp $"
|
||||
#ident "$Id: elab_sig.cc,v 1.36 2004/09/27 22:34:10 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -27,14 +27,12 @@
|
||||
# include "Module.h"
|
||||
# include "PExpr.h"
|
||||
# include "PGate.h"
|
||||
# include "PGenerate.h"
|
||||
# include "PTask.h"
|
||||
# include "PWire.h"
|
||||
# include "compiler.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "util.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
/*
|
||||
* This local function checks if a named signal is connected to a
|
||||
@@ -42,10 +40,8 @@
|
||||
* within the port_t that have a matching name.
|
||||
*/
|
||||
static bool signal_is_in_port(const svector<Module::port_t*>&ports,
|
||||
NetNet*sig)
|
||||
const hname_t&name)
|
||||
{
|
||||
perm_string name = sig->name();
|
||||
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
|
||||
Module::port_t*pp = ports[idx];
|
||||
@@ -56,15 +52,9 @@ static bool signal_is_in_port(const svector<Module::port_t*>&ports,
|
||||
// This port has an internal connection. In this case,
|
||||
// the port has 0 or more NetEIdent objects concatenated
|
||||
// together that form the port.
|
||||
|
||||
// Note that module ports should not have any heirarchy
|
||||
// in their names: they are in the root of the module
|
||||
// scope by definition.
|
||||
|
||||
for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
|
||||
perm_string pname = peek_tail_name(pp->expr[cc]->path());
|
||||
assert(pp->expr[cc]);
|
||||
if (pname == name)
|
||||
if (pp->expr[cc]->path() == name)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -72,28 +62,14 @@ static bool signal_is_in_port(const svector<Module::port_t*>&ports,
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static NetNet*find_signal_in_scope(NetScope*scope, const hname_t&path)
|
||||
{
|
||||
NetScope*cur = scope;
|
||||
unsigned idx = 0;
|
||||
|
||||
while (path.peek_name(idx+1)) {
|
||||
cur = cur->child(path.peek_name(idx));
|
||||
if (cur == 0)
|
||||
return 0;
|
||||
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
return cur->find_signal(path.peek_name(idx));
|
||||
}
|
||||
#endif
|
||||
|
||||
bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
// Get all the explicitly declared wires of the module and
|
||||
// start the signals list with them.
|
||||
const map<hname_t,PWire*>&wl = get_wires();
|
||||
|
||||
// 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.count() ; idx += 1) {
|
||||
@@ -101,12 +77,12 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (pp == 0)
|
||||
continue;
|
||||
|
||||
map<pform_name_t,PWire*>::const_iterator wt;
|
||||
map<hname_t,PWire*>::const_iterator wt;
|
||||
for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
|
||||
pform_name_t port_path (pp->expr[cc]->path());
|
||||
wt = wires_.find(port_path);
|
||||
hname_t port_path (pp->expr[cc]->path());
|
||||
wt = wl.find(port_path);
|
||||
|
||||
if (wt == wires_.end()) {
|
||||
if (wt == wl.end()) {
|
||||
cerr << get_line() << ": error: "
|
||||
<< "Port " << pp->expr[cc]->path() << " ("
|
||||
<< (idx+1) << ") of module " << name_
|
||||
@@ -126,11 +102,14 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
}
|
||||
}
|
||||
|
||||
for (map<pform_name_t,PWire*>::const_iterator wt = wires_.begin()
|
||||
; wt != wires_.end() ; wt ++ ) {
|
||||
for (map<hname_t,PWire*>::const_iterator wt = wl.begin()
|
||||
; wt != wl.end()
|
||||
; wt ++ ) {
|
||||
|
||||
PWire*cur = (*wt).second;
|
||||
NetNet*sig = cur->elaborate_sig(des, scope);
|
||||
cur->elaborate_sig(des, scope);
|
||||
|
||||
NetNet*sig = scope->find_signal_in_child(cur->path());
|
||||
|
||||
// If this wire is a signal of the module (as opposed to
|
||||
// a port of a function) and is a port, then check that
|
||||
@@ -142,10 +121,12 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (cur->get_port_type() != NetNet::NOT_A_PORT)) {
|
||||
|
||||
if (! signal_is_in_port(ports, sig)) {
|
||||
hname_t name = (*wt).first;
|
||||
|
||||
if (! signal_is_in_port(ports, name)) {
|
||||
|
||||
cerr << cur->get_line() << ": error: Signal "
|
||||
<< sig->name() << " has a declared direction "
|
||||
<< name << " has a declared direction "
|
||||
<< "but is not a port." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
@@ -177,16 +158,6 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Run through all the generate schemes to enaborate the
|
||||
// signals that they hold. Note that the generate schemes hold
|
||||
// the scopes that they instantiated, so we don't pass any
|
||||
// scope in.
|
||||
typedef list<PGenerate*>::const_iterator generate_it_t;
|
||||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; cur ++ ) {
|
||||
(*cur) -> elaborate_sig(des);
|
||||
}
|
||||
|
||||
// Get all the gates of the module and elaborate them by
|
||||
@@ -208,13 +179,11 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
for (mfunc_it_t cur = funcs_.begin()
|
||||
; cur != funcs_.end() ; cur ++) {
|
||||
|
||||
hname_t use_name ( (*cur).first );
|
||||
NetScope*fscope = scope->child(use_name);
|
||||
NetScope*fscope = scope->child((*cur).first);
|
||||
if (scope == 0) {
|
||||
cerr << (*cur).second->get_line() << ": internal error: "
|
||||
<< "Child scope for function " << (*cur).first
|
||||
<< " missing in " << scope_path(scope) << "." << endl;
|
||||
<< " missing in " << scope->name() << "." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
@@ -231,7 +200,7 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
for (mtask_it_t cur = tasks_.begin()
|
||||
; cur != tasks_.end() ; cur ++) {
|
||||
NetScope*tscope = scope->child( hname_t((*cur).first) );
|
||||
NetScope*tscope = scope->child((*cur).first);
|
||||
assert(tscope);
|
||||
(*cur).second->elaborate_sig(des, tscope);
|
||||
}
|
||||
@@ -254,9 +223,9 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
|
||||
|
||||
if (my_scope->parent() != scope) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Instance " << scope_path(my_scope)
|
||||
<< " is in parent " << scope_path(my_scope->parent())
|
||||
<< " instead of " << scope_path(scope)
|
||||
<< "Instance " << my_scope->name()
|
||||
<< " is in parent " << my_scope->parent()->name()
|
||||
<< " instead of " << scope->name()
|
||||
<< endl;
|
||||
}
|
||||
assert(my_scope->parent() == scope);
|
||||
@@ -269,50 +238,6 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool PGenerate::elaborate_sig(Design*des) const
|
||||
{
|
||||
bool flag = true;
|
||||
|
||||
typedef list<NetScope*>::const_iterator scope_list_it_t;
|
||||
for (scope_list_it_t cur = scope_list_.begin()
|
||||
; cur != scope_list_.end() ; cur ++ ) {
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: Elaborate nets in "
|
||||
<< "scope " << scope_path(*cur) << endl;
|
||||
flag = elaborate_sig_(des, *cur) & flag;
|
||||
}
|
||||
|
||||
return flag;
|
||||
}
|
||||
|
||||
bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
|
||||
{
|
||||
// Scan the declared PWires to elaborate the obvious signals
|
||||
// in the current scope.
|
||||
typedef map<pform_name_t,PWire*>::const_iterator wires_it_t;
|
||||
for (wires_it_t wt = wires.begin()
|
||||
; wt != wires.end() ; wt ++ ) {
|
||||
|
||||
PWire*cur = (*wt).second;
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: Elaborate PWire "
|
||||
<< cur->path() << " in scope " << scope_path(scope) << endl;
|
||||
|
||||
cur->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
typedef list<PGate*>::const_iterator pgate_list_it_t;
|
||||
for (pgate_list_it_t cur = gates.begin()
|
||||
; cur != gates.end() ; cur ++) {
|
||||
(*cur) ->elaborate_sig(des, scope);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* A function definition exists within an elaborated module. This
|
||||
* matters when elaborating signals, as the ports of the function are
|
||||
@@ -336,19 +261,19 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
}
|
||||
|
||||
NetNet*ret_sig = 0;
|
||||
NetVariable*ret_real = 0;
|
||||
|
||||
/* Create the signals/variables of the return value and write
|
||||
them into the function scope. */
|
||||
switch (return_type_.type) {
|
||||
|
||||
case PTF_REG:
|
||||
case PTF_REG_S:
|
||||
if (return_type_.range) {
|
||||
NetExpr*me = elab_and_eval(des, scope,
|
||||
(*return_type_.range)[0], -1);
|
||||
(*return_type_.range)[0]);
|
||||
assert(me);
|
||||
NetExpr*le = elab_and_eval(des, scope,
|
||||
(*return_type_.range)[1], -1);
|
||||
(*return_type_.range)[1]);
|
||||
assert(le);
|
||||
|
||||
long mnum = 0, lnum = 0;
|
||||
@@ -376,18 +301,15 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG);
|
||||
}
|
||||
ret_sig->set_line(*this);
|
||||
ret_sig->set_signed(return_type_.type == PTF_REG_S);
|
||||
ret_sig->port_type(NetNet::POUTPUT);
|
||||
ret_sig->data_type(IVL_VT_LOGIC);
|
||||
break;
|
||||
|
||||
case PTF_INTEGER:
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG, integer_width);
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG, INTEGER_WIDTH);
|
||||
ret_sig->set_line(*this);
|
||||
ret_sig->set_signed(true);
|
||||
ret_sig->set_isint(true);
|
||||
ret_sig->port_type(NetNet::POUTPUT);
|
||||
ret_sig->data_type(IVL_VT_LOGIC);
|
||||
break;
|
||||
|
||||
case PTF_TIME:
|
||||
@@ -396,17 +318,13 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
ret_sig->set_signed(false);
|
||||
ret_sig->set_isint(false);
|
||||
ret_sig->port_type(NetNet::POUTPUT);
|
||||
ret_sig->data_type(IVL_VT_LOGIC);
|
||||
break;
|
||||
|
||||
case PTF_REAL:
|
||||
case PTF_REALTIME:
|
||||
ret_sig = new NetNet(scope, fname, NetNet::REG, 1);
|
||||
ret_sig->set_line(*this);
|
||||
ret_sig->set_signed(true);
|
||||
ret_sig->set_isint(false);
|
||||
ret_sig->port_type(NetNet::POUTPUT);
|
||||
ret_sig->data_type(IVL_VT_REAL);
|
||||
ret_real = new NetVariable(fname);
|
||||
ret_real->set_line(*this);
|
||||
scope->add_variable(ret_real);
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -424,24 +342,22 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
name. We know by design that the port name is given
|
||||
as two components: <func>.<port>. */
|
||||
|
||||
pform_name_t path = (*ports_)[idx]->path();
|
||||
ivl_assert(*this, path.size() == 2);
|
||||
|
||||
perm_string pname = peek_tail_name(path);
|
||||
perm_string ppath = peek_head_name(path);
|
||||
hname_t path = (*ports_)[idx]->path();
|
||||
perm_string pname = lex_strings.make(path.peek_name(1));
|
||||
perm_string ppath = lex_strings.make(path.peek_name(0));
|
||||
|
||||
if (ppath != scope->basename()) {
|
||||
cerr << get_line() << ": internal error: function "
|
||||
<< "port " << (*ports_)[idx]->path()
|
||||
<< " has wrong name for function "
|
||||
<< scope_path(scope) << "." << endl;
|
||||
<< scope->name() << "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
NetNet*tmp = scope->find_signal(pname);
|
||||
if (tmp == 0) {
|
||||
cerr << get_line() << ": internal error: function "
|
||||
<< scope_path(scope) << " is missing port "
|
||||
<< scope->name() << " is missing port "
|
||||
<< pname << "." << endl;
|
||||
scope->dump(cerr);
|
||||
cerr << get_line() << ": Continuing..." << endl;
|
||||
@@ -454,6 +370,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
NetFuncDef*def = 0;
|
||||
if (ret_sig) def = new NetFuncDef(scope, ret_sig, ports);
|
||||
if (ret_real) def = new NetFuncDef(scope, ret_real, ports);
|
||||
|
||||
assert(def);
|
||||
scope->set_func_def(def);
|
||||
@@ -479,34 +396,36 @@ void PTask::elaborate_sig(Design*des, NetScope*scope) const
|
||||
name. We know by design that the port name is given
|
||||
as two components: <task>.<port>. */
|
||||
|
||||
pform_name_t path = (*ports_)[idx]->path();
|
||||
ivl_assert(*this, path.size() == 2);
|
||||
|
||||
perm_string scope_name = peek_head_name(path);
|
||||
perm_string port_name = peek_tail_name(path);
|
||||
hname_t path = (*ports_)[idx]->path();
|
||||
assert(path.peek_name(0) && path.peek_name(1));
|
||||
|
||||
/* check that the current scope really does have the
|
||||
name of the first component of the task port name. Do
|
||||
this by looking up the task scope in the parent of
|
||||
the current scope. */
|
||||
ivl_assert(*this, scope->basename() == scope_name);
|
||||
if (scope->parent()->child(path.peek_name(0)) != scope) {
|
||||
cerr << "internal error: task scope " << path
|
||||
<< " not the same as scope " << scope->name()
|
||||
<< "?!" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Find the signal for the port. We know by definition
|
||||
that it is in the scope of the task, so look only in
|
||||
the scope. */
|
||||
NetNet*tmp = scope->find_signal(port_name);
|
||||
NetNet*tmp = scope->find_signal(path.peek_name(1));
|
||||
|
||||
if (tmp == 0) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Could not find port " << port_name
|
||||
<< " in scope " << scope_path(scope) << endl;
|
||||
<< "Could not find port " << path.peek_name(1)
|
||||
<< " in scope " << scope->name() << endl;
|
||||
scope->dump(cerr);
|
||||
}
|
||||
|
||||
ports[idx] = tmp;
|
||||
}
|
||||
|
||||
NetTaskDef*def = new NetTaskDef(scope, ports);
|
||||
NetTaskDef*def = new NetTaskDef(scope->name(), ports);
|
||||
scope->set_task_def(def);
|
||||
}
|
||||
|
||||
@@ -522,19 +441,16 @@ bool PGate::elaborate_sig(Design*des, NetScope*scope) const
|
||||
* elaboration this creates an object in the design that represent the
|
||||
* defined item.
|
||||
*/
|
||||
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
{
|
||||
|
||||
/* The parser may produce hierarchical names for wires. I here
|
||||
follow the scopes down to the base where I actually want to
|
||||
elaborate the NetNet object. */
|
||||
{ pform_name_t tmp_path = hname_;
|
||||
tmp_path.pop_back();
|
||||
while (! tmp_path.empty()) {
|
||||
name_component_t cur = tmp_path.front();
|
||||
tmp_path.pop_front();
|
||||
|
||||
scope = scope->child( hname_t(cur.name) );
|
||||
{ hname_t tmp_path = hname_;
|
||||
free(tmp_path.remove_tail_name());
|
||||
for (unsigned idx = 0 ; tmp_path.peek_name(idx) ; idx += 1) {
|
||||
scope = scope->child(tmp_path.peek_name(idx));
|
||||
|
||||
if (scope == 0) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
@@ -579,7 +495,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
}
|
||||
|
||||
NetEConst*tmp;
|
||||
NetExpr*texpr = elab_and_eval(des, scope, msb_[idx], -1);
|
||||
NetExpr*texpr = elab_and_eval(des, scope, msb_[idx]);
|
||||
|
||||
tmp = dynamic_cast<NetEConst*>(texpr);
|
||||
if (tmp == 0) {
|
||||
@@ -587,20 +503,20 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
"Unable to evaluate constant expression ``" <<
|
||||
*msb_[idx] << "''." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
mnum[idx] = tmp->value().as_long();
|
||||
delete texpr;
|
||||
|
||||
texpr = elab_and_eval(des, scope, lsb_[idx], -1);
|
||||
texpr = elab_and_eval(des, scope, lsb_[idx]);
|
||||
tmp = dynamic_cast<NetEConst*>(texpr);
|
||||
if (tmp == 0) {
|
||||
cerr << msb_[idx]->get_line() << ": error: "
|
||||
"Unable to evaluate constant expression ``" <<
|
||||
*lsb_[idx] << "''." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
lnum[idx] = tmp->value().as_long();
|
||||
@@ -616,7 +532,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
<< "'' declared both as a vector and a scalar."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -629,7 +545,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
" vs. [" << mnum[0] << ":" << lnum[0] << "]"
|
||||
" for signal ``" << hname_ << "''" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -647,10 +563,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
attrib_list_t*attrib_list = evaluate_attributes(attributes, nattrib,
|
||||
des, scope);
|
||||
|
||||
long array_s0 = 0;
|
||||
long array_e0 = 0;
|
||||
unsigned array_dimensions = 0;
|
||||
|
||||
/* If the ident has idx expressions, then this is a
|
||||
memory. It can only have the idx registers after the msb
|
||||
and lsb expressions are filled. And, if it has one index,
|
||||
@@ -658,15 +570,15 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (lidx_ || ridx_) {
|
||||
assert(lidx_ && ridx_);
|
||||
|
||||
NetExpr*lexp = elab_and_eval(des, scope, lidx_, -1);
|
||||
NetExpr*rexp = elab_and_eval(des, scope, ridx_, -1);
|
||||
NetExpr*lexp = elab_and_eval(des, scope, lidx_);
|
||||
NetExpr*rexp = elab_and_eval(des, scope, ridx_);
|
||||
|
||||
if ((lexp == 0) || (rexp == 0)) {
|
||||
cerr << get_line() << ": internal error: There is "
|
||||
<< "a problem evaluating indices for ``"
|
||||
<< hname_ << "''." << endl;
|
||||
<< hname_.peek_tail_name() << "''." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
NetEConst*lcon = dynamic_cast<NetEConst*> (lexp);
|
||||
@@ -674,10 +586,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
if ((lcon == 0) || (rcon == 0)) {
|
||||
cerr << get_line() << ": internal error: The indices "
|
||||
<< "are not constant for array ``"
|
||||
<< hname_ << "''." << endl;
|
||||
<< "are not constant for memory ``"
|
||||
<< hname_.peek_tail_name() << "''." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
return;
|
||||
}
|
||||
|
||||
verinum lval = lcon->value();
|
||||
@@ -686,141 +598,31 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
delete lexp;
|
||||
delete rexp;
|
||||
|
||||
array_dimensions = 1;
|
||||
array_s0 = lval.as_long();
|
||||
array_e0 = rval.as_long();
|
||||
perm_string name = lex_strings.make(hname_.peek_tail_name());
|
||||
|
||||
long lnum = lval.as_long();
|
||||
long rnum = rval.as_long();
|
||||
|
||||
new NetMemory(scope, name, wid, lnum, rnum);
|
||||
// The constructor automatically adds the memory object
|
||||
// to the scope. Do I need to set line number information?
|
||||
|
||||
} else {
|
||||
|
||||
perm_string name = lex_strings.make(hname_.peek_tail_name());
|
||||
NetNet*sig = new NetNet(scope, name, wtype, msb, lsb);
|
||||
sig->set_line(*this);
|
||||
sig->port_type(port_type_);
|
||||
sig->set_signed(get_signed());
|
||||
sig->set_isint(get_isint());
|
||||
|
||||
for (unsigned idx = 0 ; idx < nattrib ; idx += 1)
|
||||
sig->attribute(attrib_list[idx].key, attrib_list[idx].val);
|
||||
}
|
||||
|
||||
/* If the net type is supply0 or supply1, replace it
|
||||
with a simple wire with a pulldown/pullup with supply
|
||||
strength. In other words, transform:
|
||||
|
||||
supply0 foo;
|
||||
|
||||
to:
|
||||
|
||||
wire foo;
|
||||
pulldown #(supply0) (foo);
|
||||
|
||||
This reduces the backend burden, and behaves exactly
|
||||
the same. */
|
||||
|
||||
NetLogic*pull = 0;
|
||||
if (wtype == NetNet::SUPPLY0 || wtype == NetNet::SUPPLY1) {
|
||||
NetLogic::TYPE pull_type = (wtype==NetNet::SUPPLY1)
|
||||
? NetLogic::PULLUP
|
||||
: NetLogic::PULLDOWN;
|
||||
pull = new NetLogic(scope, scope->local_symbol(),
|
||||
1, pull_type, wid);
|
||||
pull->set_line(*this);
|
||||
pull->pin(0).drive0(Link::SUPPLY);
|
||||
pull->pin(0).drive1(Link::SUPPLY);
|
||||
des->add_node(pull);
|
||||
wtype = NetNet::WIRE;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Generate a SUPPLY pulldown for the "
|
||||
<< "supply0 net." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
perm_string name = peek_tail_name(hname_);
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Create signal "
|
||||
<< wtype << " ["<<msb<<":"<<lsb<<"] " << name
|
||||
<< " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
|
||||
NetNet*sig = array_dimensions > 0
|
||||
? new NetNet(scope, name, wtype, msb, lsb, array_s0, array_e0)
|
||||
: new NetNet(scope, name, wtype, msb, lsb);
|
||||
|
||||
ivl_variable_type_t use_data_type = data_type_;
|
||||
if (use_data_type == IVL_VT_NO_TYPE) {
|
||||
use_data_type = IVL_VT_LOGIC;
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Signal " << name
|
||||
<< " in scope " << scope_path(scope)
|
||||
<< " defaults to data type " << use_data_type << endl;
|
||||
}
|
||||
}
|
||||
|
||||
sig->data_type(use_data_type);
|
||||
sig->set_line(*this);
|
||||
sig->port_type(port_type_);
|
||||
sig->set_signed(get_signed());
|
||||
sig->set_isint(get_isint());
|
||||
|
||||
if (pull)
|
||||
connect(sig->pin(0), pull->pin(0));
|
||||
|
||||
for (unsigned idx = 0 ; idx < nattrib ; idx += 1)
|
||||
sig->attribute(attrib_list[idx].key, attrib_list[idx].val);
|
||||
|
||||
return sig;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: elab_sig.cc,v $
|
||||
* Revision 1.52 2007/06/02 03:42:12 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.51 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.50 2007/04/26 03:06:22 steve
|
||||
* Rework hname_t to use perm_strings.
|
||||
*
|
||||
* Revision 1.49 2007/04/02 01:12:34 steve
|
||||
* Seperate arrayness from word count
|
||||
*
|
||||
* Revision 1.48 2007/03/08 06:11:35 steve
|
||||
* Elaborate scopes of modules instantated in generate loops.
|
||||
*
|
||||
* Revision 1.47 2007/03/07 04:24:59 steve
|
||||
* Make integer width controllable.
|
||||
*
|
||||
* Revision 1.46 2007/03/06 05:22:49 steve
|
||||
* Support signed function return values.
|
||||
*
|
||||
* Revision 1.45 2007/02/01 05:24:08 steve
|
||||
* Include type in signal create message.
|
||||
*
|
||||
* Revision 1.44 2007/01/29 02:07:34 steve
|
||||
* Types of task/function arguments set in multiple steps.
|
||||
*
|
||||
* Revision 1.43 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.42 2006/06/02 04:48:50 steve
|
||||
* Make elaborate_expr methods aware of the width that the context
|
||||
* requires of it. In the process, fix sizing of the width of unary
|
||||
* minus is context determined sizes.
|
||||
*
|
||||
* Revision 1.41 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.40 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.39 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.38 2005/02/13 01:15:07 steve
|
||||
* Replace supply nets with wires connected to pullup/down supply devices.
|
||||
*
|
||||
* Revision 1.37 2004/12/11 02:31:25 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.36 2004/09/27 22:34:10 steve
|
||||
* Cleanup and factoring of autoconf.
|
||||
*
|
||||
|
||||
+475
-1199
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2005 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-2000 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: emit.cc,v 1.89 2007/01/16 05:44:15 steve Exp $"
|
||||
#ident "$Id: emit.cc,v 1.77.2.2 2006/03/26 23:09:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -57,17 +57,18 @@ bool NetAddSub::emit_node(struct target_t*tgt) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetArrayDq::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->lpm_array_dq(this);
|
||||
}
|
||||
|
||||
bool NetCaseCmp::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_case_cmp(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetCAssign::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->net_cassign(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetCLShift::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_clshift(this);
|
||||
@@ -80,16 +81,21 @@ bool NetCompare::emit_node(struct target_t*tgt) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetConcat::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->concat(this);
|
||||
}
|
||||
|
||||
bool NetConst::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->net_const(this);
|
||||
}
|
||||
|
||||
bool NetDecode::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->lpm_decode(this);
|
||||
}
|
||||
|
||||
bool NetDemux::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->lpm_demux(this);
|
||||
}
|
||||
|
||||
bool NetDivide::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_divide(this);
|
||||
@@ -102,9 +108,10 @@ bool NetFF::emit_node(struct target_t*tgt) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetLiteral::emit_node(struct target_t*tgt) const
|
||||
bool NetForce::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->net_literal(this);
|
||||
tgt->net_force(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetModulo::emit_node(struct target_t*tgt) const
|
||||
@@ -125,29 +132,10 @@ bool NetMux::emit_node(struct target_t*tgt) const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetPartSelect::emit_node(struct target_t*tgt) const
|
||||
bool NetRamDq::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->part_select(this);
|
||||
}
|
||||
|
||||
bool NetReplicate::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->replicate(this);
|
||||
}
|
||||
|
||||
bool NetSignExtend::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->sign_extend(this);
|
||||
}
|
||||
|
||||
bool NetUReduce::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->ureduce(this);
|
||||
}
|
||||
|
||||
bool NetSysFunc::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->net_sysfunction(this);
|
||||
tgt->lpm_ram_dq(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetUserFunc::emit_node(struct target_t*tgt) const
|
||||
@@ -334,6 +322,9 @@ void NetScope::emit_scope(struct target_t*tgt) const
|
||||
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_)
|
||||
tgt->event(cur);
|
||||
|
||||
for (NetVariable*cur = vars_ ; cur ; cur = cur->snext_)
|
||||
tgt->variable(cur);
|
||||
|
||||
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_)
|
||||
cur->emit_scope(tgt);
|
||||
|
||||
@@ -343,19 +334,15 @@ void NetScope::emit_scope(struct target_t*tgt) const
|
||||
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 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_);
|
||||
}
|
||||
|
||||
if (memories_) {
|
||||
NetMemory*cur = memories_->snext_;
|
||||
do {
|
||||
tgt->memory(cur);
|
||||
cur = cur->snext_;
|
||||
} while (cur != memories_->snext_);
|
||||
}
|
||||
}
|
||||
|
||||
bool NetScope::emit_defs(struct target_t*tgt) const
|
||||
@@ -386,12 +373,13 @@ void NetWhile::emit_proc_recurse(struct target_t*tgt) const
|
||||
proc_->emit_proc(tgt);
|
||||
}
|
||||
|
||||
int Design::emit(struct target_t*tgt) const
|
||||
bool Design::emit(struct target_t*tgt) const
|
||||
{
|
||||
int rc = 0;
|
||||
bool rc = true;
|
||||
|
||||
if (tgt->start_design(this) == false)
|
||||
return -2;
|
||||
rc = rc && tgt->start_design(this);
|
||||
if (rc == false)
|
||||
return false;
|
||||
|
||||
// enumerate the scopes
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
|
||||
@@ -400,36 +388,27 @@ int Design::emit(struct target_t*tgt) const
|
||||
|
||||
|
||||
// emit nodes
|
||||
bool nodes_rc = true;
|
||||
if (nodes_) {
|
||||
NetNode*cur = nodes_->node_next_;
|
||||
do {
|
||||
nodes_rc = nodes_rc && cur->emit_node(tgt);
|
||||
rc = rc && cur->emit_node(tgt);
|
||||
cur = cur->node_next_;
|
||||
} while (cur != nodes_->node_next_);
|
||||
}
|
||||
|
||||
|
||||
// emit task and function definitions
|
||||
bool tasks_rc = true;
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin();
|
||||
scope != root_scopes_.end(); scope++)
|
||||
tasks_rc &= (*scope)->emit_defs(tgt);
|
||||
rc &= (*scope)->emit_defs(tgt);
|
||||
|
||||
|
||||
// emit the processes
|
||||
bool proc_rc = true;
|
||||
for (const NetProcTop*idx = procs_ ; idx ; idx = idx->next_)
|
||||
proc_rc &= idx->emit(tgt);
|
||||
rc = rc && idx->emit(tgt);
|
||||
|
||||
rc = tgt->end_design(this);
|
||||
|
||||
if (nodes_rc == false)
|
||||
return -1;
|
||||
if (tasks_rc == false)
|
||||
return -2;
|
||||
if (proc_rc == false)
|
||||
return -3;
|
||||
if (tgt->end_design(this) != 0)
|
||||
rc = false;
|
||||
|
||||
return rc;
|
||||
}
|
||||
@@ -464,6 +443,11 @@ void NetECRealParam::expr_scan(struct expr_scan_t*tgt) const
|
||||
tgt->expr_rparam(this);
|
||||
}
|
||||
|
||||
void NetEMemory::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_memory(this);
|
||||
}
|
||||
|
||||
void NetEParam::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
cerr << get_line() << ":internal error: unexpected NetEParam."
|
||||
@@ -500,6 +484,11 @@ void NetESignal::expr_scan(struct expr_scan_t*tgt) const
|
||||
tgt->expr_signal(this);
|
||||
}
|
||||
|
||||
void NetEBitSel::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_subsignal(this);
|
||||
}
|
||||
|
||||
void NetETernary::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_ternary(this);
|
||||
@@ -510,7 +499,12 @@ void NetEUnary::expr_scan(struct expr_scan_t*tgt) const
|
||||
tgt->expr_unary(this);
|
||||
}
|
||||
|
||||
int emit(const Design*des, const char*type)
|
||||
void NetEVariable::expr_scan(struct expr_scan_t*tgt) const
|
||||
{
|
||||
tgt->expr_variable(this);
|
||||
}
|
||||
|
||||
bool emit(const Design*des, const char*type)
|
||||
{
|
||||
for (unsigned idx = 0 ; target_table[idx] ; idx += 1) {
|
||||
const struct target*tgt = target_table[idx];
|
||||
@@ -521,59 +515,17 @@ int emit(const Design*des, const char*type)
|
||||
|
||||
cerr << "error: Code generator type " << type
|
||||
<< " not found." << endl;
|
||||
return -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: emit.cc,v $
|
||||
* Revision 1.89 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
* Revision 1.77.2.2 2006/03/26 23:09:21 steve
|
||||
* Handle asynchronous demux/bit replacements.
|
||||
*
|
||||
* Revision 1.88 2006/11/10 05:44:44 steve
|
||||
* Process delay paths in second path over signals.
|
||||
*
|
||||
* Revision 1.87 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.86 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.85 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.84 2005/05/24 01:44:27 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.83 2005/02/08 00:12:36 steve
|
||||
* Add the NetRepeat node, and code generator support.
|
||||
*
|
||||
* Revision 1.82 2005/02/03 04:56:20 steve
|
||||
* laborate reduction gates into LPM_RED_ nodes.
|
||||
*
|
||||
* Revision 1.81 2005/01/24 05:28:30 steve
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
*
|
||||
* Revision 1.80 2005/01/22 01:06:55 steve
|
||||
* Change case compare from logic to an LPM node.
|
||||
*
|
||||
* Revision 1.79 2004/12/29 23:55:43 steve
|
||||
* Unify elaboration of l-values for all proceedural assignments,
|
||||
* including assing, cassign and force.
|
||||
*
|
||||
* Generate NetConcat devices for gate outputs that feed into a
|
||||
* vector results. Use this to hande gate arrays. Also let gate
|
||||
* arrays handle vectors of gates when the outputs allow for it.
|
||||
*
|
||||
* Revision 1.78 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
* Revision 1.77.2.1 2006/02/19 00:11:31 steve
|
||||
* Handle synthesis of FF vectors with l-value decoder.
|
||||
*
|
||||
* Revision 1.77 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
@@ -600,5 +552,131 @@ int emit(const Design*des, const char*type)
|
||||
* Revision 1.71 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.70 2002/11/03 20:36:10 steve
|
||||
* Error message for mising code generator type.
|
||||
*
|
||||
* Revision 1.69 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.68 2002/06/05 03:44:25 steve
|
||||
* Add support for memory words in l-value of
|
||||
* non-blocking assignments, and remove the special
|
||||
* NetAssignMem_ and NetAssignMemNB classes.
|
||||
*
|
||||
* Revision 1.67 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.66 2002/03/09 02:10:22 steve
|
||||
* Add the NetUserFunc netlist node.
|
||||
*
|
||||
* Revision 1.65 2002/01/28 00:52:41 steve
|
||||
* Add support for bit select of parameters.
|
||||
* This leads to a NetESelect node and the
|
||||
* vvp code generator to support that.
|
||||
*
|
||||
* Revision 1.64 2002/01/19 19:02:08 steve
|
||||
* Pass back target errors processing conditionals.
|
||||
*
|
||||
* Revision 1.63 2001/10/19 21:53:24 steve
|
||||
* Support multiple root modules (Philip Blundell)
|
||||
*
|
||||
* Revision 1.62 2001/08/25 23:50:02 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.61 2001/07/27 04:51:44 steve
|
||||
* Handle part select expressions as variants of
|
||||
* NetESignal/IVL_EX_SIGNAL objects, instead of
|
||||
* creating new and useless temporary signals.
|
||||
*
|
||||
* Revision 1.60 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.59 2001/04/22 23:09:46 steve
|
||||
* More UDP consolidation from Stephan Boettcher.
|
||||
*
|
||||
* Revision 1.58 2001/04/06 02:28:02 steve
|
||||
* Generate vvp code for functions with ports.
|
||||
*
|
||||
* Revision 1.57 2001/04/02 02:28:12 steve
|
||||
* Generate code for task calls.
|
||||
*
|
||||
* Revision 1.56 2001/03/27 03:31:06 steve
|
||||
* Support error code from target_t::end_design method.
|
||||
*
|
||||
* Revision 1.55 2000/11/04 01:54:01 steve
|
||||
* Modifications in support of gcc 2.96
|
||||
*
|
||||
* Revision 1.54 2000/09/26 01:35:42 steve
|
||||
* Remove the obsolete NetEIdent class.
|
||||
*
|
||||
* Revision 1.53 2000/09/17 21:26:15 steve
|
||||
* Add support for modulus (Eric Aardoom)
|
||||
*
|
||||
* Revision 1.52 2000/09/02 20:54:20 steve
|
||||
* Rearrange NetAssign to make NetAssign_ separate.
|
||||
*
|
||||
* Revision 1.51 2000/08/14 04:39:56 steve
|
||||
* add th t-dll functions for net_const, net_bufz and processes.
|
||||
*
|
||||
* Revision 1.50 2000/08/09 03:43:45 steve
|
||||
* Move all file manipulation out of target class.
|
||||
*
|
||||
* Revision 1.49 2000/08/08 01:50:42 steve
|
||||
* target methods need not take a file stream.
|
||||
*
|
||||
* Revision 1.48 2000/07/30 18:25:43 steve
|
||||
* Rearrange task and function elaboration so that the
|
||||
* NetTaskDef and NetFuncDef functions are created during
|
||||
* signal enaboration, and carry these objects in the
|
||||
* NetScope class instead of the extra, useless map in
|
||||
* the Design class.
|
||||
*
|
||||
* Revision 1.47 2000/07/29 16:21:08 steve
|
||||
* Report code generation errors through proc_delay.
|
||||
*
|
||||
* Revision 1.46 2000/07/27 05:13:44 steve
|
||||
* Support elaboration of disable statements.
|
||||
*
|
||||
* Revision 1.45 2000/05/11 23:37:27 steve
|
||||
* Add support for procedural continuous assignment.
|
||||
*
|
||||
* Revision 1.44 2000/05/04 03:37:58 steve
|
||||
* Add infrastructure for system functions, move
|
||||
* $time to that structure and add $random.
|
||||
*
|
||||
* Revision 1.43 2000/05/02 03:13:31 steve
|
||||
* Move memories to the NetScope object.
|
||||
*
|
||||
* Revision 1.42 2000/05/02 00:58:12 steve
|
||||
* Move signal tables to the NetScope class.
|
||||
*
|
||||
* Revision 1.41 2000/04/23 03:45:24 steve
|
||||
* Add support for the procedural release statement.
|
||||
*
|
||||
* Revision 1.40 2000/04/22 04:20:19 steve
|
||||
* Add support for force assignment.
|
||||
*
|
||||
* Revision 1.39 2000/04/12 04:23:58 steve
|
||||
* Named events really should be expressed with PEIdent
|
||||
* objects in the pform,
|
||||
*
|
||||
* Handle named events within the mix of net events
|
||||
* and edges. As a unified lot they get caught together.
|
||||
* wait statements are broken into more complex statements
|
||||
* that include a conditional.
|
||||
*
|
||||
* Do not generate NetPEvent or NetNEvent objects in
|
||||
* elaboration. NetEvent, NetEvWait and NetEvProbe
|
||||
* take over those functions in the netlist.
|
||||
*/
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval.cc,v 1.47 2007/06/04 19:14:06 steve Exp $"
|
||||
#ident "$Id: eval.cc,v 1.36.2.3 2006/09/20 20:27:02 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -26,15 +26,14 @@
|
||||
|
||||
# include "PExpr.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "compiler.h"
|
||||
|
||||
verinum* PExpr::eval_const(Design*, NetScope*) const
|
||||
verinum* PExpr::eval_const(const Design*, const NetScope*) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
verinum* PEBinary::eval_const(Design*des, NetScope*scope) const
|
||||
verinum* PEBinary::eval_const(const Design*des, const NetScope*scope) const
|
||||
{
|
||||
verinum*l = left_->eval_const(des, scope);
|
||||
if (l == 0) return 0;
|
||||
@@ -113,7 +112,10 @@ verinum* PEBinary::eval_const(Design*des, NetScope*scope) const
|
||||
case 'l': { // left shift (<<)
|
||||
assert(r->is_defined());
|
||||
unsigned long rv = r->as_ulong();
|
||||
res = new verinum(verinum::V0, l->len());
|
||||
unsigned use_wid = l->len();
|
||||
if (! l->has_len())
|
||||
use_wid += rv;
|
||||
res = new verinum(verinum::V0, use_wid);
|
||||
if (rv < res->len()) {
|
||||
unsigned cnt = res->len() - rv;
|
||||
for (unsigned idx = 0 ; idx < cnt ; idx += 1)
|
||||
@@ -143,15 +145,16 @@ verinum* PEBinary::eval_const(Design*des, NetScope*scope) const
|
||||
delete r;
|
||||
return res;
|
||||
}
|
||||
verinum* PEConcat::eval_const(Design*des, NetScope*scope) const
|
||||
|
||||
verinum* PEConcat::eval_const(const Design*des, const NetScope*scope) const
|
||||
{
|
||||
verinum*accum = parms_[0]->eval_const(des, scope);
|
||||
if (accum == 0)
|
||||
return 0;
|
||||
|
||||
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
|
||||
|
||||
verinum*tmp = parms_[idx]->eval_const(des, scope);
|
||||
/* Oops, found an argument that is not constant. Give up. */
|
||||
if (tmp == 0) {
|
||||
delete accum;
|
||||
return 0;
|
||||
@@ -165,29 +168,14 @@ verinum* PEConcat::eval_const(Design*des, NetScope*scope) const
|
||||
return accum;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Evaluate an identifier as a constant expression. This is only
|
||||
* possible if the identifier is that of a parameter.
|
||||
*/
|
||||
verinum* PEIdent::eval_const(Design*des, NetScope*scope) const
|
||||
verinum* PEIdent::eval_const(const Design*des, const NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
NetNet*net;
|
||||
NetEvent*eve;
|
||||
const NetExpr*expr;
|
||||
|
||||
const name_component_t&name_tail = path_.back();
|
||||
|
||||
// Handle the special case that this ident is a genvar
|
||||
// variable name. In that case, the genvar meaning preempts
|
||||
// everything and we just return that value immediately.
|
||||
if (scope->genvar_tmp
|
||||
&& strcmp(name_tail.name,scope->genvar_tmp) == 0) {
|
||||
return new verinum(scope->genvar_tmp_val);
|
||||
}
|
||||
|
||||
symbol_search(des, scope, path_, net, expr, eve);
|
||||
const NetExpr*expr = des->find_parameter(scope, path_);
|
||||
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
@@ -202,30 +190,30 @@ verinum* PEIdent::eval_const(Design*des, NetScope*scope) const
|
||||
|
||||
assert(eval);
|
||||
|
||||
if (!name_tail.index.empty())
|
||||
if (msb_ || lsb_)
|
||||
return 0;
|
||||
|
||||
|
||||
return new verinum(eval->value());
|
||||
}
|
||||
|
||||
verinum* PEFNumber::eval_const(Design*, NetScope*) const
|
||||
verinum* PEFNumber::eval_const(const Design*, const NetScope*) const
|
||||
{
|
||||
long val = value_->as_long();
|
||||
return new verinum(val);
|
||||
}
|
||||
|
||||
verinum* PENumber::eval_const(Design*, NetScope*) const
|
||||
verinum* PENumber::eval_const(const Design*, const NetScope*) const
|
||||
{
|
||||
return new verinum(value());
|
||||
}
|
||||
|
||||
verinum* PEString::eval_const(Design*, NetScope*) const
|
||||
verinum* PEString::eval_const(const Design*, const NetScope*) const
|
||||
{
|
||||
return new verinum(string(text_));
|
||||
}
|
||||
|
||||
verinum* PETernary::eval_const(Design*des, NetScope*scope) const
|
||||
verinum* PETernary::eval_const(const Design*des, const NetScope*scope) const
|
||||
{
|
||||
verinum*test = expr_->eval_const(des, scope);
|
||||
if (test == 0)
|
||||
@@ -245,7 +233,7 @@ verinum* PETernary::eval_const(Design*des, NetScope*scope) const
|
||||
}
|
||||
}
|
||||
|
||||
verinum* PEUnary::eval_const(Design*des, NetScope*scope) const
|
||||
verinum* PEUnary::eval_const(const Design*des, const NetScope*scope) const
|
||||
{
|
||||
verinum*val = expr_->eval_const(des, scope);
|
||||
if (val == 0)
|
||||
@@ -259,7 +247,7 @@ verinum* PEUnary::eval_const(Design*des, NetScope*scope) const
|
||||
/* We need to expand the value a bit if we are
|
||||
taking the 2's complement so that we are
|
||||
guaranteed to not overflow. */
|
||||
verinum tmp ((uint64_t)0, val->len()+1);
|
||||
verinum tmp (0UL, val->len()+1);
|
||||
for (unsigned idx = 0 ; idx < val->len() ; idx += 1)
|
||||
tmp.set(idx, val->get(idx));
|
||||
|
||||
@@ -276,42 +264,14 @@ verinum* PEUnary::eval_const(Design*des, NetScope*scope) const
|
||||
|
||||
/*
|
||||
* $Log: eval.cc,v $
|
||||
* Revision 1.47 2007/06/04 19:14:06 steve
|
||||
* Build errors in picky GCC compilers.
|
||||
* Revision 1.36.2.3 2006/09/20 20:27:02 steve
|
||||
* Fix left shift of small unsized constants.
|
||||
*
|
||||
* Revision 1.46 2007/05/24 04:07:12 steve
|
||||
* Rework the heirarchical identifier parse syntax and pform
|
||||
* to handle more general combinations of heirarch and bit selects.
|
||||
* Revision 1.36.2.2 2005/12/18 21:06:01 steve
|
||||
* Properly fail when concat is not actually constant.
|
||||
*
|
||||
* Revision 1.45 2007/03/07 00:38:15 steve
|
||||
* Lint fixes.
|
||||
*
|
||||
* Revision 1.44 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.43 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.42 2006/05/19 04:07:24 steve
|
||||
* eval_const is not strict.
|
||||
*
|
||||
* Revision 1.41 2006/05/17 16:49:30 steve
|
||||
* Error message if concat expression cannot evaluate.
|
||||
*
|
||||
* Revision 1.40 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.39 2005/12/07 04:04:23 steve
|
||||
* Allow constant concat expressions.
|
||||
*
|
||||
* Revision 1.38 2005/11/27 17:01:57 steve
|
||||
* Fix for stubborn compiler.
|
||||
*
|
||||
* Revision 1.37 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
* Revision 1.36.2.1 2005/12/07 03:28:44 steve
|
||||
* Support constant concatenation of constants.
|
||||
*
|
||||
* Revision 1.36 2003/06/21 01:21:43 steve
|
||||
* Harmless fixup of warnings.
|
||||
|
||||
+3
-8
@@ -17,7 +17,7 @@
|
||||
* 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 $"
|
||||
#ident "$Id: eval_attrib.cc,v 1.7 2004/02/20 18:53:35 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -35,7 +35,8 @@
|
||||
|
||||
attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
|
||||
unsigned&natt,
|
||||
Design*des, NetScope*scope)
|
||||
const Design*des,
|
||||
const NetScope*scope)
|
||||
{
|
||||
natt = att.size();
|
||||
if (natt == 0)
|
||||
@@ -73,12 +74,6 @@ attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
|
||||
|
||||
/*
|
||||
* $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.
|
||||
*
|
||||
|
||||
+252
-391
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: eval_tree.cc,v 1.77 2007/06/02 03:42:12 steve Exp $"
|
||||
#ident "$Id: eval_tree.cc,v 1.62.2.5 2007/03/23 23:02:31 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -26,9 +26,8 @@
|
||||
# include <iostream>
|
||||
|
||||
# include "netlist.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
NetExpr* NetExpr::eval_tree(int prune_to_width)
|
||||
NetExpr* NetExpr::eval_tree()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -52,148 +51,33 @@ void NetEBinary::eval_sub_tree_()
|
||||
}
|
||||
}
|
||||
|
||||
bool NetEBinary::get_real_arguments_(verireal&lval, verireal&rval)
|
||||
{
|
||||
switch (left_->expr_type()) {
|
||||
case IVL_VT_REAL: {
|
||||
NetECReal*lc = dynamic_cast<NetECReal*> (left_);
|
||||
if (lc == 0) return false;
|
||||
lval = lc->value();
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC: {
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return false;
|
||||
verinum tmp = lc->value();
|
||||
lval = verireal(tmp.as_long());
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
switch (right_->expr_type()) {
|
||||
case IVL_VT_REAL: {
|
||||
NetECReal*rc = dynamic_cast<NetECReal*> (right_);
|
||||
if (rc == 0) return 0;
|
||||
rval = rc->value();
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC: {
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
verinum tmp = rc->value();
|
||||
rval = verireal(tmp.as_long());
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NetExpr* NetEBAdd::eval_tree(int prune_to_width)
|
||||
NetEConst* NetEBAdd::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
if (left_->expr_type() == IVL_VT_REAL || right_->expr_type()==IVL_VT_REAL)
|
||||
return eval_tree_real_();
|
||||
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
|
||||
/* If both operands are constant, then replace the entire
|
||||
expression with a constant value. */
|
||||
if (lc != 0 && rc != 0) {
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
|
||||
verinum val;
|
||||
switch (op_) {
|
||||
case '+':
|
||||
val = lval + rval;
|
||||
break;
|
||||
case '-':
|
||||
val = lval - rval;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
return new NetEConst(val);
|
||||
}
|
||||
|
||||
/* Try to combine a right constant value with the right
|
||||
constant value of a sub-expression add. For example, the
|
||||
expression (a + 2) - 1 can be rewritten as a + 1. */
|
||||
|
||||
NetEBAdd*se = dynamic_cast<NetEBAdd*>(left_);
|
||||
lc = se? dynamic_cast<NetEConst*>(se->right_) : 0;
|
||||
|
||||
if (lc != 0 && rc != 0) {
|
||||
assert(se != 0);
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
|
||||
verinum val;
|
||||
if (op_ == se->op_) {
|
||||
/* (a + lval) + rval --> a + (rval+lval) */
|
||||
/* (a - lval) - rval --> a - (rval+lval) */
|
||||
val = rval + lval;
|
||||
} else {
|
||||
/* (a - lval) + rval --> a + (rval-lval) */
|
||||
/* (a + lval) - rval --> a - (rval-lval) */
|
||||
val = rval - lval;
|
||||
}
|
||||
|
||||
NetEConst*tmp = new NetEConst(val);
|
||||
left_ = se->left_->dup_expr();
|
||||
delete se;
|
||||
delete right_;
|
||||
right_ = tmp;
|
||||
/* We've changed the subexpression, but the result is
|
||||
still not constant, so return nil here anyhow. */
|
||||
verinum val;
|
||||
switch (op_) {
|
||||
case '+':
|
||||
val = lval + rval;
|
||||
break;
|
||||
case '-':
|
||||
val = lval - rval;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Nothing more to be done, the value is not constant. */
|
||||
return 0;
|
||||
return new NetEConst(val);
|
||||
}
|
||||
|
||||
NetECReal* NetEBAdd::eval_tree_real_()
|
||||
{
|
||||
verireal lval;
|
||||
verireal rval;
|
||||
bool flag = get_real_arguments_(lval, rval);
|
||||
if (!flag) return 0;
|
||||
|
||||
verireal res_val;
|
||||
|
||||
switch (op()) {
|
||||
case '+':
|
||||
res_val = lval + rval;
|
||||
break;
|
||||
case '-':
|
||||
res_val = lval - rval;
|
||||
break;
|
||||
default:
|
||||
ivl_assert(*this, 0);
|
||||
}
|
||||
|
||||
NetECReal*res = new NetECReal( res_val );
|
||||
res->set_line(*this);
|
||||
return res;
|
||||
}
|
||||
|
||||
NetEConst* NetEBBits::eval_tree(int prune_to_width)
|
||||
NetEConst* NetEBBits::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
@@ -291,9 +175,51 @@ NetEConst* NetEBBits::eval_tree(int prune_to_width)
|
||||
return new NetEConst(res);
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_eqeq_()
|
||||
{
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
||||
const verinum&lv = l->value();
|
||||
const verinum&rv = r->value();
|
||||
|
||||
unsigned s_len = lv.len();
|
||||
if (rv.len() < s_len) s_len = rv.len();
|
||||
|
||||
verinum result(verinum::V1, 1);
|
||||
for (unsigned idx = 0 ; idx < s_len; idx += 1) {
|
||||
if (lv[idx] != rv[idx])
|
||||
result = verinum::V0;
|
||||
}
|
||||
|
||||
// If one operand was wider than the other, check that the
|
||||
// remaining bits are all zero
|
||||
if (lv.len() > s_len) {
|
||||
for (unsigned idx = s_len; idx < lv.len(); idx += 1) {
|
||||
if (lv[idx] != 0)
|
||||
result = verinum::V0;
|
||||
}
|
||||
}
|
||||
if (rv.len() > s_len) {
|
||||
for (unsigned idx = s_len; idx < rv.len(); idx += 1) {
|
||||
if (rv[idx] != 0)
|
||||
result = verinum::V0;
|
||||
}
|
||||
}
|
||||
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
|
||||
NetEConst* NetEBComp::eval_less_()
|
||||
{
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(false, false);
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(false, false);
|
||||
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
|
||||
@@ -303,27 +229,32 @@ NetEConst* NetEBComp::eval_less_()
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (left_->expr_width() == 0) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Having trouble evaluating left expression of < op."
|
||||
<< endl;
|
||||
cerr << get_line() << ": : "
|
||||
<< "Expression is: "
|
||||
<< *this << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Detect the case where the right side is greater than or
|
||||
/* Detect the case where the right side is greater that or
|
||||
equal to the largest value the left side can possibly
|
||||
have. Use the width of the left expression as all 1's to
|
||||
calculate the maximum possible width for the left_
|
||||
expression. This test only works of the compare is
|
||||
unsigned. */
|
||||
if (! (rv.has_sign() || left_->has_sign())) {
|
||||
|
||||
assert(left_->expr_width() > 0);
|
||||
verinum lv (verinum::V1, left_->expr_width());
|
||||
if (lv < rv) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
have. */
|
||||
assert(left_->expr_width() > 0);
|
||||
verinum lv (verinum::V1, left_->expr_width() + 1);
|
||||
lv.set(left_->expr_width(), verinum::V0);
|
||||
lv.has_sign( left_->has_sign() );
|
||||
if ((lv < rv) == verinum::V1) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
/* Now go on to the normal test of the values. */
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
verinum lv = l->value();
|
||||
lv = l->value();
|
||||
if (! lv.is_defined()) {
|
||||
verinum result(verinum::Vx, 1);
|
||||
return new NetEConst(result);
|
||||
@@ -345,14 +276,14 @@ NetEConst* NetEBComp::eval_less_()
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_leeq_real_()
|
||||
NetEConst* NetEBComp::eval_leeq_real_(bool gt_flag, bool include_eq_flag)
|
||||
{
|
||||
NetEConst*vtmp;
|
||||
NetECReal*rtmp;
|
||||
double lv, rv;
|
||||
|
||||
switch (left_->expr_type()) {
|
||||
case IVL_VT_REAL:
|
||||
case ET_REAL:
|
||||
rtmp = dynamic_cast<NetECReal*> (left_);
|
||||
if (rtmp == 0)
|
||||
return 0;
|
||||
@@ -360,7 +291,7 @@ NetEConst* NetEBComp::eval_leeq_real_()
|
||||
lv = rtmp->value().as_double();
|
||||
break;
|
||||
|
||||
case IVL_VT_LOGIC:
|
||||
case ET_VECTOR:
|
||||
vtmp = dynamic_cast<NetEConst*> (left_);
|
||||
if (vtmp == 0)
|
||||
return 0;
|
||||
@@ -374,7 +305,7 @@ NetEConst* NetEBComp::eval_leeq_real_()
|
||||
|
||||
|
||||
switch (right_->expr_type()) {
|
||||
case IVL_VT_REAL:
|
||||
case ET_REAL:
|
||||
rtmp = dynamic_cast<NetECReal*> (right_);
|
||||
if (rtmp == 0)
|
||||
return 0;
|
||||
@@ -382,7 +313,7 @@ NetEConst* NetEBComp::eval_leeq_real_()
|
||||
rv = rtmp->value().as_double();
|
||||
break;
|
||||
|
||||
case IVL_VT_LOGIC:
|
||||
case ET_VECTOR:
|
||||
vtmp = dynamic_cast<NetEConst*> (right_);
|
||||
if (vtmp == 0)
|
||||
return 0;
|
||||
@@ -394,7 +325,16 @@ NetEConst* NetEBComp::eval_leeq_real_()
|
||||
assert(0);
|
||||
}
|
||||
|
||||
verinum result((lv <= rv)? verinum::V1 : verinum::V0, 1);
|
||||
/* This function supports < and <=. If the eq_flag is true,
|
||||
then include <=. Otherwise, include only <. */
|
||||
bool flag;
|
||||
if (gt_flag)
|
||||
flag = include_eq_flag? (lv >= rv) : (lv > rv);
|
||||
else
|
||||
flag = include_eq_flag? (lv <= rv) : (lv < rv);
|
||||
|
||||
|
||||
verinum result(flag? verinum::V1 : verinum::V0, 1);
|
||||
vtmp = new NetEConst(result);
|
||||
vtmp->set_line(*this);
|
||||
|
||||
@@ -403,10 +343,10 @@ NetEConst* NetEBComp::eval_leeq_real_()
|
||||
|
||||
NetEConst* NetEBComp::eval_leeq_()
|
||||
{
|
||||
if (right_->expr_type() == IVL_VT_REAL)
|
||||
return eval_leeq_real_();
|
||||
if (left_->expr_type() == IVL_VT_REAL)
|
||||
return eval_leeq_real_();
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(false, true);
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(false, true);
|
||||
|
||||
NetEConst*r = dynamic_cast<NetEConst*>(right_);
|
||||
if (r == 0) return 0;
|
||||
@@ -427,7 +367,9 @@ NetEConst* NetEBComp::eval_leeq_()
|
||||
equal to the largest value the left side can possibly
|
||||
have. */
|
||||
assert(left_->expr_width() > 0);
|
||||
verinum lv (verinum::V1, left_->expr_width());
|
||||
verinum lv (verinum::V1, left_->expr_width() + 1);
|
||||
lv.set(left_->expr_width(), verinum::V0);
|
||||
lv.has_sign( left_->has_sign() );
|
||||
if (lv <= rv) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
@@ -460,23 +402,10 @@ NetEConst* NetEBComp::eval_leeq_()
|
||||
|
||||
NetEConst* NetEBComp::eval_gt_()
|
||||
{
|
||||
if ((left_->expr_type() == IVL_VT_REAL)
|
||||
&& (right_->expr_type() == IVL_VT_REAL)) {
|
||||
|
||||
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_);
|
||||
if (tmpl == 0)
|
||||
return 0;
|
||||
|
||||
NetECReal*tmpr = dynamic_cast<NetECReal*>(right_);
|
||||
if (tmpr == 0)
|
||||
return 0;
|
||||
|
||||
double ll = tmpl->value().as_double();
|
||||
double rr = tmpr->value().as_double();
|
||||
|
||||
verinum result ((ll > rr)? verinum::V1 : verinum::V0, 1, true);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(true, false);
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(true, false);
|
||||
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
@@ -499,7 +428,7 @@ NetEConst* NetEBComp::eval_gt_()
|
||||
}
|
||||
|
||||
/* Compare with a real value. Do it as double precision. */
|
||||
if (right_->expr_type() == IVL_VT_REAL) {
|
||||
if (right_->expr_type() == NetExpr::ET_REAL) {
|
||||
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
|
||||
if (tmp == 0)
|
||||
return 0;
|
||||
@@ -536,23 +465,10 @@ NetEConst* NetEBComp::eval_gt_()
|
||||
|
||||
NetEConst* NetEBComp::eval_gteq_()
|
||||
{
|
||||
if ((left_->expr_type() == IVL_VT_REAL)
|
||||
&& (right_->expr_type() == IVL_VT_REAL)) {
|
||||
|
||||
NetECReal*tmpl = dynamic_cast<NetECReal*>(left_);
|
||||
if (tmpl == 0)
|
||||
return 0;
|
||||
|
||||
NetECReal*tmpr = dynamic_cast<NetECReal*>(right_);
|
||||
if (tmpr == 0)
|
||||
return 0;
|
||||
|
||||
double ll = tmpl->value().as_double();
|
||||
double rr = tmpr->value().as_double();
|
||||
|
||||
verinum result ((ll >= rr)? verinum::V1 : verinum::V0, 1, true);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(true, true);
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return eval_leeq_real_(true, true);
|
||||
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
@@ -565,7 +481,7 @@ NetEConst* NetEBComp::eval_gteq_()
|
||||
|
||||
/* Detect the case where the left side is greater than the
|
||||
largest value the right side can possibly have. */
|
||||
if (right_->expr_type() == IVL_VT_LOGIC) {
|
||||
if (right_->expr_type() == NetExpr::ET_VECTOR) {
|
||||
assert(right_->expr_width() > 0);
|
||||
verinum rv (verinum::V1, right_->expr_width());
|
||||
if (lv >= rv) {
|
||||
@@ -575,7 +491,7 @@ NetEConst* NetEBComp::eval_gteq_()
|
||||
}
|
||||
|
||||
/* Compare with a real value. Do it as double precision. */
|
||||
if (right_->expr_type() == IVL_VT_REAL) {
|
||||
if (right_->expr_type() == NetExpr::ET_REAL) {
|
||||
NetECReal*tmp = dynamic_cast<NetECReal*>(right_);
|
||||
if (tmp == 0)
|
||||
return 0;
|
||||
@@ -596,25 +512,21 @@ NetEConst* NetEBComp::eval_gteq_()
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (lv.has_sign() && rv.has_sign()) {
|
||||
if (lv.has_sign() && rv.has_sign() && (lv.as_long() >= rv.as_long())) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
if (lv.as_long() >= rv.as_long()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
} else {
|
||||
|
||||
if (lv.as_ulong() >= rv.as_ulong()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
if (lv.as_ulong() >= rv.as_ulong()) {
|
||||
verinum result(verinum::V1, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
verinum result(verinum::V0, 1);
|
||||
return new NetEConst(result);
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
|
||||
NetEConst* NetEBComp::eval_neeq_()
|
||||
{
|
||||
NetEConst*l = dynamic_cast<NetEConst*>(left_);
|
||||
if (l == 0) return 0;
|
||||
@@ -624,10 +536,7 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
|
||||
const verinum&lv = l->value();
|
||||
const verinum&rv = r->value();
|
||||
|
||||
const verinum::V eq_res = ne_flag? verinum::V0 : verinum::V1;
|
||||
const verinum::V ne_res = ne_flag? verinum::V1 : verinum::V0;
|
||||
|
||||
verinum::V res = eq_res;
|
||||
verinum::V res = verinum::V0;
|
||||
unsigned top = lv.len();
|
||||
if (rv.len() < top)
|
||||
top = rv.len();
|
||||
@@ -660,18 +569,10 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
|
||||
break;
|
||||
|
||||
if (rv.get(idx) != lv.get(idx))
|
||||
res = ne_res;
|
||||
res = verinum::V1;
|
||||
}
|
||||
|
||||
if (res != verinum::Vx) {
|
||||
verinum::V lpad = verinum::V0;
|
||||
verinum::V rpad = verinum::V0;
|
||||
|
||||
if (lv.has_sign() && lv.get(lv.len()-1) == verinum::V1)
|
||||
lpad = verinum::V1;
|
||||
if (rv.has_sign() && rv.get(rv.len()-1) == verinum::V1)
|
||||
rpad = verinum::V1;
|
||||
|
||||
for (unsigned idx = top ; idx < lv.len() ; idx += 1)
|
||||
switch (lv.get(idx)) {
|
||||
|
||||
@@ -680,14 +581,9 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
|
||||
res = verinum::Vx;
|
||||
break;
|
||||
|
||||
case verinum::V0:
|
||||
if (res != verinum::Vx && rpad != verinum::V0)
|
||||
res = ne_res;
|
||||
break;
|
||||
|
||||
case verinum::V1:
|
||||
if (res != verinum::Vx && rpad != verinum::V1)
|
||||
res = ne_res;
|
||||
if (res != verinum::Vx)
|
||||
res = verinum::V1;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -702,14 +598,9 @@ NetEConst* NetEBComp::eval_eqeq_(bool ne_flag)
|
||||
res = verinum::Vx;
|
||||
break;
|
||||
|
||||
case verinum::V0:
|
||||
if (res != verinum::Vx && lpad != verinum::V0)
|
||||
res = ne_res;
|
||||
break;
|
||||
|
||||
case verinum::V1:
|
||||
if (res != verinum::Vx && lpad != verinum::V1)
|
||||
res = ne_res;
|
||||
if (res != verinum::Vx)
|
||||
res = verinum::V1;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -768,7 +659,7 @@ NetEConst* NetEBComp::eval_neeqeq_()
|
||||
return res;
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_tree(int prune_to_width)
|
||||
NetEConst* NetEBComp::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
@@ -777,7 +668,7 @@ NetEConst* NetEBComp::eval_tree(int prune_to_width)
|
||||
return eval_eqeqeq_();
|
||||
|
||||
case 'e': // Equality (==)
|
||||
return eval_eqeq_(false);
|
||||
return eval_eqeq_();
|
||||
|
||||
case 'G': // >=
|
||||
return eval_gteq_();
|
||||
@@ -789,7 +680,7 @@ NetEConst* NetEBComp::eval_tree(int prune_to_width)
|
||||
return eval_neeqeq_();
|
||||
|
||||
case 'n': // not-equal (!=)
|
||||
return eval_eqeq_(true);
|
||||
return eval_neeq_();
|
||||
|
||||
case '<': // Less than
|
||||
return eval_less_();
|
||||
@@ -806,11 +697,11 @@ NetEConst* NetEBComp::eval_tree(int prune_to_width)
|
||||
* The NetEBDiv operator includes the / and % operators. First evaluate
|
||||
* the sub-expressions, then perform the required operation.
|
||||
*/
|
||||
NetExpr* NetEBDiv::eval_tree(int prune_to_width)
|
||||
NetExpr* NetEBDiv::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
if (expr_type() == IVL_VT_REAL) {
|
||||
if (expr_type() == NetExpr::ET_REAL) {
|
||||
NetECReal*lc = dynamic_cast<NetECReal*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
|
||||
@@ -855,7 +746,7 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
|
||||
|
||||
|
||||
} else {
|
||||
assert(expr_type() == IVL_VT_LOGIC);
|
||||
assert(expr_type() == NetExpr::ET_VECTOR);
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
@@ -876,7 +767,7 @@ NetExpr* NetEBDiv::eval_tree(int prune_to_width)
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst* NetEBLogic::eval_tree(int prune_to_width)
|
||||
NetEConst* NetEBLogic::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
@@ -942,14 +833,50 @@ NetEConst* NetEBLogic::eval_tree(int prune_to_width)
|
||||
return new NetEConst(verinum(res, 1));
|
||||
}
|
||||
|
||||
|
||||
NetExpr* NetEBMult::eval_tree_real_()
|
||||
{
|
||||
verireal lval;
|
||||
verireal rval;
|
||||
|
||||
bool flag = get_real_arguments_(lval, rval);
|
||||
if (! flag) return 0;
|
||||
switch (left_->expr_type()) {
|
||||
case ET_REAL: {
|
||||
NetECReal*lc = dynamic_cast<NetECReal*> (left_);
|
||||
if (lc == 0) return 0;
|
||||
lval = lc->value();
|
||||
break;
|
||||
}
|
||||
|
||||
case ET_VECTOR: {
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
verinum tmp = lc->value();
|
||||
lval = verireal(tmp.as_long());
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
switch (right_->expr_type()) {
|
||||
case ET_REAL: {
|
||||
NetECReal*rc = dynamic_cast<NetECReal*> (right_);
|
||||
if (rc == 0) return 0;
|
||||
rval = rc->value();
|
||||
break;
|
||||
}
|
||||
|
||||
case ET_VECTOR: {
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
verinum tmp = rc->value();
|
||||
rval = verireal(tmp.as_long());
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
NetECReal*res = new NetECReal(lval * rval);
|
||||
@@ -957,14 +884,14 @@ NetExpr* NetEBMult::eval_tree_real_()
|
||||
return res;
|
||||
}
|
||||
|
||||
NetExpr* NetEBMult::eval_tree(int prune_to_width)
|
||||
NetExpr* NetEBMult::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
if (expr_type() == IVL_VT_REAL)
|
||||
if (expr_type() == ET_REAL)
|
||||
return eval_tree_real_();
|
||||
|
||||
assert(expr_type() == IVL_VT_LOGIC);
|
||||
assert(expr_type() == ET_VECTOR);
|
||||
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
@@ -977,45 +904,11 @@ NetExpr* NetEBMult::eval_tree(int prune_to_width)
|
||||
return new NetEConst(lval * rval);
|
||||
}
|
||||
|
||||
NetExpr* NetEBPow::eval_tree_real_()
|
||||
{
|
||||
verireal lval;
|
||||
verireal rval;
|
||||
|
||||
bool flag = get_real_arguments_(lval, rval);
|
||||
if (! flag) return 0;
|
||||
|
||||
NetECReal*res = new NetECReal( pow(lval,rval) );
|
||||
res->set_line(*this);
|
||||
return res;
|
||||
}
|
||||
|
||||
NetExpr* NetEBPow::eval_tree(int prune_to_width)
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
if (expr_type() == IVL_VT_REAL)
|
||||
return eval_tree_real_();
|
||||
|
||||
assert(expr_type() == IVL_VT_LOGIC);
|
||||
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
if (lc == 0) return 0;
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
if (rc == 0) return 0;
|
||||
|
||||
verinum lval = lc->value();
|
||||
verinum rval = rc->value();
|
||||
|
||||
return new NetEConst( pow(lval,rval) );
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Evaluate the shift operator if possible. For this to work, both
|
||||
* operands must be constant.
|
||||
*/
|
||||
NetEConst* NetEBShift::eval_tree(int prune_to_width)
|
||||
NetEConst* NetEBShift::eval_tree()
|
||||
{
|
||||
eval_sub_tree_();
|
||||
NetEConst*re = dynamic_cast<NetEConst*>(right_);
|
||||
@@ -1038,13 +931,6 @@ NetEConst* NetEBShift::eval_tree(int prune_to_width)
|
||||
|
||||
unsigned shift = rv.as_ulong();
|
||||
|
||||
if (debug_eval_tree) {
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Evaluate " << lv << "<<" << op() << ">> "
|
||||
<< rv << ", wid=" << wid << ", shift=" << shift
|
||||
<< ", lv.has_len()=" << lv.has_len() << endl;
|
||||
}
|
||||
|
||||
if ((wid == 0) || ! lv.has_len()) {
|
||||
/* If the caller doesn't care what the width is,
|
||||
then calcuate a width from the trimmed left
|
||||
@@ -1056,9 +942,6 @@ NetEConst* NetEBShift::eval_tree(int prune_to_width)
|
||||
wid = lv.len() + shift;
|
||||
}
|
||||
|
||||
if (prune_to_width > 0 && wid > (unsigned)prune_to_width)
|
||||
wid = prune_to_width;
|
||||
|
||||
assert(wid);
|
||||
verinum nv (verinum::V0, wid, lv.has_len());
|
||||
|
||||
@@ -1099,7 +982,7 @@ NetEConst* NetEBShift::eval_tree(int prune_to_width)
|
||||
return res;
|
||||
}
|
||||
|
||||
NetEConst* NetEConcat::eval_tree(int prune_to_width)
|
||||
NetEConst* NetEConcat::eval_tree()
|
||||
{
|
||||
unsigned repeat_val = repeat();
|
||||
unsigned local_errors = 0;
|
||||
@@ -1193,26 +1076,61 @@ NetEConst* NetEConcat::eval_tree(int prune_to_width)
|
||||
return res;
|
||||
}
|
||||
|
||||
NetExpr* NetEParam::eval_tree(int prune_to_width)
|
||||
/*
|
||||
* There are limits to our ability to evaluate a memory reference
|
||||
* expression, because the content of a memory is never
|
||||
* constant. However, the index expression may be precalculated, and
|
||||
* there are certain index values that do give us constant results.
|
||||
*/
|
||||
NetExpr* NetEMemory::eval_tree()
|
||||
{
|
||||
if (des_ == 0) {
|
||||
assert(scope_ == 0);
|
||||
return 0;
|
||||
/* Attempt to evaluate the index expression to a constant, if
|
||||
it is not already. */
|
||||
if (idx_ && !dynamic_cast<NetEConst*>(idx_)) {
|
||||
NetExpr* tmp = idx_->eval_tree();
|
||||
if (tmp) {
|
||||
delete idx_;
|
||||
idx_ = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: evaluating expression: "
|
||||
<< *this << endl;
|
||||
NetEConst*itmp = dynamic_cast<NetEConst*>(idx_);
|
||||
if (itmp == 0)
|
||||
return 0;
|
||||
|
||||
verinum ival = itmp->value();
|
||||
|
||||
/* If the index expression has any x or z bits, then we know
|
||||
already that the expression result is a constant x. */
|
||||
if (! ival.is_defined()) {
|
||||
verinum xres (verinum::Vx, mem_->width(), false);
|
||||
NetEConst*res = new NetEConst(xres);
|
||||
return res;
|
||||
}
|
||||
|
||||
/* If the index expression is outside the range of the memory,
|
||||
then the result is a constant x. */
|
||||
unsigned norm_idx = mem_->index_to_address(ival.as_long());
|
||||
if (norm_idx >= mem_->count()) {
|
||||
verinum xres (verinum::Vx, mem_->width(), false);
|
||||
NetEConst*res = new NetEConst(xres);
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr* NetEParam::eval_tree()
|
||||
{
|
||||
if (des_ == 0)
|
||||
return 0;
|
||||
|
||||
assert(scope_);
|
||||
const NetExpr*expr_msb;
|
||||
const NetExpr*expr_lsb;
|
||||
const NetExpr*expr = scope_->get_parameter(name_, expr_msb, expr_lsb);
|
||||
const NetExpr*expr = scope_->get_parameter(name_);
|
||||
if (expr == 0) {
|
||||
cerr << get_line() << ": internal error: Unable to match "
|
||||
<< "parameter " << name_ << " in scope "
|
||||
<< scope_path(scope_) << endl;
|
||||
<< scope_->name() << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1259,8 +1177,7 @@ NetExpr* NetEParam::eval_tree(int prune_to_width)
|
||||
|
||||
switch (res->expr_type()) {
|
||||
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC:
|
||||
case NetExpr::ET_VECTOR:
|
||||
{ NetEConst*tmp = dynamic_cast<NetEConst*>(res);
|
||||
if (tmp == 0) {
|
||||
cerr << get_line() << ": internal error: parameter "
|
||||
@@ -1277,7 +1194,7 @@ NetExpr* NetEParam::eval_tree(int prune_to_width)
|
||||
return ptmp;
|
||||
}
|
||||
|
||||
case IVL_VT_REAL:
|
||||
case NetExpr::ET_REAL:
|
||||
{ NetECReal*tmp = dynamic_cast<NetECReal*>(res);
|
||||
if (tmp == 0) {
|
||||
cerr << get_line() << ": internal error: parameter "
|
||||
@@ -1300,7 +1217,7 @@ NetExpr* NetEParam::eval_tree(int prune_to_width)
|
||||
}
|
||||
}
|
||||
|
||||
NetEConst* NetESelect::eval_tree(int prune_to_width)
|
||||
NetEConst* NetESelect::eval_tree()
|
||||
{
|
||||
NetEConst*expr = dynamic_cast<NetEConst*>(expr_);
|
||||
if (expr == 0) {
|
||||
@@ -1313,50 +1230,31 @@ NetEConst* NetESelect::eval_tree(int prune_to_width)
|
||||
expr = dynamic_cast<NetEConst*>(expr_);
|
||||
}
|
||||
|
||||
long bval = 0;
|
||||
if (base_) {
|
||||
NetEConst*base = dynamic_cast<NetEConst*>(base_);
|
||||
if (base == 0) {
|
||||
NetExpr*tmp = base_->eval_tree();
|
||||
if (tmp != 0) {
|
||||
delete base_;
|
||||
base_ = tmp;
|
||||
}
|
||||
|
||||
base = dynamic_cast<NetEConst*>(base_);
|
||||
NetEConst*base = dynamic_cast<NetEConst*>(base_);
|
||||
if (base == 0) {
|
||||
NetExpr*tmp = base_->eval_tree();
|
||||
if (tmp != 0) {
|
||||
delete base_;
|
||||
base_ = tmp;
|
||||
}
|
||||
|
||||
if (base == 0)
|
||||
return 0;
|
||||
|
||||
bval = base->value().as_long();
|
||||
base = dynamic_cast<NetEConst*>(base_);
|
||||
}
|
||||
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
if (base == 0)
|
||||
return 0;
|
||||
|
||||
verinum eval = expr->value();
|
||||
verinum oval (verinum::V0, expr_width(), true);
|
||||
|
||||
verinum::V pad_bit = verinum::Vx;
|
||||
if (base_ == 0) {
|
||||
|
||||
/* If the base is NULL (different from 0) the this
|
||||
select is here for sign extension. So calculate a
|
||||
proper pad bit. Extend x or z or 0, and sign extend 1
|
||||
if this is signed. */
|
||||
unsigned top = expr->expr_width()-1;
|
||||
|
||||
pad_bit = eval.get(top);
|
||||
if (pad_bit==verinum::V1 && !has_sign())
|
||||
pad_bit = verinum::V0;
|
||||
}
|
||||
long bval = base->value().as_long();
|
||||
|
||||
for (unsigned long idx = 0 ; idx < expr_width() ; idx += 1) {
|
||||
if ((bval >= 0) && ((unsigned long) bval < eval.len()))
|
||||
oval.set(idx, eval.get(bval));
|
||||
else
|
||||
oval.set(idx, pad_bit);
|
||||
oval.set(idx, verinum::Vx);
|
||||
|
||||
bval += 1;
|
||||
}
|
||||
@@ -1373,7 +1271,7 @@ NetEConst* NetESelect::eval_tree(int prune_to_width)
|
||||
* evaluates to x or z, then merge the constant bits of the true and
|
||||
* false expressions.
|
||||
*/
|
||||
NetExpr* NetETernary::eval_tree(int prune_to_width)
|
||||
NetExpr* NetETernary::eval_tree()
|
||||
{
|
||||
NetExpr*tmp;
|
||||
|
||||
@@ -1510,7 +1408,7 @@ void NetEUnary::eval_expr_()
|
||||
expr_ = oper;
|
||||
}
|
||||
|
||||
NetEConst* NetEUnary::eval_tree(int prune_to_width)
|
||||
NetEConst* NetEUnary::eval_tree()
|
||||
{
|
||||
eval_expr_();
|
||||
NetEConst*rval = dynamic_cast<NetEConst*>(expr_);
|
||||
@@ -1567,12 +1465,12 @@ NetEConst* NetEUnary::eval_tree(int prune_to_width)
|
||||
}
|
||||
|
||||
|
||||
NetEConst* NetEUBits::eval_tree(int prune_to_width)
|
||||
NetEConst* NetEUBits::eval_tree()
|
||||
{
|
||||
return NetEUnary::eval_tree(prune_to_width);
|
||||
return NetEUnary::eval_tree();
|
||||
}
|
||||
|
||||
NetEConst* NetEUReduce::eval_tree(int prune_to_width)
|
||||
NetEConst* NetEUReduce::eval_tree()
|
||||
{
|
||||
eval_expr_();
|
||||
NetEConst*rval = dynamic_cast<NetEConst*>(expr_);
|
||||
@@ -1655,57 +1553,20 @@ NetEConst* NetEUReduce::eval_tree(int prune_to_width)
|
||||
|
||||
/*
|
||||
* $Log: eval_tree.cc,v $
|
||||
* Revision 1.77 2007/06/02 03:42:12 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
* Revision 1.62.2.5 2007/03/23 23:02:31 steve
|
||||
* Fix compile time eval of <= comparison.
|
||||
*
|
||||
* Revision 1.76 2007/05/31 18:36:06 steve
|
||||
* Fix warning (ldolittle)
|
||||
* Revision 1.62.2.4 2007/03/23 20:59:25 steve
|
||||
* Fix compile time evaluation of < operator.
|
||||
*
|
||||
* Revision 1.75 2007/04/07 04:46:18 steve
|
||||
* Handle evaluate of addition of real valued constants.
|
||||
* Revision 1.62.2.3 2005/09/09 02:17:08 steve
|
||||
* Evaluate magnitude compare with real operands.
|
||||
*
|
||||
* Revision 1.74 2007/03/08 05:30:02 steve
|
||||
* Limit the calculated widths of constants.
|
||||
* Revision 1.62.2.2 2005/09/04 15:41:54 steve
|
||||
* More explicit internal error message.
|
||||
*
|
||||
* Revision 1.73 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.72 2006/11/04 06:16:27 steve
|
||||
* Fix padding of constant eval of NetESelect.
|
||||
*
|
||||
* Revision 1.71 2006/10/30 05:44:49 steve
|
||||
* Expression widths with unsized literals are pseudo-infinite width.
|
||||
*
|
||||
* Revision 1.70 2006/09/19 23:00:15 steve
|
||||
* Use elab_and_eval for bit select expressions.
|
||||
*
|
||||
* Revision 1.69 2006/07/31 03:50:17 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.68 2006/03/18 22:52:27 steve
|
||||
* Properly handle signedness in compare.
|
||||
*
|
||||
* Revision 1.67 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
* Revision 1.66 2005/11/10 13:28:12 steve
|
||||
* Reorganize signal part select handling, and add support for
|
||||
* indexed part selects.
|
||||
*
|
||||
* Expand expression constant propagation to eliminate extra
|
||||
* sums in certain cases.
|
||||
*
|
||||
* Revision 1.65 2005/09/14 02:53:14 steve
|
||||
* Support bool expressions and compares handle them optimally.
|
||||
*
|
||||
* Revision 1.64 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.63 2005/06/17 05:05:53 steve
|
||||
* Watch out for signed constants in magnitude compare.
|
||||
* Revision 1.62.2.1 2005/09/04 15:39:19 steve
|
||||
* More explicit internal error message.
|
||||
*
|
||||
* Revision 1.62 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: hello_vpi.c,v 1.5 2007/01/17 05:35:48 steve Exp $"
|
||||
#ident "$Id: hello_vpi.c,v 1.3 2002/08/12 01:35:01 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
# include <vpi_user.h>
|
||||
|
||||
static PLI_INT32 my_hello_calltf(char *xx)
|
||||
static int my_hello_calltf(char *xx)
|
||||
{
|
||||
vpi_printf("Hello World, from VPI.\n");
|
||||
return 0;
|
||||
@@ -62,12 +62,6 @@ void (*vlog_startup_routines[])() = {
|
||||
};
|
||||
/*
|
||||
* $Log: hello_vpi.c,v $
|
||||
* Revision 1.5 2007/01/17 05:35:48 steve
|
||||
* Fix typo is hello_vpi.c example.
|
||||
*
|
||||
* Revision 1.4 2006/10/30 22:46:25 steve
|
||||
* Updates for Cygwin portability (pr1585922)
|
||||
*
|
||||
* Revision 1.3 2002/08/12 01:35:01 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* $Id: sqrt-virtex.v,v 1.5 2007/03/22 16:08:18 steve Exp $"
|
||||
* $Id: sqrt-virtex.v,v 1.4.2.2 2005/02/23 18:37:52 steve Exp $"
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -130,7 +130,7 @@
|
||||
* contains Verilog code that simulates the mapped design. This output
|
||||
* Verilog has the single root module "chip_root", which came from the
|
||||
* name of the root module when we were making the EDIF file in the
|
||||
* first place. The module has ports named just line the ports of the
|
||||
* first place. The module has ports named just like the ports of the
|
||||
* chip_root module below.
|
||||
*
|
||||
* The generated Verilog uses the library in the directory
|
||||
@@ -183,7 +183,7 @@
|
||||
* where sqrt(y) is the exact square root of y and floor(N) is the
|
||||
* largest integer <= N.
|
||||
*
|
||||
* For 32 bit numbers, this will never run more than 16 iterations,
|
||||
* For 32bit numbers, this will never run more then 16 iterations,
|
||||
* which amounts to 16 clocks.
|
||||
*/
|
||||
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*
|
||||
* $Id: sqrt.vl,v 1.5 2007/03/22 16:08:18 steve Exp $"
|
||||
* $Id: sqrt.vl,v 1.4 2004/10/04 01:10:56 steve Exp $"
|
||||
*/
|
||||
|
||||
/*
|
||||
@@ -50,7 +50,7 @@
|
||||
* where sqrt(y) is the exact square root of y and floor(N) is the
|
||||
* largest integer <= N.
|
||||
*
|
||||
* For 32 bit numbers, this will never run more than 16 iterations,
|
||||
* For 32bit numbers, this will never run more then 16 iterations,
|
||||
* which amounts to 16 clocks.
|
||||
*/
|
||||
|
||||
|
||||
+542
-451
File diff suppressed because it is too large
Load Diff
@@ -1,84 +0,0 @@
|
||||
|
||||
Icarus Verilog Extensions
|
||||
|
||||
Icarus Verilog supports certain extensions to the baseline IEEE1364
|
||||
standard. Some of these are picked from extended variants of the
|
||||
language, such as SystemVerilog, and some are expressions of internal
|
||||
behavior of Icarus Verilog, made available as a tool debugging aid.
|
||||
|
||||
* Builtin System Functions
|
||||
|
||||
** Extended Verilog Data Types
|
||||
|
||||
This feature is turned off if the generation flag "-g" is set to other
|
||||
then the default "2x". For example, "iverilog -g2x" enables extended
|
||||
data types, and "iverilog -g2" disables them.
|
||||
|
||||
Icarus Verilog adds support for extended data types. This extended
|
||||
type syntax is based on a proposal by Cadence Design Systems,
|
||||
originally as an update to the IEEE1364. That original proposal has
|
||||
apparently been absorbed by the IEEE1800 SystemVerilog
|
||||
standard. Icarus Verilog currently only takes the new primitive types
|
||||
from the proposal.
|
||||
|
||||
Extended data types separates the concept of net/variable from the
|
||||
data type. Both nets and variables can declared with any data
|
||||
type. The primitive types available are:
|
||||
|
||||
logic - The familiar 0, 1, x and z, optionally with strength.
|
||||
bool - Limited to only 0 and 1
|
||||
real - 64bit real values
|
||||
|
||||
Nets with logic type may have multiple drivers with strength, and the
|
||||
value is resolved the usual way. Only logic values may be driven to
|
||||
logic nets, so bool values driven onto logic nets are implicitly
|
||||
converted to logic.
|
||||
|
||||
Nets with any other type may not have multiple drivers. The compiler
|
||||
should detect the multiple drivers and report an error.
|
||||
|
||||
- Declarations
|
||||
|
||||
The declaration of a net is extended to include the type of the wire,
|
||||
with the syntax:
|
||||
|
||||
wire <type> <wire-assignment-list>... ;
|
||||
|
||||
The <type>, if omitted, is taken to be logic. The "wire" can be any of
|
||||
the net keywords. Wires can be logic, bool, real, or vectors of logic
|
||||
or bool. Some valid examples:
|
||||
|
||||
wire real foo = 1.0;
|
||||
tri logic bus[31:0];
|
||||
wire bool addr[23:0];
|
||||
... and so on.
|
||||
|
||||
The declarations of variables is similar. The "reg" keyword is used to
|
||||
specify that this is a variable. Variables can have the same data
|
||||
types as nets.
|
||||
|
||||
- Ports
|
||||
|
||||
Module and task ports in standard verilog are restricted to logic
|
||||
types. This extension removes that restriction, allowing any type to
|
||||
pass through the port consistent with the continuous assignment
|
||||
connectivity that is implied by the type.
|
||||
|
||||
- Expressions
|
||||
|
||||
Expressions in the face of real values is covered by the baseline
|
||||
Verilog standard.
|
||||
|
||||
The bool type supports the same operators as the logic type, with the
|
||||
obvious differences imposed by the limited domain.
|
||||
|
||||
Comparison operators (not case compare) return logic if either of
|
||||
their operands is logic. If both are bool or real (including mix of
|
||||
bool and real) then the result is bool. This is because comparison of
|
||||
bools and reals always return exactly true or false.
|
||||
|
||||
Case comparison returns bool. This differs from baseline Verilog,
|
||||
which strictly speaking returns a logic, but only 0 or 1 values.
|
||||
|
||||
All the arithmetic operators return bool if both of their operands are
|
||||
bool or real. Otherwise, they return logic.
|
||||
+7
-32
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2002 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: functor.cc,v 1.35 2005/07/07 16:22:49 steve Exp $"
|
||||
#ident "$Id: functor.cc,v 1.32.2.1 2006/04/23 04:26:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -59,10 +59,6 @@ void functor_t::lpm_divide(class Design*, class NetDivide*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_literal(class Design*, class NetLiteral*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_modulo(class Design*, class NetModulo*)
|
||||
{
|
||||
}
|
||||
@@ -83,15 +79,10 @@ void functor_t::lpm_mux(class Design*, class NetMux*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::sign_extend(class Design*, class NetSignExtend*)
|
||||
void functor_t::lpm_ram_dq(class Design*, class NetRamDq*)
|
||||
{
|
||||
}
|
||||
|
||||
void functor_t::lpm_ureduce(class Design*, class NetUReduce*)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void NetScope::run_functor(Design*des, functor_t*fun)
|
||||
{
|
||||
for (NetScope*cur = sub_ ; cur ; cur = cur->sib_) {
|
||||
@@ -198,11 +189,6 @@ void NetFF::functor_node(Design*des, functor_t*fun)
|
||||
fun->lpm_ff(des, this);
|
||||
}
|
||||
|
||||
void NetLiteral::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_literal(des, this);
|
||||
}
|
||||
|
||||
void NetLogic::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_logic(des, this);
|
||||
@@ -223,14 +209,9 @@ void NetMux::functor_node(Design*des, functor_t*fun)
|
||||
fun->lpm_mux(des, this);
|
||||
}
|
||||
|
||||
void NetSignExtend::functor_node(Design*des, functor_t*fun)
|
||||
void NetRamDq::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->sign_extend(des, this);
|
||||
}
|
||||
|
||||
void NetUReduce::functor_node(Design*des, functor_t*fun)
|
||||
{
|
||||
fun->lpm_ureduce(des, this);
|
||||
fun->lpm_ram_dq(des, this);
|
||||
}
|
||||
|
||||
proc_match_t::~proc_match_t()
|
||||
@@ -294,14 +275,8 @@ int proc_match_t::event_wait(NetEvWait*)
|
||||
|
||||
/*
|
||||
* $Log: functor.cc,v $
|
||||
* Revision 1.35 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.34 2005/05/24 01:44:27 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.33 2005/02/03 04:56:20 steve
|
||||
* laborate reduction gates into LPM_RED_ nodes.
|
||||
* Revision 1.32.2.1 2006/04/23 04:26:14 steve
|
||||
* Constant propagate addresses through NetRamDq read ports.
|
||||
*
|
||||
* Revision 1.32 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __functor_H
|
||||
#define __functor_H
|
||||
/*
|
||||
* Copyright (c) 1999-2005 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1999-2000 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: functor.h,v 1.23 2005/07/07 16:22:49 steve Exp $"
|
||||
#ident "$Id: functor.h,v 1.20.2.1 2006/04/23 04:26:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -63,9 +63,6 @@ struct functor_t {
|
||||
/* This method is called for each structural constant. */
|
||||
virtual void lpm_divide(class Design*des, class NetDivide*);
|
||||
|
||||
/* Constant literals. */
|
||||
virtual void lpm_literal(class Design*des, class NetLiteral*);
|
||||
|
||||
/* This method is called for each structural constant. */
|
||||
virtual void lpm_modulo(class Design*des, class NetModulo*);
|
||||
|
||||
@@ -81,10 +78,8 @@ struct functor_t {
|
||||
/* This method is called for each MUX. */
|
||||
virtual void lpm_mux(class Design*des, class NetMux*);
|
||||
|
||||
/* This method is called for each unary reduction gate. */
|
||||
virtual void lpm_ureduce(class Design*des, class NetUReduce*);
|
||||
|
||||
virtual void sign_extend(class Design*des, class NetSignExtend*);
|
||||
/* This is called for eacm RamDq device. */
|
||||
virtual void lpm_ram_dq(class Design*des, class NetRamDq*);
|
||||
};
|
||||
|
||||
struct proc_match_t {
|
||||
@@ -100,14 +95,8 @@ struct proc_match_t {
|
||||
|
||||
/*
|
||||
* $Log: functor.h,v $
|
||||
* Revision 1.23 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.22 2005/05/24 01:44:27 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.21 2005/02/03 04:56:20 steve
|
||||
* laborate reduction gates into LPM_RED_ nodes.
|
||||
* Revision 1.20.2.1 2006/04/23 04:26:14 steve
|
||||
* Constant propagate addresses through NetRamDq read ports.
|
||||
*
|
||||
* Revision 1.20 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
|
||||
+2
-11
@@ -1,7 +1,4 @@
|
||||
|
||||
NOTE: THE CONTENTS OF THIS FILE ARE BEING MOVED TO THE DOCUMENTATION
|
||||
WIKI AT http://iverilog.wikia.com. PLEASE ADD NEW ENTRIES THERE.
|
||||
|
||||
Icarus Verilog vs. IEEE1364
|
||||
Copyright 2000 Stephen Williams
|
||||
|
||||
@@ -252,7 +249,7 @@ exactly the same so far as the compiler is concerned.
|
||||
|
||||
Unfortunately, Cadence seems to feel otherwise. In particular, it has
|
||||
been reported that although {1'b0, 16} causes an error, {1'b0, 15+1}
|
||||
is accepted. Further testing shows that any expression other than a
|
||||
is accepted. Further testing shows that any expression other then a
|
||||
simple unsized constant is accepted there, even if all the operands of
|
||||
all the operators that make up the expression are unsized integers.
|
||||
|
||||
@@ -501,14 +498,8 @@ of 4-value behavior in the dead zone, and appears more user friendly
|
||||
when viewed by reasonable viewers.
|
||||
|
||||
|
||||
$Id: ieee1364-notes.txt,v 1.19 2007/04/18 02:36:13 steve Exp $
|
||||
$Id: ieee1364-notes.txt,v 1.17 2003/07/15 03:49:22 steve Exp $
|
||||
$Log: ieee1364-notes.txt,v $
|
||||
Revision 1.19 2007/04/18 02:36:13 steve
|
||||
Put to iverilog wiki for further notes.
|
||||
|
||||
Revision 1.18 2007/03/22 16:08:16 steve
|
||||
Spelling fixes from Larry
|
||||
|
||||
Revision 1.17 2003/07/15 03:49:22 steve
|
||||
Spelling fixes.
|
||||
|
||||
|
||||
+4
-12
@@ -17,12 +17,12 @@
|
||||
# 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 $"
|
||||
#ident "$Id: iverilog-vpi.sh,v 1.14 2004/05/20 00:40:34 steve Exp $"
|
||||
|
||||
# These are the variables used for compiling files
|
||||
CC=@IVCC@
|
||||
CXX=@IVCXX@
|
||||
CFLAGS="@PIC@ @IVCFLAGS@ -I@INCLUDEDIR@"
|
||||
CC=gcc
|
||||
CXX=gcc
|
||||
CFLAGS="@PIC@ -O -I@INCLUDEDIR@"
|
||||
|
||||
# These are used for linking...
|
||||
LD=gcc
|
||||
@@ -63,19 +63,11 @@ do
|
||||
;;
|
||||
|
||||
*.cc) CXSRC="$CXSRC $parm"
|
||||
LD=$CXX
|
||||
if [ x$OUT = x ]; then
|
||||
OUT=`basename $parm .cc`
|
||||
fi
|
||||
;;
|
||||
|
||||
*.cpp) CXSRC="$CXSRC $parm"
|
||||
LD=$CXX
|
||||
if [ x$OUT = x ]; then
|
||||
OUT=`basename $parm .cpp`
|
||||
fi
|
||||
;;
|
||||
|
||||
*.o) OBJ="$OBJ $parm"
|
||||
if [ x$OUT = x ]; then
|
||||
OUT=`basename $parm .o`
|
||||
|
||||
@@ -9,10 +9,9 @@ ivl_design_roots
|
||||
ivl_design_time_precision
|
||||
|
||||
ivl_const_bits
|
||||
ivl_const_real
|
||||
ivl_const_pin
|
||||
ivl_const_pins
|
||||
ivl_const_signed
|
||||
ivl_const_type
|
||||
ivl_const_width
|
||||
|
||||
ivl_event_any
|
||||
ivl_event_basename
|
||||
@@ -22,13 +21,14 @@ ivl_event_neg
|
||||
ivl_event_nneg
|
||||
ivl_event_npos
|
||||
ivl_event_pos
|
||||
ivl_event_scope
|
||||
|
||||
ivl_expr_type
|
||||
ivl_expr_bits
|
||||
ivl_expr_def
|
||||
ivl_expr_dvalue
|
||||
ivl_expr_event
|
||||
ivl_expr_lsi
|
||||
ivl_expr_memory
|
||||
ivl_expr_name
|
||||
ivl_expr_opcode
|
||||
ivl_expr_oper1
|
||||
@@ -44,34 +44,36 @@ ivl_expr_signed
|
||||
ivl_expr_string
|
||||
ivl_expr_uvalue
|
||||
ivl_expr_value
|
||||
ivl_expr_variable
|
||||
ivl_expr_width
|
||||
|
||||
ivl_logic_attr
|
||||
ivl_logic_attr_cnt
|
||||
ivl_logic_attr_val
|
||||
ivl_logic_basename
|
||||
ivl_logic_delay
|
||||
ivl_logic_drive0
|
||||
ivl_logic_drive1
|
||||
ivl_logic_name
|
||||
ivl_logic_pin
|
||||
ivl_logic_pins
|
||||
ivl_logic_basename
|
||||
ivl_logic_scope
|
||||
ivl_logic_type
|
||||
ivl_logic_pin
|
||||
ivl_logic_pins
|
||||
ivl_logic_udp
|
||||
ivl_logic_width
|
||||
|
||||
ivl_lpm_array
|
||||
ivl_lpm_aset_value
|
||||
ivl_lpm_async_clr
|
||||
ivl_lpm_async_set
|
||||
ivl_lpm_base
|
||||
ivl_lpm_attr_cnt
|
||||
ivl_lpm_attr_val
|
||||
ivl_lpm_basename
|
||||
ivl_lpm_clk
|
||||
ivl_lpm_data
|
||||
ivl_lpm_datab
|
||||
ivl_lpm_data2
|
||||
ivl_lpm_data2_width
|
||||
ivl_lpm_decode
|
||||
ivl_lpm_define
|
||||
ivl_lpm_enable
|
||||
ivl_lpm_memory
|
||||
ivl_lpm_name
|
||||
ivl_lpm_q
|
||||
ivl_lpm_scope
|
||||
@@ -80,17 +82,25 @@ ivl_lpm_selects
|
||||
ivl_lpm_signed
|
||||
ivl_lpm_size
|
||||
ivl_lpm_sset_value
|
||||
ivl_lpm_string
|
||||
ivl_lpm_sync_clr
|
||||
ivl_lpm_sync_set
|
||||
ivl_lpm_type
|
||||
ivl_lpm_width
|
||||
|
||||
ivl_lval_idx
|
||||
ivl_lval_mem
|
||||
ivl_lval_mux
|
||||
ivl_lval_part_off
|
||||
ivl_lval_pin
|
||||
ivl_lval_pins
|
||||
ivl_lval_sig
|
||||
ivl_lval_width
|
||||
ivl_lval_var
|
||||
|
||||
ivl_memory_basename
|
||||
ivl_memory_root
|
||||
ivl_memory_scope
|
||||
ivl_memory_size
|
||||
ivl_memory_width
|
||||
|
||||
ivl_nexus_get_private
|
||||
ivl_nexus_name
|
||||
@@ -109,12 +119,6 @@ ivl_nexus_ptr_sig
|
||||
ivl_parameter_basename
|
||||
ivl_parameter_expr
|
||||
|
||||
ivl_path_condit
|
||||
ivl_path_delay
|
||||
ivl_path_source
|
||||
ivl_path_source_negedge
|
||||
ivl_path_source_posedge
|
||||
|
||||
ivl_scope_attr_cnt
|
||||
ivl_scope_attr_val
|
||||
ivl_scope_basename
|
||||
@@ -126,6 +130,8 @@ ivl_scope_logs
|
||||
ivl_scope_log
|
||||
ivl_scope_lpms
|
||||
ivl_scope_lpm
|
||||
ivl_scope_mem
|
||||
ivl_scope_mems
|
||||
ivl_scope_name
|
||||
ivl_scope_param
|
||||
ivl_scope_params
|
||||
@@ -137,30 +143,23 @@ ivl_scope_sig
|
||||
ivl_scope_time_units
|
||||
ivl_scope_type
|
||||
ivl_scope_tname
|
||||
ivl_scope_var
|
||||
ivl_scope_vars
|
||||
|
||||
ivl_signal_array_base
|
||||
ivl_signal_array_count
|
||||
ivl_signal_attr
|
||||
ivl_signal_attr_cnt
|
||||
ivl_signal_attr_val
|
||||
ivl_signal_basename
|
||||
ivl_signal_data_type
|
||||
ivl_signal_dimensions
|
||||
ivl_signal_integer
|
||||
ivl_signal_local
|
||||
ivl_signal_lsb
|
||||
ivl_signal_msb
|
||||
ivl_signal_name
|
||||
ivl_signal_nex
|
||||
ivl_signal_npath
|
||||
ivl_signal_path
|
||||
ivl_signal_pin
|
||||
ivl_signal_pins
|
||||
ivl_signal_port
|
||||
ivl_signal_signed
|
||||
ivl_signal_type
|
||||
ivl_signal_width
|
||||
|
||||
ivl_path_delay
|
||||
ivl_path_source
|
||||
ivl_signal_name
|
||||
ivl_signal_basename
|
||||
|
||||
ivl_process_attr_cnt
|
||||
ivl_process_attr_val
|
||||
@@ -188,6 +187,8 @@ ivl_stmt_lvals
|
||||
ivl_stmt_lwidth
|
||||
ivl_stmt_name
|
||||
ivl_stmt_nevent
|
||||
ivl_stmt_nexus
|
||||
ivl_stmt_nexus_count
|
||||
ivl_stmt_parm
|
||||
ivl_stmt_parm_count
|
||||
ivl_stmt_rval
|
||||
@@ -199,3 +200,6 @@ ivl_udp_nin
|
||||
ivl_udp_row
|
||||
ivl_udp_rows
|
||||
ivl_udp_sequ
|
||||
|
||||
ivl_variable_name
|
||||
ivl_variable_type
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 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
|
||||
* General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: ivl_assert.h,v 1.1 2007/01/31 04:21:10 steve Exp $"
|
||||
#endif
|
||||
|
||||
#ifndef __ivl_assert_h
|
||||
#define __ivl_assert_h
|
||||
|
||||
# include <assert.h>
|
||||
|
||||
#define ivl_assert(tok, expression) \
|
||||
do { \
|
||||
if (! (expression)) \
|
||||
__ivl_assert(#expression, tok, __FILE__, __LINE__); \
|
||||
} while(0)
|
||||
|
||||
#define __ivl_assert(expression, tok, file, line) \
|
||||
do { \
|
||||
cerr << (tok).get_line() << ": assert: " \
|
||||
<< file << ":" << line \
|
||||
<< ": failed assertion " << (expression) << endl; \
|
||||
abort(); \
|
||||
} while(0)
|
||||
|
||||
|
||||
#endif
|
||||
+272
-734
File diff suppressed because it is too large
Load Diff
+9
-9
@@ -18,7 +18,7 @@
|
||||
# 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 $"
|
||||
#ident "$Id: Makefile.in,v 1.17 2004/10/04 01:10:56 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -44,18 +44,18 @@ CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir)/.. -I$(srcdir) @CPPFLAGS@ @DEFS@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
|
||||
all: ivlpp@EXEEXT@
|
||||
all: ivlpp
|
||||
|
||||
clean:
|
||||
rm -f *.o lexor.c parse.c parse.h parse.output ivlpp@EXEEXT@
|
||||
rm -f *.o lexor.c parse.c parse.h parse.output ivlpp
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile
|
||||
|
||||
O = main.o lexor.o parse.o
|
||||
|
||||
ivlpp@EXEEXT@: $O
|
||||
$(CC) $(LDFLAGS) $O -o ivlpp@EXEEXT@ @EXTRALIBS@
|
||||
ivlpp: $O
|
||||
$(CC) $(LDFLAGS) $O -o ivlpp @EXTRALIBS@
|
||||
|
||||
lexor.c: lexor.lex
|
||||
flex -s -olexor.c $(srcdir)/lexor.lex
|
||||
@@ -63,16 +63,16 @@ lexor.c: lexor.lex
|
||||
parse.h parse.c: parse.y
|
||||
bison --verbose -t -d -o parse.c $(srcdir)/parse.y
|
||||
|
||||
install: all installdirs $(libdir)/ivl/ivlpp@EXEEXT@
|
||||
install: all installdirs $(libdir)/ivl/ivlpp
|
||||
|
||||
$(libdir)/ivl/ivlpp@EXEEXT@: ivlpp@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivlpp@EXEEXT@ $(libdir)/ivl/ivlpp@EXEEXT@
|
||||
$(libdir)/ivl/ivlpp: ivlpp
|
||||
$(INSTALL_PROGRAM) ./ivlpp $(libdir)/ivl/ivlpp
|
||||
|
||||
installdirs: ../mkinstalldirs
|
||||
$(srcdir)/../mkinstalldirs $(libdir)/ivl
|
||||
|
||||
uninstall:
|
||||
rm -f $(libdir)/ivl/ivlpp@EXEEXT@
|
||||
rm -f $(libdir)/ivl/ivlpp
|
||||
|
||||
lexor.o: lexor.c parse.h globals.h
|
||||
main.o: main.c globals.h
|
||||
|
||||
+6
-71
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: lexor.lex,v 1.48 2007/05/30 23:21:20 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.46.2.1 2007/05/25 18:35:45 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -70,14 +70,7 @@ struct include_stack_t {
|
||||
|
||||
static void emit_pathline(struct include_stack_t *isp);
|
||||
|
||||
/*
|
||||
* The file_queue is a singly-linked list of the files that were
|
||||
* listed on the command line/file list.
|
||||
*/
|
||||
static struct include_stack_t*file_queue = 0;
|
||||
/*
|
||||
* The istack is the inclusion stack.
|
||||
*/
|
||||
static struct include_stack_t*istack = 0;
|
||||
static struct include_stack_t*standby = 0;
|
||||
|
||||
@@ -118,11 +111,11 @@ static void ifdef_leave(void)
|
||||
if (strcmp(istack->path,cur->path) != 0) {
|
||||
fprintf(stderr, "%s:%u: warning: "
|
||||
"This `endif matches an ifdef in another file.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
istack->path, istack->lineno);
|
||||
|
||||
fprintf(stderr, "%s:%u: : "
|
||||
"This is the odd matched `ifdef.\n",
|
||||
cur->path, cur->lineno+1);
|
||||
cur->path, cur->lineno);
|
||||
}
|
||||
|
||||
free(cur->path);
|
||||
@@ -316,24 +309,7 @@ W [ \t\b\f]+
|
||||
yy_push_state(IFDEF_SUPR);
|
||||
}
|
||||
|
||||
<IFDEF_TRUE>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
BEGIN(IFDEF_SUPR);
|
||||
}
|
||||
<IFDEF_FALSE>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
char*name = strchr(yytext, '`');
|
||||
assert(name);
|
||||
name += 6;
|
||||
name += strspn(name, " \t\b\f");
|
||||
|
||||
if (is_defined(name)) {
|
||||
BEGIN(IFDEF_TRUE);
|
||||
} else {
|
||||
BEGIN(IFDEF_FALSE);
|
||||
}
|
||||
}
|
||||
<IFDEF_SUPR>`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* { }
|
||||
|
||||
<IFDEF_TRUE>`else { BEGIN(IFDEF_SUPR); }
|
||||
<IFDEF_TRUE>`else { BEGIN(IFDEF_FALSE); }
|
||||
<IFDEF_FALSE>`else { BEGIN(IFDEF_TRUE); }
|
||||
<IFDEF_SUPR>`else { }
|
||||
|
||||
@@ -346,42 +322,6 @@ W [ \t\b\f]+
|
||||
|
||||
<IFDEF_FALSE,IFDEF_TRUE,IFDEF_SUPR>`endif { ifdef_leave(); yy_pop_state(); }
|
||||
|
||||
`ifdef {
|
||||
fprintf(stderr, "%s:%u: `ifdef without a macro name - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
`ifndef {
|
||||
fprintf(stderr, "%s:%u: `ifndef without a macro name - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
`elsif {
|
||||
fprintf(stderr, "%s:%u: `elsif without a macro name - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
`elsif{W}[a-zA-Z_][a-zA-Z0-9_$]* {
|
||||
fprintf(stderr, "%s:%u: `elsif without a matching `ifdef - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
`else {
|
||||
fprintf(stderr, "%s:%u: `else without a matching `ifdef - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
`endif {
|
||||
fprintf(stderr, "%s:%u: `endif without a matching `ifdef - ignored.\n",
|
||||
istack->path, istack->lineno+1);
|
||||
error_count += 1;
|
||||
}
|
||||
|
||||
/* This pattern notices macros and arranges for them to be replaced. */
|
||||
`[a-zA-Z][a-zA-Z0-9_$]* { def_match(); }
|
||||
|
||||
@@ -819,7 +759,7 @@ static void lexor_done()
|
||||
ifdef_stack = cur->next;
|
||||
|
||||
fprintf(stderr, "%s:%u: error: This `ifdef lacks an `endif.\n",
|
||||
cur->path, cur->lineno+1);
|
||||
cur->path, cur->lineno);
|
||||
|
||||
free(cur->path);
|
||||
free(cur);
|
||||
@@ -837,14 +777,11 @@ static int yywrap()
|
||||
int line_mask_flag = 0;
|
||||
struct include_stack_t*isp = istack;
|
||||
istack = isp->next;
|
||||
FILE *delayed_close = (FILE *) 0;
|
||||
|
||||
/* Delete the current input buffers, and free the cell. */
|
||||
yy_delete_buffer(YY_CURRENT_BUFFER);
|
||||
if (isp->file) {
|
||||
/* Delay the close of this file, because the yyrestart
|
||||
below seems to have some memory of this file. */
|
||||
delayed_close = isp->file;
|
||||
fclose(isp->file);
|
||||
free(isp->path);
|
||||
} else {
|
||||
/* If I am printing line directives and I just finished
|
||||
@@ -888,7 +825,6 @@ static int yywrap()
|
||||
}
|
||||
|
||||
yyrestart(istack->file);
|
||||
if (delayed_close) fclose(delayed_close);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -897,7 +833,6 @@ static int yywrap()
|
||||
top. If I need to print a line directive, do so. */
|
||||
|
||||
yy_switch_to_buffer(istack->yybs);
|
||||
if (delayed_close) fclose(delayed_close);
|
||||
|
||||
if (line_direct_flag && istack->path && !line_mask_flag)
|
||||
fprintf(yyout, "\n`line %u \"%s\" 2\n",
|
||||
|
||||
+37
-88
@@ -17,7 +17,7 @@ const char COPYRIGHT[] =
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: main.c,v 1.23 2006/10/02 18:16:18 steve Exp $"
|
||||
#ident "$Id: main.c,v 1.20.2.1 2006/06/27 01:37:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -58,8 +58,6 @@ extern int getopt(int argc, char*argv[], const char*fmt);
|
||||
extern int optind;
|
||||
extern const char*optarg;
|
||||
#endif
|
||||
/* Path to the dependency file, if there is one. */
|
||||
char *dep_path = NULL;
|
||||
|
||||
/*
|
||||
* Keep in source_list an array of pointers to file names. The array
|
||||
@@ -91,76 +89,6 @@ int line_direct_flag = 0;
|
||||
unsigned error_count = 0;
|
||||
FILE *depend_file = NULL;
|
||||
|
||||
static int flist_read_flags(const char*path)
|
||||
{
|
||||
char line_buf[2048];
|
||||
FILE*fd = fopen(path, "r");
|
||||
if (fd == 0) {
|
||||
fprintf(stderr, "%s: unable to open for reading.\n", path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (fgets(line_buf, sizeof line_buf, fd) != 0) {
|
||||
/* Skip leading white space. */
|
||||
char*cp = line_buf + strspn(line_buf, " \t\r\b\f");
|
||||
/* Remove trailing white space. */
|
||||
char*tail = cp + strlen(cp);
|
||||
while (tail > cp) {
|
||||
if (! isspace(tail[-1]))
|
||||
break;
|
||||
tail -= 1;
|
||||
tail[0] = 0;
|
||||
}
|
||||
|
||||
/* Skip empty lines */
|
||||
if (*cp == 0)
|
||||
continue;
|
||||
/* Skip comment lines */
|
||||
if (cp[0] == '#')
|
||||
continue;
|
||||
|
||||
/* The arg points to the argument to the keyword. */
|
||||
char*arg = strchr(cp, ':');
|
||||
if (arg) *arg++ = 0;
|
||||
|
||||
if (strcmp(cp,"D") == 0) {
|
||||
char*val = strchr(arg, '=');
|
||||
if (val)
|
||||
*val++ = 0;
|
||||
else
|
||||
val = "1";
|
||||
|
||||
define_macro(arg, val, 0);
|
||||
|
||||
} else if (strcmp(cp,"I") == 0) {
|
||||
include_dir = realloc(include_dir,
|
||||
(include_cnt+1)*sizeof(char*));
|
||||
include_dir[include_cnt] = strdup(arg);
|
||||
include_cnt += 1;
|
||||
|
||||
} else if (strcmp(cp,"keyword") == 0) {
|
||||
char*buf = malloc(strlen(arg) + 2);
|
||||
buf[0] = '`';
|
||||
strcpy(buf+1, optarg);
|
||||
define_macro(optarg, buf, 1);
|
||||
free(buf);
|
||||
|
||||
} else if (strcmp(cp,"M") == 0) {
|
||||
if (dep_path) {
|
||||
fprintf(stderr, "duplicate -M flag.\n");
|
||||
} else {
|
||||
dep_path = strdup(arg);
|
||||
}
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "%s: Invalid keyword %s\n", path, cp);
|
||||
}
|
||||
}
|
||||
|
||||
fclose(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function reads from a file a list of file names. Each name
|
||||
* starts with the first non-space character, and ends with the last
|
||||
@@ -198,7 +126,8 @@ int main(int argc, char*argv[])
|
||||
int opt, idx;
|
||||
const char*flist_path = 0;
|
||||
unsigned flag_errors = 0;
|
||||
char*out_path = 0;
|
||||
const char*out_path = 0;
|
||||
const char*dep_path = NULL;
|
||||
FILE*out;
|
||||
|
||||
/* Define preprocessor keywords that I plan to just pass. */
|
||||
@@ -224,11 +153,20 @@ int main(int argc, char*argv[])
|
||||
include_dir[0] = strdup(".");
|
||||
include_cnt = 1;
|
||||
|
||||
while ((opt=getopt(argc, argv, "F:f:K:Lo:v")) != EOF) switch (opt) {
|
||||
while ((opt = getopt(argc, argv, "D:f:I:K:LM:o:v")) != EOF) switch (opt) {
|
||||
|
||||
case 'F':
|
||||
flist_read_flags(optarg);
|
||||
break;
|
||||
case 'D': {
|
||||
char*tmp = strdup(optarg);
|
||||
char*val = strchr(tmp, '=');
|
||||
if (val)
|
||||
*val++ = 0;
|
||||
else
|
||||
val = "1";
|
||||
|
||||
define_macro(tmp, val, 0);
|
||||
free(tmp);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'f':
|
||||
if (flist_path) {
|
||||
@@ -238,6 +176,13 @@ int main(int argc, char*argv[])
|
||||
flist_path = optarg;
|
||||
break;
|
||||
|
||||
case 'I':
|
||||
include_dir = realloc(include_dir,
|
||||
(include_cnt+1)*sizeof(char*));
|
||||
include_dir[include_cnt] = strdup(optarg);
|
||||
include_cnt += 1;
|
||||
break;
|
||||
|
||||
case 'K': {
|
||||
char*buf = malloc(strlen(optarg) + 2);
|
||||
buf[0] = '`';
|
||||
@@ -251,6 +196,14 @@ int main(int argc, char*argv[])
|
||||
line_direct_flag = 1;
|
||||
break;
|
||||
|
||||
case 'M':
|
||||
if (dep_path) {
|
||||
fprintf(stderr, "duplicate -M flag.\n");
|
||||
} else {
|
||||
dep_path = optarg;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'o':
|
||||
if (out_path) {
|
||||
fprintf(stderr, "duplicate -o flag.\n");
|
||||
@@ -272,11 +225,13 @@ int main(int argc, char*argv[])
|
||||
}
|
||||
|
||||
if (flag_errors) {
|
||||
fprintf(stderr, "\nUsage: %s [-v][-L][-F<fil>][-f<fil>] <file>...\n"
|
||||
" -F<fil> - Get defines and includes from file\n"
|
||||
fprintf(stderr, "\nUsage: %s [-v][-L][-I<dir>][-D<def>] <file>...\n"
|
||||
" -D<def> - Predefine a value.\n"
|
||||
" -f<fil> - Read the sources listed in the file\n"
|
||||
" -I<dir> - Add an include file search directory\n"
|
||||
" -K<def> - Define a keyword macro that I just pass\n"
|
||||
" -L - Emit line number directives\n"
|
||||
" -M<fil> - Write dependencies to <fil>\n"
|
||||
" -o<fil> - Send the output to <fil>\n"
|
||||
" -v - Print version information\n",
|
||||
argv[0]);
|
||||
@@ -335,14 +290,8 @@ int main(int argc, char*argv[])
|
||||
|
||||
/*
|
||||
* $Log: main.c,v $
|
||||
* Revision 1.23 2006/10/02 18:16:18 steve
|
||||
* Save dep_path because arg space is overrun.
|
||||
*
|
||||
* Revision 1.22 2006/07/26 00:11:40 steve
|
||||
* Pass depfiles through temp defines file.
|
||||
*
|
||||
* Revision 1.21 2006/07/26 00:02:48 steve
|
||||
* Pass defines and includes through temp file.
|
||||
* Revision 1.20.2.1 2006/06/27 01:37:14 steve
|
||||
* Fix const/non-const warnings.
|
||||
*
|
||||
* Revision 1.20 2004/09/10 00:15:45 steve
|
||||
* Remove bad casts.
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: lexor.lex,v 1.96 2007/06/14 03:50:00 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.86.2.4 2007/02/09 05:29:24 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -53,7 +53,6 @@ extern YYLTYPE yylloc;
|
||||
struct file_name_cell {
|
||||
const char*text;
|
||||
struct file_name_cell*next;
|
||||
bool library_flag;
|
||||
};
|
||||
|
||||
static struct file_name_cell*file_names = 0;
|
||||
@@ -73,13 +72,6 @@ static const char* set_file_name(char*text)
|
||||
cur = new struct file_name_cell;
|
||||
cur->text = text;
|
||||
cur->next = file_names;
|
||||
|
||||
/* Check this file name with the list of library file
|
||||
names. If there is a match, then turn on the
|
||||
pform_library_flag. This is how the parser knows that
|
||||
modules declared in this file are library modules. */
|
||||
cur->library_flag = library_file_map[cur->text];
|
||||
pform_library_flag = cur->library_flag;
|
||||
return text;
|
||||
}
|
||||
|
||||
@@ -109,7 +101,6 @@ static int comment_enter;
|
||||
%s UDPTABLE
|
||||
%x PPTIMESCALE
|
||||
%x PPDEFAULT_NETTYPE
|
||||
%s EDGES
|
||||
|
||||
W [ \t\b\f\r]+
|
||||
|
||||
@@ -143,7 +134,6 @@ W [ \t\b\f\r]+
|
||||
"<<<" { return K_LS; /* Note: Functionally, <<< is the same as <<. */}
|
||||
">>" { return K_RS; }
|
||||
">>>" { return K_RSS; }
|
||||
"**" { return K_POW; }
|
||||
"<=" { return K_LE; }
|
||||
">=" { return K_GE; }
|
||||
"=>" { return K_EG; }
|
||||
@@ -166,9 +156,9 @@ W [ \t\b\f\r]+
|
||||
/* Watch out for the tricky case of (*). Cannot parse this as "(*"
|
||||
and ")", but since I know that this is really ( * ), replace it
|
||||
with "*" and return that. */
|
||||
"("{W}*"*"{W}*")" { return '*'; }
|
||||
"(*"{W}*")" { return '*'; }
|
||||
|
||||
|
||||
<EDGES>"]" { BEGIN(0); return yytext[0]; }
|
||||
[}{;:\[\],()#=.@&!?<>%|^~+*/-] { return yytext[0]; }
|
||||
|
||||
\" { BEGIN(CSTRING); }
|
||||
@@ -211,44 +201,14 @@ W [ \t\b\f\r]+
|
||||
<UDPTABLE>[pP] { return 'p'; }
|
||||
<UDPTABLE>[01\?\*\-] { return yytext[0]; }
|
||||
|
||||
<EDGES>"01" { return K_edge_descriptor; }
|
||||
<EDGES>"0x" { return K_edge_descriptor; }
|
||||
<EDGES>"0z" { return K_edge_descriptor; }
|
||||
<EDGES>"10" { return K_edge_descriptor; }
|
||||
<EDGES>"1x" { return K_edge_descriptor; }
|
||||
<EDGES>"1z" { return K_edge_descriptor; }
|
||||
<EDGES>"x0" { return K_edge_descriptor; }
|
||||
<EDGES>"x1" { return K_edge_descriptor; }
|
||||
<EDGES>"z0" { return K_edge_descriptor; }
|
||||
<EDGES>"z1" { return K_edge_descriptor; }
|
||||
|
||||
[a-zA-Z_][a-zA-Z0-9$_]* {
|
||||
int rc = lexor_keyword_code(yytext, yyleng);
|
||||
switch (rc) {
|
||||
case IDENTIFIER:
|
||||
if (rc == IDENTIFIER) {
|
||||
yylval.text = strdup(yytext);
|
||||
if (strncmp(yylval.text,"PATHPULSE$", 10) == 0)
|
||||
rc = PATHPULSE_IDENTIFIER;
|
||||
break;
|
||||
|
||||
case K_bool:
|
||||
case K_logic:
|
||||
case K_wone:
|
||||
if (! gn_cadence_types_enabled()) {
|
||||
yylval.text = strdup(yytext);
|
||||
rc = IDENTIFIER;
|
||||
} else {
|
||||
yylval.text = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case K_edge:
|
||||
BEGIN(EDGES);
|
||||
break;
|
||||
|
||||
default:
|
||||
} else {
|
||||
yylval.text = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -321,10 +281,10 @@ W [ \t\b\f\r]+
|
||||
^{W}?`disable_portfaults{W}?.* { }
|
||||
^{W}?`enable_portfaults{W}?.* { }
|
||||
^{W}?`endcelldefine{W}?.* { }
|
||||
`endprotect { }
|
||||
^{W}?`endprotect{W}?.* { }
|
||||
^{W}?`nosuppress_faults{W}?.* { }
|
||||
^{W}?`nounconnected_drive{W}?.* { }
|
||||
`protect { }
|
||||
^{W}?`protect{W}?.* { }
|
||||
^{W}?`resetall{W}?.* { }
|
||||
^{W}?`suppress_faults{W}?.* { }
|
||||
^{W}?`unconnected_drive{W}?.* { }
|
||||
@@ -485,7 +445,7 @@ static verinum*make_unsized_binary(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
verinum*out = new verinum(bits, size, false);
|
||||
verinum*out = new verinum(bits, size);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
@@ -545,7 +505,7 @@ static verinum*make_unsized_octal(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
verinum*out = new verinum(bits, size, false);
|
||||
verinum*out = new verinum(bits, size);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
@@ -615,7 +575,7 @@ static verinum*make_unsized_hex(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
verinum*out = new verinum(bits, size, false);
|
||||
verinum*out = new verinum(bits, size);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
|
||||
@@ -14,7 +14,6 @@ always, K_always
|
||||
and, K_and
|
||||
assign, K_assign
|
||||
begin, K_begin
|
||||
bool, K_bool
|
||||
buf, K_buf
|
||||
bufif0, K_bufif0
|
||||
bufif1, K_bufif1
|
||||
@@ -31,7 +30,6 @@ else, K_else
|
||||
end, K_end
|
||||
endcase, K_endcase
|
||||
endfunction, K_endfunction
|
||||
endgenerate, K_endgenerate
|
||||
endmodule, K_endmodule
|
||||
endprimitive, K_endprimitive
|
||||
endspecify, K_endspecify
|
||||
@@ -43,12 +41,9 @@ force, K_force
|
||||
forever, K_forever
|
||||
fork, K_fork
|
||||
function, K_function
|
||||
generate, K_generate
|
||||
genvar, K_genvar
|
||||
highz0, K_highz0
|
||||
highz1, K_highz1
|
||||
if, K_if
|
||||
ifnone, K_ifnone
|
||||
initial, K_initial
|
||||
inout, K_inout
|
||||
input, K_input
|
||||
@@ -56,7 +51,6 @@ integer, K_integer
|
||||
join, K_join
|
||||
large, K_large
|
||||
localparam, K_localparam
|
||||
logic, K_logic
|
||||
macromodule, K_macromodule
|
||||
medium, K_medium
|
||||
module, K_module
|
||||
@@ -116,7 +110,6 @@ weak0, K_weak0
|
||||
weak1, K_weak1
|
||||
while, K_while
|
||||
wire, K_wire
|
||||
wone, K_wone
|
||||
wor, K_wor
|
||||
xnor, K_xnor
|
||||
xor, K_xor
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 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 $"
|
||||
#ident "$Id: Makefile.in,v 1.34.2.1 2005/02/23 18:40:24 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -41,6 +41,7 @@ INSTALL_DATA = @INSTALL_DATA@
|
||||
CPPFLAGS = @ident_support@ -I. -I.. -I$(srcdir) -I$(srcdir)/.. @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
STRIP = @STRIP@
|
||||
RANLIB = @RANLIB@
|
||||
|
||||
A = a_close.o a_compare_handles.o a_configure.o a_fetch_argc.o \
|
||||
@@ -91,7 +92,8 @@ clean:
|
||||
rm -rf *.o dep libveriuser.a libveriuser.o bin32
|
||||
|
||||
distclean: clean
|
||||
rm -f Makefile config.status config.log config.cache config.h
|
||||
rm -f Makefile config.status config.log config.cache
|
||||
rm -rf autom4te.cache
|
||||
|
||||
install:: all installdirs $(libdir64)/libveriuser.a $(INSTALL32)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: a_next.c,v 1.4 2006/10/30 22:45:37 steve Exp $"
|
||||
#ident "$Id: a_next.c,v 1.3 2003/06/17 16:55:07 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
@@ -34,7 +34,7 @@ handle acc_next(PLI_INT32 *type, handle scope, handle prev)
|
||||
|
||||
/* trace */
|
||||
if (pli_trace) {
|
||||
PLI_INT32 *ip;
|
||||
int *ip;
|
||||
fprintf(pli_trace, "acc_next(%p <", type);
|
||||
for (ip = type; *ip; ip++) {
|
||||
fprintf(pli_trace, "%s%d", ip != type ? "," : "", *ip);
|
||||
@@ -94,9 +94,6 @@ handle acc_next_scope(handle scope, handle prev)
|
||||
|
||||
/*
|
||||
* $Log: a_next.c,v $
|
||||
* Revision 1.4 2006/10/30 22:45:37 steve
|
||||
* Updates for Cygwin portability (pr1585922)
|
||||
*
|
||||
* Revision 1.3 2003/06/17 16:55:07 steve
|
||||
* 1) setlinebuf() for vpi_trace
|
||||
* 2) Addes error checks for trace file opens
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: getinstance.c,v 1.5 2005/09/20 18:34:01 steve Exp $"
|
||||
#ident "$Id: getinstance.c,v 1.4 2003/05/18 00:16:35 steve Exp $"
|
||||
#endif
|
||||
|
||||
#include <veriuser.h>
|
||||
@@ -28,14 +28,11 @@
|
||||
*/
|
||||
PLI_BYTE8* tf_getinstance(void)
|
||||
{
|
||||
return (PLI_BYTE8 *)vpi_handle(vpiSysTfCall, 0 /* NULL */);
|
||||
return (char *)vpi_handle(vpiSysTfCall, 0 /* NULL */);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: getinstance.c,v $
|
||||
* Revision 1.5 2005/09/20 18:34:01 steve
|
||||
* Clean up compiler warnings.
|
||||
*
|
||||
* Revision 1.4 2003/05/18 00:16:35 steve
|
||||
* Add PLI_TRACE tracing of PLI1 modules.
|
||||
*
|
||||
|
||||
+10
-16
@@ -18,7 +18,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: veriusertfs.c,v 1.17 2007/05/08 22:01:26 steve Exp $"
|
||||
#ident "$Id: veriusertfs.c,v 1.15 2004/09/10 23:13:05 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -44,9 +44,9 @@ typedef struct t_pli_data {
|
||||
int paramvc; /* parameter number for misctf */
|
||||
} s_pli_data, *p_pli_data;
|
||||
|
||||
static PLI_INT32 compiletf(char *);
|
||||
static PLI_INT32 calltf(char *);
|
||||
static PLI_INT32 callback(p_cb_data);
|
||||
static int compiletf(char *);
|
||||
static int calltf(char *);
|
||||
static int callback(p_cb_data);
|
||||
|
||||
/*
|
||||
* Register veriusertfs routines/wrappers. Iterate over the tfcell
|
||||
@@ -58,7 +58,7 @@ void veriusertfs_register_table(p_tfcell vtable)
|
||||
p_tfcell tf;
|
||||
s_vpi_systf_data tf_data;
|
||||
p_pli_data data;
|
||||
static char trace_buf[1024];
|
||||
char trace_buf[1024];
|
||||
|
||||
if (!pli_trace && (path = getenv("PLI_TRACE"))) {
|
||||
if (strcmp(path,"-") == 0)
|
||||
@@ -69,8 +69,8 @@ void veriusertfs_register_table(p_tfcell vtable)
|
||||
perror(path);
|
||||
exit(1);
|
||||
}
|
||||
setvbuf(pli_trace, trace_buf, _IOLBF, sizeof(trace_buf));
|
||||
}
|
||||
setvbuf(pli_trace, trace_buf, _IOLBF, sizeof(trace_buf));
|
||||
}
|
||||
|
||||
for (tf = vtable; tf; tf++) {
|
||||
@@ -139,7 +139,7 @@ void veriusertfs_register_table(p_tfcell vtable)
|
||||
* This function calls the veriusertfs checktf and sets up all the
|
||||
* callbacks misctf requires.
|
||||
*/
|
||||
static PLI_INT32 compiletf(char *data)
|
||||
static int compiletf(char *data)
|
||||
{
|
||||
p_pli_data pli;
|
||||
p_tfcell tf;
|
||||
@@ -221,7 +221,7 @@ static PLI_INT32 compiletf(char *data)
|
||||
/*
|
||||
* This function is the wrapper for the veriusertfs calltf routine.
|
||||
*/
|
||||
static PLI_INT32 calltf(char *data)
|
||||
static int calltf(char *data)
|
||||
{
|
||||
int rc = 0;
|
||||
p_pli_data pli;
|
||||
@@ -249,13 +249,13 @@ static PLI_INT32 calltf(char *data)
|
||||
*/
|
||||
extern int async_misctf_enable;
|
||||
|
||||
static PLI_INT32 callback(p_cb_data data)
|
||||
static int callback(p_cb_data data)
|
||||
{
|
||||
p_pli_data pli;
|
||||
p_tfcell tf;
|
||||
int reason;
|
||||
int paramvc = 0;
|
||||
PLI_INT32 rc;
|
||||
int rc;
|
||||
|
||||
/* not enabled */
|
||||
if (data->reason == cbValueChange && !async_misctf_enable)
|
||||
@@ -389,12 +389,6 @@ PLI_INT32 tf_setrealdelay(double dly)
|
||||
}
|
||||
/*
|
||||
* $Log: veriusertfs.c,v $
|
||||
* Revision 1.17 2007/05/08 22:01:26 steve
|
||||
* Trace file line buffer must be static.
|
||||
*
|
||||
* Revision 1.16 2006/10/30 22:45:37 steve
|
||||
* Updates for Cygwin portability (pr1585922)
|
||||
*
|
||||
* Revision 1.15 2004/09/10 23:13:05 steve
|
||||
* Compile cleanup of C code.
|
||||
*
|
||||
|
||||
+1
-16
@@ -17,7 +17,7 @@
|
||||
* 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 $"
|
||||
#ident "$Id: link_const.cc,v 1.17 2004/10/04 01:10:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -132,8 +132,6 @@ verinum::V Nexus::driven_value() const
|
||||
|
||||
} else if ((sig = dynamic_cast<const NetNet*>(cur->get_obj()))) {
|
||||
|
||||
// If we find an attached SUPPLY0/1, the we know
|
||||
// from that what the driven value is. Stop now.
|
||||
if (sig->type() == NetNet::SUPPLY0) {
|
||||
driven_ = V0;
|
||||
return verinum::V0;
|
||||
@@ -142,16 +140,6 @@ verinum::V Nexus::driven_value() const
|
||||
driven_ = V1;
|
||||
return verinum::V1;
|
||||
}
|
||||
|
||||
// If we find an attached TRI0/1, then this is a
|
||||
// good guess for the driven value, but keep
|
||||
// looking for something better.
|
||||
if (sig->type() == NetNet::TRI0) {
|
||||
val = verinum::V0;
|
||||
}
|
||||
if (sig->type() == NetNet::TRI1) {
|
||||
val = verinum::V1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -176,9 +164,6 @@ verinum::V Nexus::driven_value() const
|
||||
|
||||
/*
|
||||
* $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.
|
||||
*
|
||||
|
||||
+2
-2
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: load_module.cc,v 1.13 2005/03/22 15:53:48 steve Exp $"
|
||||
#ident "$Id: load_module.cc,v 1.12.2.1 2005/03/22 15:53:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -193,7 +193,7 @@ int build_library_index(const char*path, bool key_case_sensitive)
|
||||
|
||||
/*
|
||||
* $Log: load_module.cc,v $
|
||||
* Revision 1.13 2005/03/22 15:53:48 steve
|
||||
* Revision 1.12.2.1 2005/03/22 15:53:12 steve
|
||||
* popen must be matched by pclose.
|
||||
*
|
||||
* Revision 1.12 2003/06/05 04:31:09 steve
|
||||
|
||||
@@ -1,4 +1,11 @@
|
||||
|
||||
Icarus Verilog for Mac OS X
|
||||
|
||||
NOTE: Icarus Verilog version 0.8 is known to compile "out of the
|
||||
box" on MacOSX 10.3. OSX 10.3 users need only the developer tools
|
||||
included with new systems or available for free download from
|
||||
Apple. Install Xcode and skip directly to step #3.
|
||||
|
||||
This file describes the procedure to build and install Icarus Verilog
|
||||
on Mac OS X. I assume that you have experience with Unix and
|
||||
Terminal.app and a basic knowledge of how to download, compile and
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
const char COPYRIGHT[] =
|
||||
"Copyright (c) 1998-2005 Stephen Williams ([email protected])";
|
||||
"Copyright (c) 1998-2004 Stephen Williams ([email protected])";
|
||||
|
||||
/*
|
||||
* This source code is free software; you can redistribute it
|
||||
@@ -19,7 +19,7 @@ const char COPYRIGHT[] =
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: main.cc,v 1.95 2007/04/19 02:52:53 steve Exp $"
|
||||
#ident "$Id: main.cc,v 1.86.2.3 2006/06/12 00:16:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -81,20 +81,12 @@ const char*basedir = ".";
|
||||
|
||||
const char*target = "null";
|
||||
|
||||
/*
|
||||
* These are the language support control flags. These support which
|
||||
* language features (the generation) to support. The generation_flag
|
||||
* is a major moce, and the gn_* flags control specifc sub-features.
|
||||
*/
|
||||
generation_t generation_flag = GN_DEFAULT;
|
||||
bool gn_cadence_types_flag = true;
|
||||
bool gn_specify_blocks_flag = true;
|
||||
|
||||
map<string,const char*> flags;
|
||||
char*vpi_module_list = 0;
|
||||
|
||||
map<perm_string,unsigned> missing_modules;
|
||||
map<string,bool> library_file_map;
|
||||
|
||||
list<const char*> library_suff;
|
||||
|
||||
@@ -111,6 +103,7 @@ FILE *depend_file = NULL;
|
||||
bool warn_implicit = false;
|
||||
bool warn_timescale = false;
|
||||
bool warn_portbinding = false;
|
||||
bool warn_unused = false;
|
||||
|
||||
bool error_implicit = false;
|
||||
|
||||
@@ -120,14 +113,14 @@ bool error_implicit = false;
|
||||
bool debug_scopes = false;
|
||||
bool debug_eval_tree = false;
|
||||
bool debug_elaborate = false;
|
||||
bool debug_synth2 = false;
|
||||
bool debug_synth = false;
|
||||
bool debug_cprop = false;
|
||||
|
||||
/*
|
||||
* Verbose messages enabled.
|
||||
*/
|
||||
bool verbose_flag = false;
|
||||
|
||||
unsigned integer_width = 32;
|
||||
|
||||
/*
|
||||
* Keep a heap of identifier strings that I encounter. This is a more
|
||||
* efficient way to allocate those strings.
|
||||
@@ -148,9 +141,7 @@ extern void synth(Design*des);
|
||||
extern void synth2(Design*des);
|
||||
extern void syn_rules(Design*des);
|
||||
extern void nodangle(Design*des);
|
||||
#ifdef WITH_T_XNF
|
||||
extern void xnfio(Design*des);
|
||||
#endif
|
||||
|
||||
typedef void (*net_func)(Design*);
|
||||
static struct net_func_map {
|
||||
@@ -162,9 +153,7 @@ static struct net_func_map {
|
||||
{ "synth", &synth },
|
||||
{ "synth2", &synth2 },
|
||||
{ "syn-rules", &syn_rules },
|
||||
#ifdef WITH_T_XNF
|
||||
{ "xnfio", &xnfio },
|
||||
#endif
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
@@ -190,29 +179,17 @@ const char *net_func_to_name(const net_func func)
|
||||
|
||||
static void process_generation_flag(const char*gen)
|
||||
{
|
||||
if (strcmp(gen,"1") == 0) {
|
||||
if (strcmp(gen,"1") == 0)
|
||||
generation_flag = GN_VER1995;
|
||||
|
||||
} else if (strcmp(gen,"2") == 0) {
|
||||
else if (strcmp(gen,"2") == 0)
|
||||
generation_flag = GN_VER2001;
|
||||
|
||||
} else if (strcmp(gen,"2x") == 0) {
|
||||
generation_flag = GN_VER2001X;
|
||||
else if (strcmp(gen,"3.0") == 0)
|
||||
generation_flag = GN_SYSVER30;
|
||||
|
||||
} else if (strcmp(gen,"xtypes") == 0) {
|
||||
gn_cadence_types_flag = true;
|
||||
|
||||
} else if (strcmp(gen,"no-xtypes") == 0) {
|
||||
gn_cadence_types_flag = false;
|
||||
|
||||
} else if (strcmp(gen,"specify") == 0) {
|
||||
gn_specify_blocks_flag = true;
|
||||
|
||||
} else if (strcmp(gen,"no-specify") == 0) {
|
||||
gn_specify_blocks_flag = false;
|
||||
|
||||
} else {
|
||||
}
|
||||
else
|
||||
generation_flag = GN_DEFAULT;
|
||||
}
|
||||
|
||||
static void parm_to_flagmap(const string&flag)
|
||||
@@ -273,22 +250,13 @@ static void parm_to_flagmap(const string&flag)
|
||||
* functor:<name>
|
||||
* Append a named functor to the processing path.
|
||||
*
|
||||
* generation:<1|2|2x|xtypes|no-xtypes|specify|no-specify>
|
||||
* generation:<1|2|3.0>
|
||||
* This is the generation flag
|
||||
*
|
||||
* ivlpp:<preprocessor command>
|
||||
* This specifies the ivlpp command line used to process
|
||||
* library modules as I read them in.
|
||||
*
|
||||
* iwidth:<bits>
|
||||
* This specifies the width of integer variables. (that is,
|
||||
* variables declared using the "integer" keyword.)
|
||||
*
|
||||
* library_file:<path>
|
||||
* This marks that a source file with the given path is a
|
||||
* library. Any modules in that file are marked as library
|
||||
* modules.
|
||||
*
|
||||
* module:<name>
|
||||
* Load a VPI module.
|
||||
*
|
||||
@@ -350,9 +318,12 @@ static void read_iconfig_file(const char*ipath)
|
||||
} else if (strcmp(cp,"elaborate") == 0) {
|
||||
debug_elaborate = true;
|
||||
cerr << "debug: Enable elaborate debug" << endl;
|
||||
} else if (strcmp(cp,"synth2") == 0) {
|
||||
debug_synth2 = true;
|
||||
cerr << "debug: Enable synth2 debug" << endl;
|
||||
} else if (strcmp(cp,"synth") == 0) {
|
||||
debug_synth = true;
|
||||
cerr << "debug: Enable synthesis debug" << endl;
|
||||
} else if (strcmp(cp,"cprop") == 0) {
|
||||
debug_cprop = true;
|
||||
cerr << "debug: Enable cprop debug" << endl;
|
||||
} else {
|
||||
}
|
||||
|
||||
@@ -379,13 +350,6 @@ static void read_iconfig_file(const char*ipath)
|
||||
} else if (strcmp(buf, "ivlpp") == 0) {
|
||||
ivlpp_string = strdup(cp);
|
||||
|
||||
} else if (strcmp(buf, "iwidth") == 0) {
|
||||
integer_width = strtoul(cp,0,10);
|
||||
|
||||
} else if (strcmp(buf, "library_file") == 0) {
|
||||
const char* path = strdup(cp);
|
||||
library_file_map[path] = true;
|
||||
|
||||
} else if (strcmp(buf,"module") == 0) {
|
||||
if (vpi_module_list == 0) {
|
||||
vpi_module_list = strdup(cp);
|
||||
@@ -422,6 +386,9 @@ static void read_iconfig_file(const char*ipath)
|
||||
case 't':
|
||||
warn_timescale = true;
|
||||
break;
|
||||
case 'u':
|
||||
warn_unused = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -586,21 +553,11 @@ int main(int argc, char*argv[])
|
||||
case GN_VER2001:
|
||||
cout << "IEEE1364-2001";
|
||||
break;
|
||||
case GN_VER2001X:
|
||||
cout << "IEEE1364-2001+Extensions";
|
||||
case GN_SYSVER30:
|
||||
cout << "SystemVerilog 3.0";
|
||||
break;
|
||||
}
|
||||
|
||||
if (gn_specify_blocks_flag)
|
||||
cout << ",specify";
|
||||
else
|
||||
cout << ",no-specify";
|
||||
|
||||
if (gn_cadence_types_flag)
|
||||
cout << ",xtypes";
|
||||
else
|
||||
cout << ",no-xtypes";
|
||||
|
||||
cout << endl << "PARSING INPUT" << endl;
|
||||
}
|
||||
|
||||
@@ -653,20 +610,11 @@ int main(int argc, char*argv[])
|
||||
for (mod = pform_modules.begin()
|
||||
; mod != pform_modules.end()
|
||||
; mod++) {
|
||||
|
||||
/* Don't choose library modules. */
|
||||
if ((*mod).second->library_flag)
|
||||
continue;
|
||||
|
||||
/* Don't choose modules instantiated in other
|
||||
modules. */
|
||||
if (mentioned_p[(*mod).second->mod_name()])
|
||||
continue;
|
||||
|
||||
/* What's left might as well be chosen as a root. */
|
||||
if (verbose_flag)
|
||||
cout << " " << (*mod).second->mod_name();
|
||||
roots.push_back((*mod).second->mod_name());
|
||||
if (mentioned_p[(*mod).second->mod_name()] == false) {
|
||||
if (verbose_flag)
|
||||
cout << " " << (*mod).second->mod_name();
|
||||
roots.push_back((*mod).second->mod_name());
|
||||
}
|
||||
}
|
||||
if (verbose_flag)
|
||||
cout << endl;
|
||||
@@ -762,18 +710,12 @@ int main(int argc, char*argv[])
|
||||
cout << "CODE GENERATION -t "<<target<< endl;
|
||||
}
|
||||
|
||||
int emit_rc;
|
||||
bool emit_rc;
|
||||
emit_rc = emit(des, target);
|
||||
if (emit_rc > 0) {
|
||||
cerr << "error: Code generation had "
|
||||
<< emit_rc << " errors."
|
||||
<< endl;
|
||||
if (!emit_rc) {
|
||||
cerr << "error: Code generation had errors." << endl;
|
||||
return 1;
|
||||
}
|
||||
if (emit_rc < 0) {
|
||||
cerr << "error: Code generator failure: " << emit_rc << endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (verbose_flag) {
|
||||
if (times_flag) {
|
||||
@@ -815,34 +757,14 @@ int main(int argc, char*argv[])
|
||||
|
||||
/*
|
||||
* $Log: main.cc,v $
|
||||
* Revision 1.95 2007/04/19 02:52:53 steve
|
||||
* Add support for -v flag in command file.
|
||||
* Revision 1.86.2.3 2006/06/12 00:16:53 steve
|
||||
* Add support for -Wunused warnings.
|
||||
*
|
||||
* Revision 1.94 2007/03/07 04:24:59 steve
|
||||
* Make integer width controllable.
|
||||
* Revision 1.86.2.2 2006/04/23 04:25:45 steve
|
||||
* Add cprop debugging.
|
||||
*
|
||||
* Revision 1.93 2006/09/28 04:35:18 steve
|
||||
* Support selective control of specify and xtypes features.
|
||||
*
|
||||
* Revision 1.92 2005/07/14 23:38:43 steve
|
||||
* Display as version 0.9.devel
|
||||
*
|
||||
* Revision 1.91 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.90 2005/06/28 04:25:55 steve
|
||||
* Remove reference to SystemVerilog.
|
||||
*
|
||||
* Revision 1.89 2005/04/24 23:44:02 steve
|
||||
* Update DFF support to new data flow.
|
||||
*
|
||||
* Revision 1.88 2005/01/22 01:06:55 steve
|
||||
* Change case compare from logic to an LPM node.
|
||||
*
|
||||
* Revision 1.87 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
* Revision 1.86.2.1 2006/04/01 01:37:24 steve
|
||||
* Add synth debug flag
|
||||
*
|
||||
* Revision 1.86 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
|
||||
@@ -71,7 +71,7 @@ The msys package is available from the mingw download site. This is
|
||||
not the compiler but a collection of *nix tools ported to Windows and
|
||||
wrapped in a convenient installer. The msys package is all the various
|
||||
basic tools (shells, file utils, etc) and the msysDTK is extra
|
||||
developer tools other than the compiler.
|
||||
developer tools other then the compiler.
|
||||
|
||||
Download the msys-1.x.x.exe and msysdtc-1.x.x.exe binaries. These are
|
||||
self-installing packages. Install msys first, and then msysDTC. Most
|
||||
|
||||
+121
-71
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_assign.cc,v 1.22 2007/01/16 05:44:15 steve Exp $"
|
||||
#ident "$Id: net_assign.cc,v 1.18.2.3 2006/05/02 02:00:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -39,11 +39,31 @@ unsigned count_lval_width(const NetAssign_*idx)
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetNet*s)
|
||||
: sig_(s), word_(0), base_(0)
|
||||
: sig_(s), mem_(0), var_(0), bmux_(0)
|
||||
{
|
||||
lwid_ = sig_->vector_width();
|
||||
loff_ = 0;
|
||||
lwid_ = sig_->pin_count();
|
||||
sig_->incr_lref();
|
||||
more = 0;
|
||||
mem_lref_ = false;
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetMemory*s)
|
||||
: sig_(0), mem_(s), var_(0), bmux_(0)
|
||||
{
|
||||
loff_ = 0;
|
||||
lwid_ = mem_->width();
|
||||
more = 0;
|
||||
mem_lref_ = false;
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetVariable*s)
|
||||
: sig_(0), mem_(0), var_(s), bmux_(0)
|
||||
{
|
||||
loff_ = 0;
|
||||
lwid_ = 0;
|
||||
more = 0;
|
||||
mem_lref_ = false;
|
||||
}
|
||||
|
||||
NetAssign_::~NetAssign_()
|
||||
@@ -54,40 +74,47 @@ NetAssign_::~NetAssign_()
|
||||
sig_->type(NetNet::WIRE);
|
||||
}
|
||||
|
||||
if (mem_) {
|
||||
NetNet*exp = mem_->reg_from_explode();
|
||||
if (exp && mem_lref_) {
|
||||
exp->decr_lref();
|
||||
if (turn_sig_to_wire_on_release_ && exp->peek_lref() == 0)
|
||||
exp->type(NetNet::WIRE);
|
||||
}
|
||||
}
|
||||
assert( more == 0 );
|
||||
if (word_) delete word_;
|
||||
if (bmux_) delete bmux_;
|
||||
}
|
||||
|
||||
void NetAssign_::set_word(NetExpr*r)
|
||||
void NetAssign_::set_bmux(NetExpr*r)
|
||||
{
|
||||
assert(word_ == 0);
|
||||
word_ = r;
|
||||
assert(bmux_ == 0);
|
||||
bmux_ = r;
|
||||
}
|
||||
|
||||
NetExpr* NetAssign_::word()
|
||||
NetExpr* NetAssign_::bmux()
|
||||
{
|
||||
return word_;
|
||||
return bmux_;
|
||||
}
|
||||
|
||||
const NetExpr* NetAssign_::word() const
|
||||
const NetExpr* NetAssign_::bmux() const
|
||||
{
|
||||
return word_;
|
||||
}
|
||||
|
||||
const NetExpr* NetAssign_::get_base() const
|
||||
{
|
||||
return base_;
|
||||
return bmux_;
|
||||
}
|
||||
|
||||
unsigned NetAssign_::lwidth() const
|
||||
{
|
||||
return lwid_;
|
||||
if (mem_) return lwid_;
|
||||
else if (bmux_) return 1;
|
||||
else return lwid_;
|
||||
}
|
||||
|
||||
perm_string NetAssign_::name() const
|
||||
{
|
||||
if (sig_) {
|
||||
return sig_->name();
|
||||
} else if (mem_) {
|
||||
return mem_->name();
|
||||
} else {
|
||||
return perm_string::literal("");
|
||||
}
|
||||
@@ -95,13 +122,48 @@ perm_string NetAssign_::name() const
|
||||
|
||||
NetNet* NetAssign_::sig() const
|
||||
{
|
||||
return sig_;
|
||||
if (mem_)
|
||||
return 0;
|
||||
else
|
||||
return sig_;
|
||||
}
|
||||
|
||||
void NetAssign_::set_part(NetExpr*base, unsigned wid)
|
||||
NetMemory* NetAssign_::mem() const
|
||||
{
|
||||
base_ = base;
|
||||
lwid_ = wid;
|
||||
return mem_;
|
||||
}
|
||||
|
||||
NetVariable* NetAssign_::var() const
|
||||
{
|
||||
return var_;
|
||||
}
|
||||
|
||||
void NetAssign_::incr_mem_lref()
|
||||
{
|
||||
if (! mem_lref_) {
|
||||
assert(mem_);
|
||||
NetNet*exp = mem_->reg_from_explode();
|
||||
assert(exp);
|
||||
exp->incr_lref();
|
||||
mem_lref_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void NetAssign_::set_part(unsigned lo, unsigned lw)
|
||||
{
|
||||
loff_ = lo;
|
||||
lwid_ = lw;
|
||||
if (sig_) {
|
||||
assert(sig_->pin_count() >= (lo + lw));
|
||||
} else {
|
||||
assert(mem_);
|
||||
assert(lwid_ == mem_->width());
|
||||
}
|
||||
}
|
||||
|
||||
unsigned NetAssign_::get_loff() const
|
||||
{
|
||||
return loff_;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -221,60 +283,16 @@ NetAssignNB::~NetAssignNB()
|
||||
{
|
||||
}
|
||||
|
||||
NetCAssign::NetCAssign(NetAssign_*lv, NetExpr*rv)
|
||||
: NetAssignBase(lv, rv)
|
||||
{
|
||||
}
|
||||
|
||||
NetCAssign::~NetCAssign()
|
||||
{
|
||||
}
|
||||
|
||||
NetDeassign::NetDeassign(NetAssign_*l)
|
||||
: NetAssignBase(l, 0)
|
||||
{
|
||||
}
|
||||
|
||||
NetDeassign::~NetDeassign()
|
||||
{
|
||||
}
|
||||
|
||||
NetForce::NetForce(NetAssign_*lv, NetExpr*rv)
|
||||
: NetAssignBase(lv, rv)
|
||||
{
|
||||
}
|
||||
|
||||
NetForce::~NetForce()
|
||||
{
|
||||
}
|
||||
|
||||
NetRelease::NetRelease(NetAssign_*l)
|
||||
: NetAssignBase(l, 0)
|
||||
{
|
||||
}
|
||||
|
||||
NetRelease::~NetRelease()
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_assign.cc,v $
|
||||
* Revision 1.22 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
* Revision 1.18.2.3 2006/05/02 02:00:15 steve
|
||||
* Fix uninitialized mem_lref_ member.
|
||||
*
|
||||
* Revision 1.21 2006/02/02 02:43:58 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
* Revision 1.18.2.2 2006/04/16 19:26:38 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.20 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.19 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
* Revision 1.18.2.1 2006/03/12 07:34:17 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.18 2004/08/28 15:08:31 steve
|
||||
* Do not change reg to wire in NetAssign_ unless synthesizing.
|
||||
@@ -285,5 +303,37 @@ NetRelease::~NetRelease()
|
||||
* Revision 1.16 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.15 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.14 2002/08/04 18:28:15 steve
|
||||
* Do not use hierarchical names of memories to
|
||||
* generate vvp labels. -tdll target does not
|
||||
* used hierarchical name string to look up the
|
||||
* memory objects in the design.
|
||||
*
|
||||
* Revision 1.13 2002/07/02 03:02:57 steve
|
||||
* Change the signal to a net when assignments go away.
|
||||
*
|
||||
* Revision 1.12 2002/06/08 23:42:46 steve
|
||||
* Add NetRamDq synthsesis from memory l-values.
|
||||
*
|
||||
* Revision 1.11 2002/06/04 05:38:44 steve
|
||||
* Add support for memory words in l-value of
|
||||
* blocking assignments, and remove the special
|
||||
* NetAssignMem class.
|
||||
*
|
||||
* Revision 1.10 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.9 2002/04/21 22:31:02 steve
|
||||
* Redo handling of assignment internal delays.
|
||||
* Leave it possible for them to be calculated
|
||||
* at run time.
|
||||
*/
|
||||
|
||||
|
||||
+141
-103
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_design.cc,v 1.54 2007/06/05 04:18:09 steve Exp $"
|
||||
#ident "$Id: net_design.cc,v 1.45.2.1 2006/10/04 00:34:45 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -32,7 +32,6 @@
|
||||
# include "netlist.h"
|
||||
# include "util.h"
|
||||
# include "compiler.h"
|
||||
# include "netmisc.h"
|
||||
# include <sstream>
|
||||
|
||||
Design:: Design()
|
||||
@@ -68,8 +67,8 @@ int Design::get_precision() const
|
||||
return des_precision_;
|
||||
}
|
||||
|
||||
uint64_t Design::scale_to_precision(uint64_t val,
|
||||
const NetScope*scope) const
|
||||
unsigned long Design::scale_to_precision(unsigned long val,
|
||||
const NetScope*scope) const
|
||||
{
|
||||
int units = scope->time_unit();
|
||||
assert( units >= des_precision_ );
|
||||
@@ -85,7 +84,7 @@ uint64_t Design::scale_to_precision(uint64_t val,
|
||||
NetScope* Design::make_root_scope(perm_string root)
|
||||
{
|
||||
NetScope *root_scope_;
|
||||
root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE);
|
||||
root_scope_ = new NetScope(0, root, NetScope::MODULE);
|
||||
/* This relies on the fact that the basename return value is
|
||||
permallocated. */
|
||||
root_scope_->set_module_name(root_scope_->basename());
|
||||
@@ -115,27 +114,26 @@ const list<NetScope*> Design::find_root_scopes() const
|
||||
* more step down the tree until the name runs out or the search
|
||||
* fails.
|
||||
*/
|
||||
NetScope* Design::find_scope(const std::list<hname_t>&path) const
|
||||
NetScope* Design::find_scope(const hname_t&path) const
|
||||
{
|
||||
if (path.empty())
|
||||
if (path.peek_name(0) == 0)
|
||||
return 0;
|
||||
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
|
||||
; scope != root_scopes_.end(); scope++) {
|
||||
|
||||
NetScope*cur = *scope;
|
||||
if (path.front() != cur->fullname())
|
||||
if (strcmp(path.peek_name(0), cur->basename()) != 0)
|
||||
continue;
|
||||
|
||||
std::list<hname_t> tmp = path;
|
||||
tmp.pop_front();
|
||||
|
||||
unsigned hidx = 1;
|
||||
while (cur) {
|
||||
if (tmp.empty()) return cur;
|
||||
const char*name = path.peek_name(hidx);
|
||||
if (name == 0)
|
||||
return cur;
|
||||
|
||||
cur = cur->child( tmp.front() );
|
||||
|
||||
tmp.pop_front();
|
||||
cur = cur->child(name);
|
||||
hidx += 1;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -145,34 +143,28 @@ NetScope* Design::find_scope(const std::list<hname_t>&path) const
|
||||
|
||||
/*
|
||||
* This is a relative lookup of a scope by name. The starting point is
|
||||
* the scope parameter within which I start looking for the scope. If
|
||||
* I do not find the scope within the passed scope, start looking in
|
||||
* parent scopes until I find it, or I run out of parent scopes.
|
||||
* the scope parameter is the place within which I start looking for
|
||||
* the scope. If I do not find the scope within the passed scope,
|
||||
* start looking in parent scopes until I find it, or I run out of
|
||||
* parent scopes.
|
||||
*/
|
||||
NetScope* Design::find_scope(NetScope*scope, const std::list<hname_t>&path) const
|
||||
NetScope* Design::find_scope(NetScope*scope, const hname_t&path) const
|
||||
{
|
||||
assert(scope);
|
||||
if (path.empty())
|
||||
if (path.peek_name(0) == 0)
|
||||
return scope;
|
||||
|
||||
for ( ; scope ; scope = scope->parent()) {
|
||||
|
||||
std::list<hname_t> tmp = path;
|
||||
unsigned hidx = 0;
|
||||
const char*key = path.peek_name(hidx);
|
||||
|
||||
NetScope*cur = scope;
|
||||
do {
|
||||
hname_t key = tmp.front();
|
||||
if (cur->type() == NetScope::MODULE
|
||||
&& cur->module_name()==key.peek_name()) {
|
||||
|
||||
/* Up references may match module name */
|
||||
|
||||
} else {
|
||||
cur = cur->child( key );
|
||||
if (cur == 0) break;
|
||||
}
|
||||
tmp.pop_front();
|
||||
} while (!tmp.empty());
|
||||
cur = cur->child(key);
|
||||
if (cur == 0) break;
|
||||
hidx += 1;
|
||||
key = path.peek_name(hidx);
|
||||
} while (key);
|
||||
|
||||
if (cur) return cur;
|
||||
}
|
||||
@@ -181,6 +173,71 @@ NetScope* Design::find_scope(NetScope*scope, const std::list<hname_t>&path) cons
|
||||
return find_scope(path);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find a parameter from within a specified context. If the name is
|
||||
* not here, keep looking up until I run out of up to look at. The
|
||||
* method works by scanning scopes, starting with the passed scope and
|
||||
* working up towards the root, looking for the named parameter. The
|
||||
* name in this case can be hierarchical, so there is an inner loop to
|
||||
* follow the scopes of the name down to to key.
|
||||
*
|
||||
* The expression value of the parameter is returned as the result,
|
||||
* and the scope that contains the parameter is returned in the out
|
||||
* argument found_in.
|
||||
*/
|
||||
const NetExpr* Design::find_parameter(NetScope*scope,
|
||||
const hname_t&path,
|
||||
NetScope*&found_in) const
|
||||
{
|
||||
for ( ; scope ; scope = scope->parent()) {
|
||||
unsigned hidx = 0;
|
||||
|
||||
NetScope*cur = scope;
|
||||
while (path.peek_name(hidx+1)) {
|
||||
cur = cur->child(path.peek_name(hidx));
|
||||
if (cur == 0)
|
||||
break;
|
||||
hidx += 1;
|
||||
}
|
||||
|
||||
if (cur == 0)
|
||||
continue;
|
||||
|
||||
if (const NetExpr*res = cur->get_parameter(path.peek_name(hidx))) {
|
||||
found_in = cur;
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const NetExpr* Design::find_parameter(const NetScope*scope,
|
||||
const hname_t&path) const
|
||||
{
|
||||
for ( ; scope ; scope = scope->parent()) {
|
||||
unsigned hidx = 0;
|
||||
|
||||
const NetScope*cur = scope;
|
||||
while (path.peek_name(hidx+1)) {
|
||||
cur = cur->child(path.peek_name(hidx));
|
||||
if (cur == 0)
|
||||
break;
|
||||
hidx += 1;
|
||||
}
|
||||
|
||||
if (cur == 0)
|
||||
continue;
|
||||
|
||||
if (const NetExpr*res = cur->get_parameter(path.peek_name(hidx)))
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This method runs through the scope, noticing the defparam
|
||||
* statements that were collected during the elaborate_scope pass and
|
||||
@@ -204,30 +261,29 @@ void NetScope::run_defparams(Design*des)
|
||||
}
|
||||
}
|
||||
|
||||
map<pform_name_t,NetExpr*>::const_iterator pp;
|
||||
map<hname_t,NetExpr*>::const_iterator pp;
|
||||
for (pp = defparams.begin() ; pp != defparams.end() ; pp ++ ) {
|
||||
NetExpr*val = (*pp).second;
|
||||
pform_name_t path = (*pp).first;
|
||||
hname_t path = (*pp).first;
|
||||
|
||||
perm_string perm_name = peek_tail_name(path);
|
||||
path.pop_back();
|
||||
|
||||
list<hname_t> eval_path = eval_scope_path(des, this, path);
|
||||
char*tmp = path.remove_tail_name();
|
||||
perm_string perm_name = lex_strings.make(tmp);
|
||||
delete[]tmp;
|
||||
|
||||
/* If there is no path on the name, then the targ_scope
|
||||
is the current scope. */
|
||||
NetScope*targ_scope = des->find_scope(this, eval_path);
|
||||
NetScope*targ_scope = des->find_scope(this, path);
|
||||
if (targ_scope == 0) {
|
||||
cerr << val->get_line() << ": warning: scope of " <<
|
||||
path << "." << perm_name << " not found." << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
bool flag = targ_scope->replace_parameter(perm_name, val);
|
||||
bool flag = targ_scope->replace_parameter(perm_name, val->dup_expr());
|
||||
if (! flag) {
|
||||
cerr << val->get_line() << ": warning: parameter "
|
||||
<< perm_name << " not found in "
|
||||
<< scope_path(targ_scope) << "." << endl;
|
||||
<< targ_scope->name() << "." << endl;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -334,27 +390,18 @@ void NetScope::evaluate_parameters(Design*des)
|
||||
assert(expr);
|
||||
|
||||
switch (expr->expr_type()) {
|
||||
case IVL_VT_REAL:
|
||||
case NetExpr::ET_REAL:
|
||||
if (! dynamic_cast<const NetECReal*>(expr)) {
|
||||
|
||||
NetExpr*nexpr = expr->eval_tree();
|
||||
if (nexpr == 0) {
|
||||
cerr << (*cur).second.expr->get_line()
|
||||
<< ": internal error: "
|
||||
<< "unable to evaluate real parameter value: "
|
||||
<< *expr << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(nexpr);
|
||||
delete expr;
|
||||
(*cur).second.expr = nexpr;
|
||||
cerr << (*cur).second.expr->get_line()
|
||||
<< ": internal error: "
|
||||
"unable to evaluate real parameter values: " <<
|
||||
*expr << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
|
||||
case IVL_VT_LOGIC:
|
||||
case IVL_VT_BOOL:
|
||||
case NetExpr::ET_VECTOR:
|
||||
if (! dynamic_cast<const NetEConst*>(expr)) {
|
||||
|
||||
// Try to evaluate the expression.
|
||||
@@ -434,52 +481,68 @@ const char* Design::get_flag(const string&key) const
|
||||
* It is the job of this function to properly implement Verilog scope
|
||||
* rules as signals are concerned.
|
||||
*/
|
||||
NetNet* Design::find_signal(NetScope*scope, pform_name_t path)
|
||||
NetNet* Design::find_signal(NetScope*scope, hname_t path)
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
perm_string key = peek_tail_name(path);
|
||||
path.pop_back();
|
||||
if (! path.empty()) {
|
||||
list<hname_t> eval_path = eval_scope_path(this, scope, path);
|
||||
scope = find_scope(scope, eval_path);
|
||||
}
|
||||
char*key = path.remove_tail_name();
|
||||
if (path.peek_name(0))
|
||||
scope = find_scope(scope, path);
|
||||
|
||||
while (scope) {
|
||||
if (NetNet*net = scope->find_signal(key))
|
||||
if (NetNet*net = scope->find_signal(key)) {
|
||||
delete key;
|
||||
return net;
|
||||
}
|
||||
|
||||
if (scope->type() == NetScope::MODULE)
|
||||
break;
|
||||
|
||||
scope = scope->parent();
|
||||
}
|
||||
|
||||
delete key;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetFuncDef* Design::find_function(NetScope*scope, const pform_name_t&name)
|
||||
NetFuncDef* Design::find_function(NetScope*scope, const hname_t&name)
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
std::list<hname_t> eval_path = eval_scope_path(this, scope, name);
|
||||
NetScope*func = find_scope(scope, eval_path);
|
||||
NetScope*func = find_scope(scope, name);
|
||||
if (func && (func->type() == NetScope::FUNC))
|
||||
return func->func_def();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope* Design::find_task(NetScope*scope, const pform_name_t&name)
|
||||
NetFuncDef* Design::find_function(const hname_t&key)
|
||||
{
|
||||
std::list<hname_t> eval_path = eval_scope_path(this, scope, name);
|
||||
NetScope*task = find_scope(scope, eval_path);
|
||||
NetScope*func = find_scope(key);
|
||||
if (func && (func->type() == NetScope::FUNC))
|
||||
return func->func_def();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope* Design::find_task(NetScope*scope, const hname_t&name)
|
||||
{
|
||||
NetScope*task = find_scope(scope, name);
|
||||
if (task && (task->type() == NetScope::TASK))
|
||||
return task;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetScope* Design::find_task(const hname_t&key)
|
||||
{
|
||||
NetScope*task = find_scope(key);
|
||||
if (task && (task->type() == NetScope::TASK))
|
||||
return task;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Design::add_node(NetNode*net)
|
||||
{
|
||||
assert(net->design_ == 0);
|
||||
@@ -555,33 +618,8 @@ void Design::delete_process(NetProcTop*top)
|
||||
|
||||
/*
|
||||
* $Log: net_design.cc,v $
|
||||
* Revision 1.54 2007/06/05 04:18:09 steve
|
||||
* Upward names may reference modules by module_name.
|
||||
*
|
||||
* Revision 1.53 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.52 2007/05/24 04:07:12 steve
|
||||
* Rework the heirarchical identifier parse syntax and pform
|
||||
* to handle more general combinations of heirarch and bit selects.
|
||||
*
|
||||
* Revision 1.51 2007/04/26 03:06:22 steve
|
||||
* Rework hname_t to use perm_strings.
|
||||
*
|
||||
* Revision 1.50 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.49 2006/07/31 03:50:17 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.48 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
* Revision 1.47 2005/09/14 02:53:14 steve
|
||||
* Support bool expressions and compares handle them optimally.
|
||||
*
|
||||
* Revision 1.46 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
* Revision 1.45.2.1 2006/10/04 00:34:45 steve
|
||||
* Fix a dangling reference to NetEParam objects in defparams.
|
||||
*
|
||||
* Revision 1.45 2004/10/04 01:10:54 steve
|
||||
* Clean up spurious trailing white space.
|
||||
|
||||
+3
-6
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_event.cc,v 1.27 2007/06/02 03:42:13 steve Exp $"
|
||||
#ident "$Id: net_event.cc,v 1.26 2004/10/04 01:10:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -56,10 +56,10 @@ perm_string NetEvent::name() const
|
||||
return name_;
|
||||
}
|
||||
|
||||
NetScope* NetEvent::scope()
|
||||
string NetEvent::full_name() const
|
||||
{
|
||||
assert(scope_);
|
||||
return scope_;
|
||||
return scope_->name() + "." + string(name_);
|
||||
}
|
||||
|
||||
const NetScope* NetEvent::scope() const
|
||||
@@ -449,9 +449,6 @@ NetProc* NetEvWait::statement()
|
||||
|
||||
/*
|
||||
* $Log: net_event.cc,v $
|
||||
* Revision 1.27 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.26 2004/10/04 01:10:54 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
+33
-89
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_expr.cc,v 1.27 2006/07/31 03:50:17 steve Exp $"
|
||||
#ident "$Id: net_expr.cc,v 1.23 2004/10/04 01:10:54 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -25,12 +25,9 @@
|
||||
# include "compiler.h"
|
||||
# include <iostream>
|
||||
|
||||
/*
|
||||
* the grand default data type is a logic vector.
|
||||
*/
|
||||
ivl_variable_type_t NetExpr::expr_type() const
|
||||
NetExpr::TYPE NetExpr::expr_type() const
|
||||
{
|
||||
return IVL_VT_LOGIC;
|
||||
return ET_VECTOR;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -99,15 +96,15 @@ NetEBAdd* NetEBAdd::dup_expr() const
|
||||
return result;
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetEBAdd::expr_type() const
|
||||
NetExpr::TYPE NetEBAdd::expr_type() const
|
||||
{
|
||||
if (left_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
|
||||
if (right_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
|
||||
return IVL_VT_LOGIC;
|
||||
return ET_VECTOR;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -164,21 +161,6 @@ bool NetEBComp::has_width() const
|
||||
return true;
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetEBComp::expr_type() const
|
||||
{
|
||||
// Case compare always returns BOOL
|
||||
if (op() == 'E' || op() == 'N')
|
||||
return IVL_VT_BOOL;
|
||||
|
||||
if (left()->expr_type() == IVL_VT_LOGIC)
|
||||
return IVL_VT_LOGIC;
|
||||
|
||||
if (right()->expr_type() == IVL_VT_LOGIC)
|
||||
return IVL_VT_LOGIC;
|
||||
|
||||
return IVL_VT_BOOL;
|
||||
}
|
||||
|
||||
NetEBDiv::NetEBDiv(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
@@ -201,15 +183,15 @@ NetEBDiv* NetEBDiv::dup_expr() const
|
||||
return result;
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetEBDiv::expr_type() const
|
||||
NetExpr::TYPE NetEBDiv::expr_type() const
|
||||
{
|
||||
if (left_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
|
||||
if (right_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
|
||||
return IVL_VT_LOGIC;
|
||||
return ET_VECTOR;
|
||||
}
|
||||
|
||||
NetEBMult::NetEBMult(char op, NetExpr*l, NetExpr*r)
|
||||
@@ -237,49 +219,15 @@ NetEBMult* NetEBMult::dup_expr() const
|
||||
return result;
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetEBMult::expr_type() const
|
||||
NetExpr::TYPE NetEBMult::expr_type() const
|
||||
{
|
||||
if (left_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
if (left_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
|
||||
if (right_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
if (right_->expr_type() == ET_REAL)
|
||||
return ET_REAL;
|
||||
|
||||
return IVL_VT_LOGIC;
|
||||
}
|
||||
|
||||
NetEBPow::NetEBPow(char op, NetExpr*l, NetExpr*r)
|
||||
: NetEBinary(op, l, r)
|
||||
{
|
||||
assert(op == 'p');
|
||||
expr_width(l->expr_width());
|
||||
cast_signed(l->has_sign() || r->has_sign());
|
||||
}
|
||||
|
||||
NetEBPow::~NetEBPow()
|
||||
{
|
||||
}
|
||||
|
||||
NetEBPow* NetEBPow::dup_expr() const
|
||||
{
|
||||
NetEBPow*result = new NetEBPow(op_, left_->dup_expr(),
|
||||
right_->dup_expr());
|
||||
result->set_line(*this);
|
||||
return result;
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetEBPow::expr_type() const
|
||||
{
|
||||
if (right_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
if (left_->expr_type() == IVL_VT_REAL)
|
||||
return IVL_VT_REAL;
|
||||
if (left_->has_sign())
|
||||
return IVL_VT_REAL;
|
||||
if (right_->has_sign())
|
||||
return IVL_VT_REAL;
|
||||
|
||||
return IVL_VT_LOGIC;
|
||||
return ET_VECTOR;
|
||||
}
|
||||
|
||||
NetEBShift::NetEBShift(char op, NetExpr*l, NetExpr*r)
|
||||
@@ -424,9 +372,9 @@ NetECReal* NetECReal::dup_expr() const
|
||||
return tmp;
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetECReal::expr_type() const
|
||||
NetExpr::TYPE NetECReal::expr_type() const
|
||||
{
|
||||
return IVL_VT_REAL;
|
||||
return ET_REAL;
|
||||
}
|
||||
|
||||
NetECRealParam::NetECRealParam(NetScope*s, perm_string n, const verireal&v)
|
||||
@@ -502,7 +450,15 @@ bool NetESelect::has_width() const
|
||||
return true;
|
||||
}
|
||||
|
||||
NetESFunc::NetESFunc(const char*n, ivl_variable_type_t t,
|
||||
bool NetESelect::set_width(unsigned w)
|
||||
{
|
||||
if (expr_width() == 1)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
NetESFunc::NetESFunc(const char*n, NetExpr::TYPE t,
|
||||
unsigned width, unsigned np)
|
||||
: name_(0), type_(t)
|
||||
{
|
||||
@@ -553,25 +509,13 @@ NetExpr* NetESFunc::parm(unsigned idx)
|
||||
return parms_[idx];
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetESFunc::expr_type() const
|
||||
NetExpr::TYPE NetESFunc::expr_type() const
|
||||
{
|
||||
return type_;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_expr.cc,v $
|
||||
* Revision 1.27 2006/07/31 03:50:17 steve
|
||||
* Add support for power in constant expressions.
|
||||
*
|
||||
* Revision 1.26 2005/11/26 00:35:43 steve
|
||||
* More precise about r-value width of constants.
|
||||
*
|
||||
* Revision 1.25 2005/09/14 02:53:14 steve
|
||||
* Support bool expressions and compares handle them optimally.
|
||||
*
|
||||
* Revision 1.24 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.23 2004/10/04 01:10:54 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
|
||||
+102
-6
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_force.cc,v 1.13 2004/12/11 02:31:26 steve Exp $"
|
||||
#ident "$Id: net_force.cc,v 1.12 2004/02/18 17:11:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -33,14 +33,110 @@
|
||||
# include "netlist.h"
|
||||
# include <assert.h>
|
||||
|
||||
/*
|
||||
* Construct the procedural continuous assignment statement. This is a
|
||||
* bit different from a normal assignment because the the lval is only
|
||||
* intermittently connected. The deassign in particular disconnects
|
||||
* the signals when they are not being assigned anymore. Because of
|
||||
* this, there is no other reference to the lval to make it stay put
|
||||
* so we increment the eref.
|
||||
*
|
||||
* XXXX I'm not sure this is the right way. Perhaps I should create
|
||||
* output pins to connect to the netlist? But that would cause the
|
||||
* link ring to grow, and that is not quite correct either. Hmm...
|
||||
*/
|
||||
NetCAssign::NetCAssign(NetScope*s, perm_string n, NetNet*l)
|
||||
: NetNode(s, n, l->pin_count()), lval_(l)
|
||||
{
|
||||
lval_->incr_eref();
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("I"), idx);
|
||||
}
|
||||
}
|
||||
|
||||
NetCAssign::~NetCAssign()
|
||||
{
|
||||
lval_->decr_eref();
|
||||
}
|
||||
|
||||
const NetNet* NetCAssign::lval() const
|
||||
{
|
||||
return lval_;
|
||||
}
|
||||
|
||||
const Link& NetCAssign::lval_pin(unsigned idx) const
|
||||
{
|
||||
assert(idx < lval_->pin_count());
|
||||
return lval_->pin(idx);
|
||||
}
|
||||
|
||||
NetDeassign::NetDeassign(NetNet*l)
|
||||
: lval_(l)
|
||||
{
|
||||
lval_->incr_eref();
|
||||
}
|
||||
|
||||
NetDeassign::~NetDeassign()
|
||||
{
|
||||
lval_->decr_eref();
|
||||
}
|
||||
|
||||
const NetNet*NetDeassign::lval() const
|
||||
{
|
||||
return lval_;
|
||||
}
|
||||
|
||||
NetForce::NetForce(NetScope*s, perm_string n, NetNet*l)
|
||||
: NetNode(s, n, l->pin_count()), lval_(l)
|
||||
{
|
||||
lval_->incr_eref();
|
||||
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("I"), idx);
|
||||
}
|
||||
}
|
||||
|
||||
NetForce::~NetForce()
|
||||
{
|
||||
lval_->decr_eref();
|
||||
}
|
||||
|
||||
const Link& NetForce::lval_pin(unsigned idx) const
|
||||
{
|
||||
assert(idx < lval_->pin_count());
|
||||
return lval_->pin(idx);
|
||||
}
|
||||
|
||||
const NetNet* NetForce::lval() const
|
||||
{
|
||||
return lval_;
|
||||
}
|
||||
|
||||
NetRelease::NetRelease(NetNet*l)
|
||||
: lval_(l)
|
||||
{
|
||||
/* Put myself into a release list that the net is
|
||||
keeping. This is so that the NetNet can detach itself if
|
||||
and when it is deleted by the optimizer. */
|
||||
release_next_ = lval_->release_list_;
|
||||
lval_->release_list_ = this;
|
||||
}
|
||||
|
||||
NetRelease::~NetRelease()
|
||||
{
|
||||
assert(lval_ == 0);
|
||||
}
|
||||
|
||||
const NetNet*NetRelease::lval() const
|
||||
{
|
||||
return lval_;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: net_force.cc,v $
|
||||
* Revision 1.13 2004/12/11 02:31:26 steve
|
||||
* Rework of internals to carry vectors through nexus instead
|
||||
* of single bits. Make the ivl, tgt-vvp and vvp initial changes
|
||||
* down this path.
|
||||
*
|
||||
* Revision 1.12 2004/02/18 17:11:56 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
||||
+70
-67
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_func.cc,v 1.10 2007/06/02 03:42:13 steve Exp $"
|
||||
#ident "$Id: net_func.cc,v 1.6 2004/05/31 23:34:37 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -26,25 +26,42 @@
|
||||
# include "PExpr.h"
|
||||
# include <iostream>
|
||||
|
||||
/*
|
||||
* To make a NetUserFunc device, make as many pins as there are ports
|
||||
* in the function. Get the port count from the function definition,
|
||||
* which accounts for all the inputs, plus one for the phantom output
|
||||
* that is the result.
|
||||
*/
|
||||
static unsigned count_def_pins(const NetFuncDef*def)
|
||||
{
|
||||
assert(def->return_sig());
|
||||
|
||||
unsigned sum = def->return_sig()->pin_count();
|
||||
for (unsigned idx = 0 ; idx < def->port_count() ; idx += 1)
|
||||
sum += def->port(idx)->pin_count();
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
NetUserFunc::NetUserFunc(NetScope*s, perm_string n, NetScope*d)
|
||||
: NetNode(s, n, d->func_def()->port_count()+1),
|
||||
: NetNode(s, n, count_def_pins(d->func_def())),
|
||||
def_(d)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(def_->basename(), 0);
|
||||
NetFuncDef*def = def_->func_def();
|
||||
|
||||
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
|
||||
unsigned port_wid = port_width(0);
|
||||
for (unsigned idx = 0 ; idx < port_wid ; idx += 1) {
|
||||
pin(idx).set_dir(Link::OUTPUT);
|
||||
pin(idx).set_name(def_->basename(), idx);
|
||||
}
|
||||
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("D"), idx-1);
|
||||
pin(idx).drive0(Link::HIGHZ);
|
||||
pin(idx).drive1(Link::HIGHZ);
|
||||
unsigned pin_base = port_wid;
|
||||
for (unsigned idx = 1 ; idx < port_count() ; idx += 1) {
|
||||
|
||||
const NetNet*port_sig = def->port(idx-1);
|
||||
unsigned bits = port_width(idx);
|
||||
for (unsigned bit = 0; bit < bits; bit += 1) {
|
||||
pin(pin_base+bit).set_dir(Link::INPUT);
|
||||
pin(pin_base+bit).set_name(port_sig->name(), bit);
|
||||
pin(pin_base+bit).drive0(Link::HIGHZ);
|
||||
pin(pin_base+bit).drive1(Link::HIGHZ);
|
||||
}
|
||||
|
||||
pin_base += bits;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,6 +69,11 @@ NetUserFunc::~NetUserFunc()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned NetUserFunc::port_count() const
|
||||
{
|
||||
return def_->func_def()->port_count() + 1;
|
||||
}
|
||||
|
||||
unsigned NetUserFunc::port_width(unsigned port) const
|
||||
{
|
||||
NetFuncDef*def = def_->func_def();
|
||||
@@ -60,16 +82,44 @@ unsigned NetUserFunc::port_width(unsigned port) const
|
||||
if (port == 0) {
|
||||
const NetNet*sig = def->return_sig();
|
||||
assert(sig);
|
||||
return sig->vector_width();
|
||||
return sig->pin_count();
|
||||
}
|
||||
|
||||
port -= 1;
|
||||
assert(port < def->port_count());
|
||||
const NetNet*port_sig = def->port(port);
|
||||
|
||||
return port_sig->vector_width();
|
||||
return port_sig->pin_count();
|
||||
}
|
||||
|
||||
Link& NetUserFunc::port_pin(unsigned port, unsigned idx)
|
||||
{
|
||||
NetFuncDef*def = def_->func_def();
|
||||
unsigned pin_base = 0;
|
||||
const NetNet*port_sig;
|
||||
|
||||
if (port == 0)
|
||||
return pin(idx);
|
||||
|
||||
port_sig = def->return_sig();
|
||||
pin_base += port_sig->pin_count();
|
||||
port -= 1;
|
||||
|
||||
assert(port < def->port_count());
|
||||
|
||||
for (unsigned port_idx = 0 ; port_idx < port ; port_idx += 1) {
|
||||
port_sig = def->port(port_idx);
|
||||
pin_base += port_sig->pin_count();
|
||||
}
|
||||
|
||||
port_sig = def->port(port);
|
||||
assert(idx < port_sig->pin_count());
|
||||
assert((pin_base+idx) < pin_count());
|
||||
|
||||
return pin(pin_base+idx);
|
||||
}
|
||||
|
||||
|
||||
const NetScope* NetUserFunc::def() const
|
||||
{
|
||||
return def_;
|
||||
@@ -95,14 +145,14 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope)
|
||||
|
||||
if (dscope->type() != NetScope::FUNC) {
|
||||
cerr << get_line() << ": error: Attempt to call scope "
|
||||
<< scope_path(dscope) << " as a function." << endl;
|
||||
<< dscope->name() << " as a function." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parms_count != dscope->func_def()->port_count()) {
|
||||
cerr << get_line() << ": error: Function " << scope_path(dscope)
|
||||
<< " expects " << (dscope->func_def()->port_count())
|
||||
cerr << get_line() << ": error: Function " << dscope->name()
|
||||
<< " expects " << (dscope->func_def()->port_count()-1)
|
||||
<< " arguments, you passed " << parms_count << "."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
@@ -112,55 +162,8 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope)
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
NetSysFunc::NetSysFunc(NetScope*s, perm_string n,
|
||||
const struct sfunc_return_type*def,
|
||||
unsigned ports)
|
||||
: NetNode(s, n, ports)
|
||||
{
|
||||
def_ = def;
|
||||
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Q"), 0);
|
||||
|
||||
for (unsigned idx = 1 ; idx < pin_count() ; idx += 1) {
|
||||
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
pin(idx).set_name(perm_string::literal("D"), idx-1);
|
||||
pin(idx).drive0(Link::HIGHZ);
|
||||
pin(idx).drive1(Link::HIGHZ);
|
||||
}
|
||||
}
|
||||
|
||||
NetSysFunc::~NetSysFunc()
|
||||
{
|
||||
}
|
||||
|
||||
const char*NetSysFunc::func_name() const
|
||||
{
|
||||
return def_->name;
|
||||
}
|
||||
|
||||
unsigned NetSysFunc::vector_width() const
|
||||
{
|
||||
return def_->wid;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: net_func.cc,v $
|
||||
* Revision 1.10 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.9 2007/04/17 04:17:47 steve
|
||||
* Fix argument count in function error message.
|
||||
*
|
||||
* Revision 1.8 2006/06/18 04:15:50 steve
|
||||
* Add support for system functions in continuous assignments.
|
||||
*
|
||||
* Revision 1.7 2005/03/18 02:56:03 steve
|
||||
* Add support for LPM_UFUNC user defined functions.
|
||||
*
|
||||
* Revision 1.6 2004/05/31 23:34:37 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
|
||||
+127
-99
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_link.cc,v 1.21 2007/06/02 03:42:13 steve Exp $"
|
||||
#ident "$Id: net_link.cc,v 1.14.2.6 2006/08/23 04:09:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -40,18 +40,16 @@ void connect(Nexus*l, Link&r)
|
||||
if (l == r.nexus_)
|
||||
return;
|
||||
|
||||
|
||||
Nexus*tmp = r.nexus_;
|
||||
|
||||
while (Link*cur = tmp->list_) {
|
||||
tmp->list_ = cur->next_;
|
||||
cur->nexus_ = 0;
|
||||
cur->next_ = 0;
|
||||
cur->prev_ = 0;
|
||||
l->relink(cur);
|
||||
}
|
||||
|
||||
l->driven_ = Nexus::NO_GUESS;
|
||||
|
||||
assert(tmp->list_ == 0);
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
@@ -60,13 +58,15 @@ void connect(Link&l, Link&r)
|
||||
assert(&l != &r);
|
||||
if (r.is_linked() && !l.is_linked())
|
||||
connect(r.nexus_, l);
|
||||
else if (r.nexus_->list_len_ > l.nexus_->list_len_)
|
||||
connect(r.nexus_, l);
|
||||
else
|
||||
connect(l.nexus_, r);
|
||||
}
|
||||
|
||||
Link::Link()
|
||||
: dir_(PASSIVE), drive0_(STRONG), drive1_(STRONG), init_(verinum::Vx),
|
||||
inst_(0), next_(0), nexus_(0)
|
||||
inst_(0), next_(0), prev_(0), nexus_(0)
|
||||
{
|
||||
(new Nexus()) -> relink(this);
|
||||
}
|
||||
@@ -218,6 +218,7 @@ Nexus::Nexus()
|
||||
{
|
||||
name_ = 0;
|
||||
list_ = 0;
|
||||
list_len_ = 0;
|
||||
driven_ = NO_GUESS;
|
||||
t_cookie_ = 0;
|
||||
}
|
||||
@@ -244,6 +245,18 @@ verinum::V Nexus::get_init() const
|
||||
return verinum::Vz;
|
||||
}
|
||||
|
||||
int Nexus::is_driven() const
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
for (Link*cur = list_ ; cur ; cur = cur->next_) {
|
||||
if (cur->get_dir() == Link::OUTPUT)
|
||||
count += 1;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void Nexus::unlink(Link*that)
|
||||
{
|
||||
if (name_) {
|
||||
@@ -257,22 +270,32 @@ void Nexus::unlink(Link*that)
|
||||
driven_ = NO_GUESS;
|
||||
|
||||
assert(that);
|
||||
assert(that->nexus_ == this);
|
||||
if (list_ == that) {
|
||||
assert(that->prev_ == 0);
|
||||
// Move the second item the front of the list.
|
||||
list_ = that->next_;
|
||||
if (list_)
|
||||
list_->prev_ = 0;
|
||||
list_len_ -= 1;
|
||||
// Clear the pointers for the link.
|
||||
that->next_ = 0;
|
||||
that->prev_ = 0;
|
||||
that->nexus_ = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
Link*cur = list_;
|
||||
while (cur->next_ != that) {
|
||||
assert(cur->next_);
|
||||
cur = cur->next_;
|
||||
}
|
||||
|
||||
Link*cur = that->prev_;
|
||||
assert(cur->nexus_ == this);
|
||||
|
||||
cur->next_ = that->next_;
|
||||
if (cur->next_)
|
||||
cur->next_->prev_ = cur;
|
||||
that->nexus_ = 0;
|
||||
that->next_ = 0;
|
||||
that->prev_ = 0;
|
||||
list_len_ -= 1;
|
||||
}
|
||||
|
||||
void Nexus::relink(Link*that)
|
||||
@@ -290,8 +313,13 @@ void Nexus::relink(Link*that)
|
||||
assert(that->nexus_ == 0);
|
||||
assert(that->next_ == 0);
|
||||
that->next_ = list_;
|
||||
that->prev_ = 0;
|
||||
if (that->next_)
|
||||
that->next_->prev_ = that;
|
||||
|
||||
that->nexus_ = this;
|
||||
list_ = that;
|
||||
list_len_ += 1;
|
||||
}
|
||||
|
||||
Link* Nexus::first_nlink()
|
||||
@@ -304,42 +332,18 @@ const Link* Nexus::first_nlink() const
|
||||
return list_;
|
||||
}
|
||||
|
||||
ivl_nexus_t Nexus::t_cookie() const
|
||||
void* Nexus::t_cookie() const
|
||||
{
|
||||
return t_cookie_;
|
||||
}
|
||||
|
||||
ivl_nexus_t Nexus::t_cookie(ivl_nexus_t val)const
|
||||
void* Nexus::t_cookie(void*val)const
|
||||
{
|
||||
ivl_nexus_t tmp = t_cookie_;
|
||||
void*tmp = t_cookie_;
|
||||
t_cookie_ = val;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
unsigned Nexus::vector_width() const
|
||||
{
|
||||
for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||
const NetNet*sig = dynamic_cast<const NetNet*>(cur->get_obj());
|
||||
if (sig == 0)
|
||||
continue;
|
||||
|
||||
return sig->vector_width();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetNet* Nexus::pick_any_net()
|
||||
{
|
||||
for (Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) {
|
||||
NetNet*sig = dynamic_cast<NetNet*>(cur->get_obj());
|
||||
if (sig != 0)
|
||||
return sig;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char* Nexus::name() const
|
||||
{
|
||||
if (name_)
|
||||
@@ -387,11 +391,12 @@ const char* Nexus::name() const
|
||||
obj->name() << " pin " << pin << "(" <<
|
||||
lnk->get_name() << "<" << lnk->get_inst() << ">)"
|
||||
" type=" << typeid(*obj).name() << "?" << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(sig);
|
||||
ostringstream tmp;
|
||||
tmp << scope_path(sig->scope()) << "." << sig->name();
|
||||
tmp << sig->name();
|
||||
if (sig->pin_count() > 1)
|
||||
tmp << "<" << pin << ">";
|
||||
|
||||
@@ -405,6 +410,7 @@ const char* Nexus::name() const
|
||||
NexusSet::NexusSet()
|
||||
{
|
||||
items_ = 0;
|
||||
index_ = 0;
|
||||
nitems_ = 0;
|
||||
}
|
||||
|
||||
@@ -413,8 +419,11 @@ NexusSet::~NexusSet()
|
||||
if (nitems_ > 0) {
|
||||
assert(items_ != 0);
|
||||
delete[] items_;
|
||||
assert(index_ != 0);
|
||||
delete[] index_;
|
||||
} else {
|
||||
assert(items_ == 0);
|
||||
assert(index_ == 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -423,26 +432,44 @@ unsigned NexusSet::count() const
|
||||
return nitems_;
|
||||
}
|
||||
|
||||
/*
|
||||
* Add the Nexus to the nexus set at the *end* of the array. This
|
||||
* preserves order, which is used in a few cases by the
|
||||
* synthesizer. But for efficiency, also create a sorted index.
|
||||
*/
|
||||
void NexusSet::add(Nexus*that)
|
||||
{
|
||||
/* Handle the special case that the set is empty. */
|
||||
if (nitems_ == 0) {
|
||||
assert(items_ == 0);
|
||||
assert(index_ == 0);
|
||||
items_ = (Nexus**)malloc(sizeof(Nexus*));
|
||||
items_[0] = that;
|
||||
index_ = (unsigned*)malloc(sizeof(unsigned));
|
||||
index_[0] = 0;
|
||||
nitems_ = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned ptr = bsearch_(that);
|
||||
if (ptr < nitems_) {
|
||||
assert(items_[ptr] == that);
|
||||
if (ptr < nitems_ && items_[index_[ptr]] == that) {
|
||||
assert(items_[index_[ptr]] == that);
|
||||
return;
|
||||
}
|
||||
|
||||
assert(ptr == nitems_);
|
||||
items_ = (Nexus**) realloc(items_, (nitems_+1) * sizeof(Nexus*));
|
||||
index_ = (unsigned*)realloc(index_, (nitems_+1) * sizeof(unsigned));
|
||||
|
||||
items_[nitems_] = that;
|
||||
|
||||
unsigned dest = nitems_;
|
||||
for (unsigned idx = ptr ; idx < nitems_ ; idx += 1) {
|
||||
unsigned tmp = index_[idx];
|
||||
index_[idx] = dest;
|
||||
dest = tmp;
|
||||
}
|
||||
index_[nitems_] = dest;
|
||||
|
||||
items_ = (Nexus**)realloc(items_, (nitems_+1) * sizeof(Nexus*));
|
||||
items_[ptr] = that;
|
||||
nitems_ += 1;
|
||||
}
|
||||
|
||||
@@ -458,20 +485,31 @@ void NexusSet::rem(Nexus*that)
|
||||
return;
|
||||
|
||||
unsigned ptr = bsearch_(that);
|
||||
if (ptr >= nitems_)
|
||||
if (ptr >= nitems_ || items_[index_[ptr]] != that)
|
||||
return;
|
||||
|
||||
if (nitems_ == 1) {
|
||||
free(items_);
|
||||
free(index_);
|
||||
items_ = 0;
|
||||
index_ = 0;
|
||||
nitems_ = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
for (unsigned idx = ptr ; idx < (nitems_-1) ; idx += 1)
|
||||
unsigned index_ptr = index_[ptr];
|
||||
for (unsigned idx = index_ptr ; idx < (nitems_-1) ; idx += 1)
|
||||
items_[idx] = items_[idx+1];
|
||||
|
||||
items_ = (Nexus**)realloc(items_, (nitems_-1) * sizeof(Nexus*));
|
||||
for (unsigned idx = ptr ; idx < (nitems_-1) ; idx += 1)
|
||||
index_[idx] = index_[idx+1];
|
||||
|
||||
for (unsigned idx = 0 ; idx < (nitems_-1) ; idx += 1)
|
||||
if (index_[idx] > index_ptr)
|
||||
index_[idx] -= 1;
|
||||
|
||||
items_ = (Nexus**) realloc(items_, (nitems_-1) * sizeof(Nexus*));
|
||||
index_ = (unsigned*)realloc(index_, (nitems_-1) * sizeof(unsigned));
|
||||
nitems_ -= 1;
|
||||
}
|
||||
|
||||
@@ -487,14 +525,37 @@ Nexus* NexusSet::operator[] (unsigned idx) const
|
||||
return items_[idx];
|
||||
}
|
||||
|
||||
/*
|
||||
* This method uses binary search to locate the item in the list of
|
||||
* nexus pointers. If the item is in the set, then this method returns
|
||||
* the index where it exists in the *index* array. If the item is not
|
||||
* in the set, the index points to where in the array the item should go.
|
||||
*/
|
||||
unsigned NexusSet::bsearch_(Nexus*that) const
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
|
||||
if (items_[idx] == that)
|
||||
return idx;
|
||||
|
||||
unsigned low = 0, hig = nitems_;
|
||||
|
||||
while (low < hig) {
|
||||
unsigned mid = (low + hig) / 2;
|
||||
if (mid == hig) mid -= 1;
|
||||
assert(mid >= low);
|
||||
assert(mid < hig);
|
||||
|
||||
if (items_[index_[mid]] == that) {
|
||||
return mid;
|
||||
|
||||
} else if (items_[index_[mid]] > that) {
|
||||
hig = mid;
|
||||
|
||||
} else {
|
||||
low = mid+1;
|
||||
}
|
||||
}
|
||||
|
||||
return nitems_;
|
||||
assert(low == hig);
|
||||
assert(low == nitems_ || items_[index_[low]] >= that);
|
||||
return low;
|
||||
}
|
||||
|
||||
bool NexusSet::contains(const NexusSet&that) const
|
||||
@@ -503,7 +564,7 @@ bool NexusSet::contains(const NexusSet&that) const
|
||||
unsigned where = bsearch_(that[idx]);
|
||||
if (where == nitems_)
|
||||
return false;
|
||||
if (items_[where] != that[idx])
|
||||
if (items_[index_[where]] != that[idx])
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -516,7 +577,7 @@ bool NexusSet::intersect(const NexusSet&that) const
|
||||
unsigned where = bsearch_(that[idx]);
|
||||
if (where == nitems_)
|
||||
continue;
|
||||
if (items_[where] == that[idx])
|
||||
if (items_[index_[where]] == that[idx])
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -525,26 +586,23 @@ bool NexusSet::intersect(const NexusSet&that) const
|
||||
|
||||
/*
|
||||
* $Log: net_link.cc,v $
|
||||
* Revision 1.21 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
* Revision 1.14.2.6 2006/08/23 04:09:14 steve
|
||||
* missing sig diagnostics.
|
||||
*
|
||||
* Revision 1.20 2007/03/26 18:17:50 steve
|
||||
* Remove pretense of general use for t_cookie.
|
||||
* Revision 1.14.2.5 2006/08/15 03:41:24 steve
|
||||
* Improve performance of unlink of heavily connected nexa.
|
||||
*
|
||||
* Revision 1.19 2006/02/02 02:43:58 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
* Revision 1.14.2.4 2006/08/08 02:17:48 steve
|
||||
* Improved nexus management performance.
|
||||
*
|
||||
* Revision 1.18 2005/09/25 23:40:11 steve
|
||||
* Simplify NexusSet set handling.
|
||||
* Revision 1.14.2.3 2006/07/23 19:42:33 steve
|
||||
* Handle statement output override better in blocks.
|
||||
*
|
||||
* Revision 1.17 2005/06/13 23:22:37 steve
|
||||
* Fix compile errors.
|
||||
* Revision 1.14.2.2 2006/01/27 02:05:46 steve
|
||||
* Speed up processing of connect when one side is empty.
|
||||
*
|
||||
* Revision 1.16 2005/04/24 23:44:02 steve
|
||||
* Update DFF support to new data flow.
|
||||
*
|
||||
* Revision 1.15 2005/01/09 20:16:01 steve
|
||||
* Use PartSelect/PV and VP to handle part selects through ports.
|
||||
* Revision 1.14.2.1 2005/09/25 23:30:31 steve
|
||||
* More predictable ordering of items in NexusSet.
|
||||
*
|
||||
* Revision 1.14 2004/02/18 17:11:56 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
@@ -570,35 +628,5 @@ bool NexusSet::intersect(const NexusSet&that) const
|
||||
* Revision 1.7 2002/06/24 01:49:39 steve
|
||||
* Make link_drive_constant cache its results in
|
||||
* the Nexus, to improve cprop performance.
|
||||
*
|
||||
* Revision 1.6 2002/04/21 04:59:08 steve
|
||||
* Add support for conbinational events by finding
|
||||
* the inputs to expressions and some statements.
|
||||
* Get case and assignment statements working.
|
||||
*
|
||||
* Revision 1.5 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.4 2000/10/06 23:46:50 steve
|
||||
* ivl_target updates, including more complete
|
||||
* handling of ivl_nexus_t objects. Much reduced
|
||||
* dependencies on pointers to netlist objects.
|
||||
*
|
||||
* Revision 1.3 2000/08/26 00:54:03 steve
|
||||
* Get at gate information for ivl_target interface.
|
||||
*
|
||||
* Revision 1.2 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.1 2000/06/25 19:59:42 steve
|
||||
* Redesign Links to include the Nexus class that
|
||||
* carries properties of the connected set of links.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
+35
-32
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000-2005 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2000-2004 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_modulo.cc,v 1.9 2005/09/15 22:54:47 steve Exp $"
|
||||
#ident "$Id: net_modulo.cc,v 1.7 2004/02/18 17:11:56 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -30,22 +30,25 @@
|
||||
# include "netlist.h"
|
||||
# include "compiler.h"
|
||||
|
||||
/*
|
||||
* 0 -- Result
|
||||
* 1 -- DataA
|
||||
* 2 -- DataB
|
||||
*/
|
||||
|
||||
NetModulo::NetModulo(NetScope*s, perm_string n, unsigned wr,
|
||||
unsigned wa, unsigned wb)
|
||||
: NetNode(s, n, 3),
|
||||
: NetNode(s, n, wr+wa+wb),
|
||||
width_r_(wr), width_a_(wa), width_b_(wb)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Result"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("DataA"), 0);
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
pin(2).set_name(perm_string::literal("DataB"), 0);
|
||||
unsigned p = 0;
|
||||
for (unsigned idx = 0 ; idx < width_r_ ; idx += 1, p += 1) {
|
||||
pin(p).set_dir(Link::OUTPUT);
|
||||
pin(p).set_name(perm_string::literal("Result"), idx);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < width_a_ ; idx += 1, p += 1) {
|
||||
pin(p).set_dir(Link::INPUT);
|
||||
pin(p).set_name(perm_string::literal("DataA"), idx);
|
||||
}
|
||||
for (unsigned idx = 0 ; idx < width_b_ ; idx += 1, p += 1) {
|
||||
pin(p).set_dir(Link::INPUT);
|
||||
pin(p).set_name(perm_string::literal("DataB"), idx);
|
||||
}
|
||||
}
|
||||
|
||||
NetModulo::~NetModulo()
|
||||
@@ -67,44 +70,44 @@ unsigned NetModulo::width_b() const
|
||||
return width_b_;
|
||||
}
|
||||
|
||||
Link& NetModulo::pin_Result()
|
||||
Link& NetModulo::pin_Result(unsigned idx)
|
||||
{
|
||||
return pin(0);
|
||||
assert(idx < width_r_);
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
const Link& NetModulo::pin_Result() const
|
||||
const Link& NetModulo::pin_Result(unsigned idx) const
|
||||
{
|
||||
return pin(0);
|
||||
assert(idx < width_r_);
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
Link& NetModulo::pin_DataA()
|
||||
Link& NetModulo::pin_DataA(unsigned idx)
|
||||
{
|
||||
return pin(1);
|
||||
assert(idx < width_a_);
|
||||
return pin(idx+width_r_);
|
||||
}
|
||||
|
||||
const Link& NetModulo::pin_DataA() const
|
||||
const Link& NetModulo::pin_DataA(unsigned idx) const
|
||||
{
|
||||
return pin(1);
|
||||
assert(idx < width_a_);
|
||||
return pin(idx+width_r_);
|
||||
}
|
||||
|
||||
Link& NetModulo::pin_DataB()
|
||||
Link& NetModulo::pin_DataB(unsigned idx)
|
||||
{
|
||||
return pin(2);
|
||||
assert(idx < width_b_);
|
||||
return pin(idx+width_r_+width_a_);
|
||||
}
|
||||
|
||||
const Link& NetModulo::pin_DataB() const
|
||||
const Link& NetModulo::pin_DataB(unsigned idx) const
|
||||
{
|
||||
return pin(2);
|
||||
assert(idx < width_b_);
|
||||
return pin(idx+width_r_+width_a_);
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: net_modulo.cc,v $
|
||||
* Revision 1.9 2005/09/15 22:54:47 steve
|
||||
* Fix bug configuring NetModulo pins.
|
||||
*
|
||||
* Revision 1.8 2005/03/12 06:43:35 steve
|
||||
* Update support for LPM_MOD.
|
||||
*
|
||||
* Revision 1.7 2004/02/18 17:11:56 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
|
||||
+29
-31
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_nex_input.cc,v 1.16 2007/01/16 05:44:15 steve Exp $"
|
||||
#ident "$Id: net_nex_input.cc,v 1.12.2.1 2006/05/21 21:58:47 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -54,6 +54,15 @@ NexusSet* NetEBinary::nex_input()
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetEBitSel::nex_input()
|
||||
{
|
||||
NexusSet*result = sig_->nex_input();
|
||||
NexusSet*tmp = idx_->nex_input();
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
return result;
|
||||
}
|
||||
|
||||
NexusSet* NetEConcat::nex_input()
|
||||
{
|
||||
NexusSet*result = parms_[0]->nex_input();
|
||||
@@ -78,6 +87,12 @@ NexusSet* NetECReal::nex_input()
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetEMemory::nex_input()
|
||||
{
|
||||
NexusSet*result = idx_->nex_input();
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* A parameter by definition has no inputs. It represents a constant
|
||||
* value, even if that value is a constant expression.
|
||||
@@ -123,7 +138,8 @@ NexusSet* NetESFunc::nex_input()
|
||||
NexusSet* NetESignal::nex_input()
|
||||
{
|
||||
NexusSet*result = new NexusSet;
|
||||
for (unsigned idx = 0 ; idx < net_->pin_count() ; idx += 1)
|
||||
assert(msi_ <= net_->pin_count());
|
||||
for (unsigned idx = lsi_ ; idx <= msi_ ; idx += 1)
|
||||
result->add(net_->pin(idx).nexus());
|
||||
|
||||
return result;
|
||||
@@ -162,21 +178,17 @@ NexusSet* NetEUnary::nex_input()
|
||||
return expr_->nex_input();
|
||||
}
|
||||
|
||||
NexusSet* NetEVariable::nex_input()
|
||||
{
|
||||
return new NexusSet;
|
||||
}
|
||||
|
||||
NexusSet* NetAssign_::nex_input()
|
||||
{
|
||||
NexusSet*result = new NexusSet;
|
||||
if (word_) {
|
||||
NexusSet*tmp = word_->nex_input();
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
if (base_) {
|
||||
NexusSet*tmp = base_->nex_input();
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
|
||||
return result;
|
||||
if (bmux_ == 0)
|
||||
return new NexusSet;
|
||||
else
|
||||
return bmux_->nex_input();
|
||||
}
|
||||
|
||||
NexusSet* NetAssignBase::nex_input()
|
||||
@@ -387,22 +399,8 @@ NexusSet* NetWhile::nex_input()
|
||||
|
||||
/*
|
||||
* $Log: net_nex_input.cc,v $
|
||||
* Revision 1.16 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.15 2006/04/16 00:15:43 steve
|
||||
* Fix part selects in l-values.
|
||||
*
|
||||
* Revision 1.14 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.13 2005/01/24 05:28:30 steve
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
* Revision 1.12.2.1 2006/05/21 21:58:47 steve
|
||||
* NetESignal input is only selected bits.
|
||||
*
|
||||
* Revision 1.12 2004/09/04 04:24:15 steve
|
||||
* PR1026: assignment statements can have sensitivities in the l-values.
|
||||
|
||||
+74
-24
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_nex_output.cc,v 1.14 2007/04/17 04:34:23 steve Exp $"
|
||||
#ident "$Id: net_nex_output.cc,v 1.11.2.8 2006/08/08 02:17:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -47,7 +47,55 @@ void NetAssignBase::nex_output(NexusSet&out)
|
||||
{
|
||||
for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) {
|
||||
if (NetNet*lsig = cur->sig()) {
|
||||
out.add(lsig->pin(0).nexus());
|
||||
|
||||
if (cur->bmux()) {
|
||||
for (unsigned idx = 0; idx < lsig->pin_count(); idx += 1) {
|
||||
out.add(lsig->pin(idx).nexus());
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Handle l-value signals. We don't need to worry
|
||||
here about whether there is a bmux, because the
|
||||
synthesizer will detect that mux and create a
|
||||
decoder between the expression and the signal. */
|
||||
for (unsigned idx = 0 ; idx < cur->lwidth() ; idx += 1) {
|
||||
unsigned off = cur->get_loff() + idx;
|
||||
out.add(lsig->pin(off).nexus());
|
||||
}
|
||||
|
||||
} else if (NetMemory*lmem = cur->mem()) {
|
||||
|
||||
/* Memories here are treated as a bunch of reg
|
||||
devices. Use the explode_to_reg method to get
|
||||
access to the FF version of the memory and use
|
||||
that in our l-value management. */
|
||||
NetNet*tmp = lmem->explode_to_reg();
|
||||
|
||||
if (NetEConst*ae = dynamic_cast<NetEConst*>(cur->bmux())) {
|
||||
/* The address is constant, so simply
|
||||
connect to the right pins and we are
|
||||
done. */
|
||||
long adr_s = ae->value().as_long();
|
||||
unsigned adr = lmem->index_to_address(adr_s) * lmem->width();
|
||||
|
||||
if (adr >= lmem->count()*lmem->width()) {
|
||||
/* Skip assignments with constant
|
||||
addresses that are outside the
|
||||
range of memories. */
|
||||
} else {
|
||||
for (unsigned idx=0; idx<cur->lwidth(); idx += 1)
|
||||
out.add(tmp->pin(adr+idx).nexus());
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Put all the bits of the memory into the
|
||||
set. The synthesis will generate a
|
||||
decoder to handle this. */
|
||||
for (unsigned idx = 0; idx < tmp->pin_count(); idx+=1)
|
||||
out.add(tmp->pin(idx).nexus());
|
||||
}
|
||||
|
||||
} else {
|
||||
/* Quoting from netlist.h comments for class NetMemory:
|
||||
* "This is not a node because memory objects can only be
|
||||
@@ -66,21 +114,17 @@ void NetBlock::nex_output(NexusSet&out)
|
||||
if (last_ == 0)
|
||||
return;
|
||||
|
||||
NetProc*cur = last_;
|
||||
NetProc*cur = last_->next_;
|
||||
do {
|
||||
cur = cur->next_;
|
||||
cur->nex_output(out);
|
||||
} while (cur != last_);
|
||||
cur = cur->next_;
|
||||
} while (cur != last_->next_);
|
||||
}
|
||||
|
||||
void NetCase::nex_output(NexusSet&out)
|
||||
{
|
||||
for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) {
|
||||
|
||||
// Empty statements clearly have no output.
|
||||
if (items_[idx].statement == 0)
|
||||
continue;
|
||||
|
||||
assert(items_[idx].statement);
|
||||
items_[idx].statement->nex_output(out);
|
||||
}
|
||||
@@ -115,15 +159,6 @@ void NetSTask::nex_output(NexusSet&out)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* Consider a task call to not have any outputs. This is not quite
|
||||
* right, we should be listing as outputs all the output ports, but for
|
||||
* the purposes that this method is used, this will do for now.
|
||||
*/
|
||||
void NetUTask::nex_output(NexusSet&out)
|
||||
{
|
||||
}
|
||||
|
||||
void NetWhile::nex_output(NexusSet&out)
|
||||
{
|
||||
if (proc_ != 0)
|
||||
@@ -132,14 +167,29 @@ void NetWhile::nex_output(NexusSet&out)
|
||||
|
||||
/*
|
||||
* $Log: net_nex_output.cc,v $
|
||||
* Revision 1.14 2007/04/17 04:34:23 steve
|
||||
* Fix handling calls to tasks in combinational always block
|
||||
* Revision 1.11.2.8 2006/08/08 02:17:48 steve
|
||||
* Improved nexus management performance.
|
||||
*
|
||||
* Revision 1.13 2007/04/05 01:53:52 steve
|
||||
* Probe of case statement inputs can skip nul statements.
|
||||
* Revision 1.11.2.7 2006/06/02 23:42:48 steve
|
||||
* Compilation warnings.
|
||||
*
|
||||
* Revision 1.12 2005/02/14 04:58:50 steve
|
||||
* l-value input may be a vector.
|
||||
* Revision 1.11.2.6 2006/06/01 03:01:48 steve
|
||||
* Handle condit clauses with unassigned outputs.
|
||||
*
|
||||
* Revision 1.11.2.5 2006/05/18 01:47:12 steve
|
||||
* Fix synthesis of l-value bit select in block.
|
||||
*
|
||||
* Revision 1.11.2.4 2006/05/05 01:56:36 steve
|
||||
* Handle memory assignments out of range during synthesis
|
||||
*
|
||||
* Revision 1.11.2.3 2006/04/16 19:26:38 steve
|
||||
* Fix handling of exploded memories with partial or missing resets.
|
||||
*
|
||||
* Revision 1.11.2.2 2006/03/12 07:34:17 steve
|
||||
* Fix the memsynth1 case.
|
||||
*
|
||||
* Revision 1.11.2.1 2006/01/18 01:23:23 steve
|
||||
* Rework l-value handling to allow for more l-value type flexibility.
|
||||
*
|
||||
* Revision 1.11 2004/09/16 03:17:33 steve
|
||||
* net_output handles l-value concatenations.
|
||||
|
||||
+3
-6
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_proc.cc,v 1.7 2006/08/08 05:11:37 steve Exp $"
|
||||
#ident "$Id: net_proc.cc,v 1.6 2002/08/12 01:34:59 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -131,7 +131,7 @@ NetForever::~NetForever()
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
NetPDelay::NetPDelay(uint64_t d, NetProc*st)
|
||||
NetPDelay::NetPDelay(unsigned long d, NetProc*st)
|
||||
: delay_(d), expr_(0), statement_(st)
|
||||
{
|
||||
}
|
||||
@@ -146,7 +146,7 @@ NetPDelay::~NetPDelay()
|
||||
if (expr_) delete expr_;
|
||||
}
|
||||
|
||||
uint64_t NetPDelay::delay() const
|
||||
unsigned long NetPDelay::delay() const
|
||||
{
|
||||
assert(expr_ == 0);
|
||||
return delay_;
|
||||
@@ -177,9 +177,6 @@ const NetExpr* NetRepeat::expr() const
|
||||
|
||||
/*
|
||||
* $Log: net_proc.cc,v $
|
||||
* Revision 1.7 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
* Revision 1.6 2002/08/12 01:34:59 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user