mirror of
https://github.com/steveicarus/iverilog.git
synced 2026-08-23 22:36:54 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
87e813766a | ||
|
|
e24e77660f | ||
|
|
8ec6d9983d | ||
|
|
ae82eccdc4 | ||
|
|
fa18d9bc01 | ||
|
|
16ec4cb685 | ||
|
|
6f08f92ffc | ||
|
|
0a38499941 | ||
|
|
55f8e5d364 | ||
|
|
b631268f56 | ||
|
|
1a8ffe2a9c | ||
|
|
e4bcc87dc1 | ||
|
|
34111a25cb | ||
|
|
8fd42fbf61 | ||
|
|
129a064e1a | ||
|
|
c7d97f4146 | ||
|
|
1f9a246c6d | ||
|
|
17fd3bae15 | ||
|
|
29aa68302e | ||
|
|
8dcd09797f | ||
|
|
ddd36ecb6c | ||
|
|
67b1eee7ce | ||
|
|
629c6e9a40 | ||
|
|
6ea1337be0 | ||
|
|
b981c81d37 | ||
|
|
210e28e571 | ||
|
|
f6ad90f8d3 | ||
|
|
890f592eec | ||
|
|
f9c1c02f8d | ||
|
|
26f47c26f0 | ||
|
|
c0496ea648 | ||
|
|
498d8fe6ad | ||
|
|
dafc653935 | ||
|
|
401faef5b8 | ||
|
|
22efa9f066 | ||
|
|
583abb7f49 | ||
|
|
fe65ae8db0 | ||
|
|
cc48a6c8d7 | ||
|
|
36471e9f96 | ||
|
|
427d5664ef | ||
|
|
253fdc6232 | ||
|
|
79fdb2b243 | ||
|
|
089bdefad1 | ||
|
|
8ed1a010f7 | ||
|
|
9931e4c013 | ||
|
|
acdb278b97 | ||
|
|
d3a54547aa | ||
|
|
f621448ced | ||
|
|
2229825783 | ||
|
|
fb7ce1d330 | ||
|
|
ff7625cd9c | ||
|
|
8f9738719b | ||
|
|
31914c7fcd | ||
|
|
abaeb1e702 | ||
|
|
513fa72d99 | ||
|
|
65baeaed8f | ||
|
|
fbc731d19e | ||
|
|
5047a3add3 | ||
|
|
d3588b4e23 | ||
|
|
33e5f22cf1 | ||
|
|
af913e7eb1 | ||
|
|
dd995b3409 | ||
|
|
a863b2390c | ||
|
|
c5524b4acf | ||
|
|
d883979fd8 | ||
|
|
37111eb4a8 | ||
|
|
bd1b00ca29 | ||
|
|
0168502bbb | ||
|
|
ea74940be4 | ||
|
|
8856c07d88 | ||
|
|
9e21880cdc | ||
|
|
fe8da0bf14 | ||
|
|
fe02214fcc | ||
|
|
611d2c81b3 | ||
|
|
96443f1338 | ||
|
|
32fb919b00 | ||
|
|
72ec3a2c09 | ||
|
|
a50ec29ad9 | ||
|
|
d9efe3312e | ||
|
|
29b4d5a46e | ||
|
|
f23a5bfa96 | ||
|
|
74ac5dbf58 | ||
|
|
ae88f5cc68 | ||
|
|
760f2182ba | ||
|
|
e6fa72c318 | ||
|
|
8c434ca6fa | ||
|
|
6f810e0dba | ||
|
|
b68f17483e | ||
|
|
606751dbfd | ||
|
|
fc9a90c9e0 | ||
|
|
b21390b228 | ||
|
|
1352eada12 | ||
|
|
243cf94165 | ||
|
|
e789b3a5cf | ||
|
|
bb02da0319 | ||
|
|
0946f40c7b | ||
|
|
80a2b05733 | ||
|
|
6804732b9e | ||
|
|
d6969b719a | ||
|
|
d2ba78559a | ||
|
|
1f54f128c1 | ||
|
|
2c32a81d91 | ||
|
|
cd5b1b111c | ||
|
|
9d4fc92df5 | ||
|
|
45307f6144 | ||
|
|
92c36f152d | ||
|
|
4f74d9df98 | ||
|
|
0137832003 | ||
|
|
189532c5bf | ||
|
|
7d2d87f7c6 | ||
|
|
521f66f040 | ||
|
|
c1c2381261 | ||
|
|
97234cb7ca | ||
|
|
3fd80b09f0 | ||
|
|
2b3acfb344 | ||
|
|
326329d497 | ||
|
|
d958a4a5af | ||
|
|
7d42c50253 | ||
|
|
6d91be5b19 | ||
|
|
d52f41535f | ||
|
|
a623502ece | ||
|
|
d22e9713f7 | ||
|
|
5869d7d879 | ||
|
|
074a6a44e3 | ||
|
|
85ceea7358 | ||
|
|
b2e1db6adb | ||
|
|
05efaa6427 | ||
|
|
cfe2198e5e | ||
|
|
d175eb17f1 | ||
|
|
2de8bafb5c | ||
|
|
8e1c7e2891 | ||
|
|
8ae6240947 | ||
|
|
f77d803aeb | ||
|
|
4b829bf04f | ||
|
|
17a508047b | ||
|
|
b350b14f93 | ||
|
|
ca9da51a79 | ||
|
|
98417cb03a | ||
|
|
f07257067a | ||
|
|
e4d7eda02a | ||
|
|
4d8164945e | ||
|
|
c0954349e4 | ||
|
|
e89b9fc25e | ||
|
|
11a83c352d | ||
|
|
d8d7673d27 | ||
|
|
6f3ddce7c4 | ||
|
|
f5a7ee0736 | ||
|
|
91d84e7dc7 |
@@ -17,6 +17,7 @@ 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 then what is included?" And
|
||||
invoke the error without any Verilog other than what is included?" And
|
||||
while we are at it, please place a copyright notice in your test
|
||||
program and include a GPL license statement if you can. Your test
|
||||
program may find its way into the test suite, and the notices will
|
||||
@@ -160,8 +160,11 @@ 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.4 2003/02/19 04:36:31 steve Exp $
|
||||
$Id: BUGS.txt,v 1.5 2007/03/22 16:08:14 steve Exp $
|
||||
$Log: BUGS.txt,v $
|
||||
Revision 1.5 2007/03/22 16:08:14 steve
|
||||
Spelling fixes from Larry
|
||||
|
||||
Revision 1.4 2003/02/19 04:36:31 steve
|
||||
Notes on hte bug database.
|
||||
|
||||
|
||||
@@ -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.5 2002/11/02 03:27:52 steve Exp $"
|
||||
#ident "$Id: HName.cc,v 1.8 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -29,235 +29,107 @@
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
|
||||
|
||||
hname_t::hname_t()
|
||||
{
|
||||
item_ = 0;
|
||||
count_ = 0;
|
||||
number_ = INT_MIN;
|
||||
}
|
||||
|
||||
hname_t::hname_t(const char*text)
|
||||
hname_t::hname_t(perm_string text)
|
||||
{
|
||||
item_ = strdup(text);
|
||||
count_ = 1;
|
||||
name_ = text;
|
||||
number_ = INT_MIN;
|
||||
}
|
||||
|
||||
hname_t::hname_t(perm_string text, int num)
|
||||
{
|
||||
name_ = text;
|
||||
number_ = num;
|
||||
}
|
||||
|
||||
hname_t::hname_t(const hname_t&that)
|
||||
{
|
||||
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;
|
||||
}
|
||||
name_ = that.name_;
|
||||
number_ = that.number_;
|
||||
}
|
||||
|
||||
hname_t& hname_t::operator = (const hname_t&that)
|
||||
{
|
||||
name_ = that.name_;
|
||||
number_ = that.number_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned hname_t::component_count() const
|
||||
perm_string hname_t::peek_name(void) const
|
||||
{
|
||||
return count_;
|
||||
return name_;
|
||||
}
|
||||
|
||||
void hname_t::append(const char*text)
|
||||
bool hname_t::has_number() const
|
||||
{
|
||||
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;
|
||||
}
|
||||
return number_ != INT_MIN;
|
||||
}
|
||||
|
||||
void hname_t::prepend(const char*text)
|
||||
int hname_t::peek_number() const
|
||||
{
|
||||
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];
|
||||
}
|
||||
return number_;
|
||||
}
|
||||
|
||||
bool operator < (const hname_t&l, const hname_t&r)
|
||||
{
|
||||
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)
|
||||
int cmp = strcmp(l.peek_name(), r.peek_name());
|
||||
if (cmp < 0) return true;
|
||||
if (cmp > 0) return false;
|
||||
if (l.has_number() && r.has_number())
|
||||
return l.peek_number() < r.peek_number();
|
||||
else
|
||||
return false;
|
||||
if (rc && !lc)
|
||||
return true;
|
||||
|
||||
// Must be ==
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator == (const hname_t&l, const hname_t&r)
|
||||
{
|
||||
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);
|
||||
if (l.peek_name() == r.peek_name()) {
|
||||
if (l.has_number() && r.has_number())
|
||||
return l.peek_number() == r.peek_number();
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
if (lc || rc)
|
||||
return false;
|
||||
|
||||
// Must be ==
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator != (const hname_t&l, const hname_t&r)
|
||||
{ return ! (l==r); }
|
||||
|
||||
ostream& operator<< (ostream&out, const hname_t&that)
|
||||
{
|
||||
switch (that.count_) {
|
||||
case 0:
|
||||
if (that.peek_name() == 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 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2001-2007 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -19,10 +19,11 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: HName.h,v 1.4 2002/11/02 03:27:51 steve Exp $"
|
||||
#ident "$Id: HName.h,v 1.7 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <iostream>
|
||||
# include "StringHeap.h"
|
||||
#ifdef __GNUC__
|
||||
#if __GNUC__ > 2
|
||||
using namespace std;
|
||||
@@ -30,59 +31,56 @@ using namespace std;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This class represents a Verilog hierarchical name. A hierarchical
|
||||
* name is an ordered list of simple names.
|
||||
* 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.
|
||||
*/
|
||||
|
||||
class hname_t {
|
||||
|
||||
public:
|
||||
hname_t ();
|
||||
explicit hname_t (const char*text);
|
||||
explicit hname_t (perm_string text);
|
||||
explicit hname_t (perm_string text, int num);
|
||||
hname_t (const hname_t&that);
|
||||
~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);
|
||||
hname_t& operator= (const hname_t&);
|
||||
|
||||
// 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);
|
||||
// Return the string part of the hname_t.
|
||||
perm_string peek_name(void) 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&);
|
||||
bool has_number() const;
|
||||
int peek_number() const;
|
||||
|
||||
private:
|
||||
union {
|
||||
char**array_;
|
||||
char* item_;
|
||||
};
|
||||
unsigned count_;
|
||||
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_;
|
||||
|
||||
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.
|
||||
|
||||
+12
-13
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.179 2006/10/30 22:45:36 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.181 2007/05/24 04:07:11 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -43,7 +43,6 @@ mandir = @mandir@
|
||||
libdir64 = @libdir64@
|
||||
|
||||
dllib=@DLLIB@
|
||||
strip_dynamic=@strip_dynamic@
|
||||
|
||||
CC = @CC@
|
||||
CXX = @CXX@
|
||||
@@ -51,7 +50,6 @@ INSTALL = @INSTALL@
|
||||
INSTALL_SCRIPT = @INSTALL_SCRIPT@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
INSTALL_DATA = @INSTALL_DATA@
|
||||
STRIP = @STRIP@
|
||||
LEX = @LEX@
|
||||
YACC = @YACC@
|
||||
|
||||
@@ -68,7 +66,7 @@ all: dep ivl@EXEEXT@
|
||||
|
||||
# In the windows world, the installer will need a dosify program to
|
||||
# dosify text files.
|
||||
ifeq (@WIN32@,yes)
|
||||
ifeq (@MING32@,yes)
|
||||
all: dep dosify.exe
|
||||
dosify.exe: dosify.c
|
||||
$(CC) -o dosify.exe dosify.c
|
||||
@@ -88,9 +86,9 @@ clean:
|
||||
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
|
||||
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 ivl@EXEEXT@
|
||||
rm -rf dep
|
||||
|
||||
distclean: clean
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
@@ -110,7 +108,7 @@ load_module.o netlist.o netmisc.o net_assign.o \
|
||||
net_design.o net_event.o net_expr.o net_force.o net_func.o \
|
||||
net_link.o net_modulo.o net_nex_input.o net_nex_output.o \
|
||||
net_proc.o net_scope.o net_udp.o pad_to_width.o \
|
||||
parse.o parse_misc.o pform.o pform_dump.o \
|
||||
parse.o parse_misc.o pform.o pform_dump.o pform_types.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 \
|
||||
@@ -131,11 +129,10 @@ 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) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@
|
||||
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ ivl.exp $O $(dllib) @EXTRALIBS@
|
||||
else
|
||||
ivl@EXEEXT@: $O
|
||||
$(CXX) $(LDFLAGS) -o ivl@EXEEXT@ $O $(dllib)
|
||||
|
||||
endif
|
||||
|
||||
ifeq (@MINGW32@,yes)
|
||||
@@ -145,6 +142,9 @@ 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@;' \
|
||||
@@ -185,7 +185,7 @@ iverilog-vpi.ps: $(srcdir)/iverilog-vpi.man
|
||||
iverilog-vpi.pdf: iverilog-vpi.ps
|
||||
ps2pdf iverilog-vpi.ps iverilog-vpi.pdf
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
ifeq (@MING32@,yes)
|
||||
INSTALL_DOC = $(prefix)/iverilog-vpi.pdf $(mandir)/man1/iverilog-vpi.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
all: dep iverilog-vpi.pdf
|
||||
@@ -212,7 +212,6 @@ $(bindir)/iverilog-vpi: ./iverilog-vpi
|
||||
|
||||
$(libdir)/ivl/ivl@EXEEXT@: ./ivl@EXEEXT@
|
||||
$(INSTALL_PROGRAM) ./ivl@EXEEXT@ $(libdir)/ivl/ivl@EXEEXT@
|
||||
$(STRIP) $(strip_dynamic) $(libdir)/ivl/ivl@EXEEXT@
|
||||
|
||||
$(libdir)/ivl/xnf-s.conf: $(srcdir)/xnf-s.conf
|
||||
$(INSTALL_DATA) $(srcdir)/xnf-s.conf $(libdir)/ivl/xnf-s.conf
|
||||
@@ -269,14 +268,14 @@ uninstall:
|
||||
for dir in $(SUBDIRS); do (cd $$dir ; $(MAKE) $@); done
|
||||
for dir in vpi ivlpp driver; \
|
||||
do (cd $$dir ; $(MAKE) $@); done
|
||||
for f in xnf.conf xnf-s.conf ivl; \
|
||||
for f in xnf.conf xnf-s.conf ivl@EXEEXT@; \
|
||||
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
|
||||
rm -f $(mandir)/man1/iverilog-vpi.1 $(prefix)/iverilog-vpi.pdf
|
||||
|
||||
|
||||
-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.25 2004/10/04 01:10:51 steve Exp $"
|
||||
#ident "$Id: Module.cc,v 1.27 2007/05/24 04:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -31,6 +31,7 @@
|
||||
Module::Module(perm_string n)
|
||||
: name_(n)
|
||||
{
|
||||
library_flag = false;
|
||||
default_nettype = NetNet::NONE;
|
||||
}
|
||||
|
||||
@@ -110,9 +111,9 @@ unsigned Module::find_port(const char*name) const
|
||||
}
|
||||
|
||||
|
||||
PWire* Module::get_wire(const hname_t&name) const
|
||||
PWire* Module::get_wire(const pform_name_t&name) const
|
||||
{
|
||||
map<hname_t,PWire*>::const_iterator obj = wires_.find(name);
|
||||
map<pform_name_t,PWire*>::const_iterator obj = wires_.find(name);
|
||||
if (obj == wires_.end())
|
||||
return 0;
|
||||
else
|
||||
@@ -132,11 +133,6 @@ 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_;
|
||||
@@ -150,6 +146,13 @@ 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.41 2006/09/23 04:57:19 steve Exp $"
|
||||
#ident "$Id: Module.h,v 1.43 2007/05/24 04:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
@@ -30,6 +30,7 @@
|
||||
# include "named.h"
|
||||
# include "LineInfo.h"
|
||||
# include "netlist.h"
|
||||
# include "pform_types.h"
|
||||
class PEvent;
|
||||
class PExpr;
|
||||
class PEIdent;
|
||||
@@ -68,6 +69,12 @@ 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
|
||||
@@ -92,7 +99,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<hname_t,PExpr*>defparms;
|
||||
map<pform_name_t,PExpr*>defparms;
|
||||
|
||||
/* Parameters may be overridden at instantiation time;
|
||||
the overrides do not contain explicit parameter names,
|
||||
@@ -144,10 +151,9 @@ class Module : public LineInfo {
|
||||
|
||||
// Find a wire by name. This is used for connecting gates to
|
||||
// existing wires, etc.
|
||||
PWire* get_wire(const hname_t&name) const;
|
||||
PWire* get_wire(const pform_name_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;
|
||||
|
||||
@@ -162,7 +168,7 @@ class Module : public LineInfo {
|
||||
private:
|
||||
perm_string name_;
|
||||
|
||||
map<hname_t,PWire*> wires_;
|
||||
map<pform_name_t,PWire*> wires_;
|
||||
list<PGate*> gates_;
|
||||
list<PProcess*> behaviors_;
|
||||
map<perm_string,PTask*> tasks_;
|
||||
@@ -176,6 +182,13 @@ 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.42 2007/04/19 02:52:53 steve
|
||||
* Add support for -v flag in command file.
|
||||
*
|
||||
* Revision 1.41 2006/09/23 04:57:19 steve
|
||||
* Basic support for specify timing.
|
||||
*
|
||||
|
||||
@@ -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.38 2006/10/30 05:44:49 steve Exp $"
|
||||
#ident "$Id: PExpr.cc,v 1.39 2007/05/24 04:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -93,13 +93,26 @@ PEBShift::~PEBShift()
|
||||
{
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(const hname_t&n, const svector<PExpr *> &parms)
|
||||
PECallFunction::PECallFunction(const pform_name_t&n, const svector<PExpr *> &parms)
|
||||
: path_(n), parms_(parms)
|
||||
{
|
||||
}
|
||||
|
||||
PECallFunction::PECallFunction(const hname_t&n)
|
||||
: path_(n)
|
||||
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))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -165,33 +178,32 @@ bool PEFNumber::is_constant(Module*) const
|
||||
return true;
|
||||
}
|
||||
|
||||
PEIdent::PEIdent(const hname_t&s)
|
||||
: path_(s), msb_(0), lsb_(0), sel_(SEL_NONE), idx_(0)
|
||||
PEIdent::PEIdent(const pform_name_t&that)
|
||||
: path_(that)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* 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));
|
||||
/* */
|
||||
perm_string tmp = path_.back().name;
|
||||
|
||||
{ map<perm_string,Module::param_expr_t>::const_iterator cur;
|
||||
cur = mod->parameters.find(tmp);
|
||||
@@ -288,6 +300,10 @@ 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.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PExpr.h,v 1.86 2006/11/10 04:54:26 steve Exp $"
|
||||
#ident "$Id: PExpr.h,v 1.90 2007/06/04 19:14:06 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -27,6 +27,7 @@
|
||||
# include "netlist.h"
|
||||
# include "verinum.h"
|
||||
# include "LineInfo.h"
|
||||
# include "pform_types.h"
|
||||
|
||||
class Design;
|
||||
class Module;
|
||||
@@ -124,7 +125,7 @@ class PExpr : public LineInfo {
|
||||
// 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(const Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
// This method returns true if that expression is the same as
|
||||
// this expression. This method is used for comparing
|
||||
@@ -150,7 +151,7 @@ class PEConcat : public PExpr {
|
||||
PEConcat(const svector<PExpr*>&p, PExpr*r =0);
|
||||
~PEConcat();
|
||||
|
||||
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
virtual NetNet* elaborate_lnet(Design*des, NetScope*scope,
|
||||
@@ -221,7 +222,7 @@ 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(const Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
/* A PEFNumber is a constant, so this returns true. */
|
||||
virtual bool is_constant(Module*) const;
|
||||
@@ -247,9 +248,14 @@ class PEFNumber : public PExpr {
|
||||
class PEIdent : public PExpr {
|
||||
|
||||
public:
|
||||
explicit PEIdent(const hname_t&s);
|
||||
explicit PEIdent(perm_string);
|
||||
explicit PEIdent(const pform_name_t&);
|
||||
~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,
|
||||
@@ -284,9 +290,12 @@ class PEIdent : public PExpr {
|
||||
NetNet* elaborate_port(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
verinum* eval_const(const Design*des, NetScope*sc) const;
|
||||
verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
const hname_t& path() const;
|
||||
const pform_name_t& path() const { return path_; }
|
||||
|
||||
private:
|
||||
pform_name_t path_;
|
||||
|
||||
private:
|
||||
// Common functions to calculate parts of part/bit selects.
|
||||
@@ -294,9 +303,10 @@ class PEIdent : public PExpr {
|
||||
bool calculate_up_do_width_(Design*, NetScope*, unsigned long&wid) const;
|
||||
|
||||
private:
|
||||
NetAssign_*elaborate_lval_net_part_(Design*, NetScope*, NetNet*) const;
|
||||
NetAssign_*elaborate_lval_net_idx_up_(Design*, NetScope*, NetNet*) const;
|
||||
NetAssign_*elaborate_lval_net_idx_do_(Design*, NetScope*, NetNet*) const;
|
||||
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,
|
||||
@@ -306,44 +316,41 @@ class PEIdent : public PExpr {
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const;
|
||||
NetExpr*elaborate_expr_net(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetScope*found) const;
|
||||
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,
|
||||
NetNet*net,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net_idx_up_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
NetExpr*elaborate_expr_net_bit_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*net,
|
||||
NetESignal*net,
|
||||
NetScope*found) const;
|
||||
hname_t path_;
|
||||
|
||||
public:
|
||||
// Use these to support part-select operators.
|
||||
PExpr*msb_;
|
||||
PExpr*lsb_;
|
||||
|
||||
enum { SEL_NONE, SEL_PART, SEL_IDX_UP, SEL_IDX_DO } sel_;
|
||||
|
||||
// If this is a reference to a memory/array, this is the index
|
||||
// expression. If this is a reference to a vector, this is a
|
||||
// bit select.
|
||||
std::vector<PExpr*> idx_;
|
||||
|
||||
NetNet* elaborate_net_ram_(Design*des, NetScope*scope,
|
||||
NetMemory*mem, unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const;
|
||||
NetNet* elaborate_net_array_(Design*des, NetScope*scope,
|
||||
NetNet*sig, unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
NetNet* elaborate_net_bitmux_(Design*des, NetScope*scope,
|
||||
NetNet*sig,
|
||||
@@ -354,9 +361,6 @@ class PEIdent : public PExpr {
|
||||
Link::strength_t drive1) const;
|
||||
|
||||
private:
|
||||
NetAssign_* elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
NetMemory*mem) const;
|
||||
|
||||
NetNet* elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
bool implicit_net_ok,
|
||||
bool bidirectional_flag) const;
|
||||
@@ -365,6 +369,7 @@ class PEIdent : public PExpr {
|
||||
|
||||
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;
|
||||
|
||||
};
|
||||
|
||||
@@ -395,7 +400,7 @@ class PENumber : public PExpr {
|
||||
NetScope*scope,
|
||||
bool is_force) const;
|
||||
|
||||
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_the_same(const PExpr*that) const;
|
||||
virtual bool is_constant(Module*) const;
|
||||
@@ -434,7 +439,7 @@ class PEString : public PExpr {
|
||||
virtual NetEConst*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool) const;
|
||||
virtual NetEConst*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
verinum* eval_const(const Design*, NetScope*) const;
|
||||
verinum* eval_const(Design*, NetScope*) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
@@ -460,7 +465,7 @@ class PEUnary : public PExpr {
|
||||
virtual NetExpr*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
virtual bool is_constant(Module*) const;
|
||||
|
||||
@@ -493,7 +498,7 @@ class PEBinary : public PExpr {
|
||||
virtual NetEBinary*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetExpr*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
protected:
|
||||
char op_;
|
||||
@@ -601,7 +606,7 @@ class PETernary : public PExpr {
|
||||
virtual NetETernary*elaborate_expr(Design*des, NetScope*,
|
||||
int expr_width, bool sys_task_arg) const;
|
||||
virtual NetETernary*elaborate_pexpr(Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(const Design*des, NetScope*sc) const;
|
||||
virtual verinum* eval_const(Design*des, NetScope*sc) const;
|
||||
|
||||
private:
|
||||
PExpr*expr_;
|
||||
@@ -616,8 +621,10 @@ class PETernary : public PExpr {
|
||||
*/
|
||||
class PECallFunction : public PExpr {
|
||||
public:
|
||||
explicit PECallFunction(const hname_t&n, const svector<PExpr *> &parms);
|
||||
explicit PECallFunction(const hname_t&n);
|
||||
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);
|
||||
~PECallFunction();
|
||||
|
||||
virtual void dump(ostream &) const;
|
||||
@@ -633,7 +640,7 @@ class PECallFunction : public PExpr {
|
||||
int expr_wid, bool sys_task_arg) const;
|
||||
|
||||
private:
|
||||
hname_t path_;
|
||||
pform_name_t path_;
|
||||
svector<PExpr *> parms_;
|
||||
|
||||
bool check_call_matches_definition_(Design*des, NetScope*dscope) const;
|
||||
@@ -650,6 +657,22 @@ class PECallFunction : public PExpr {
|
||||
|
||||
/*
|
||||
* $Log: PExpr.h,v $
|
||||
* Revision 1.90 2007/06/04 19:14:06 steve
|
||||
* Build errors in picky GCC 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.
|
||||
*
|
||||
|
||||
+9
-3
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PGenerate.cc,v 1.1 2006/04/10 02:40:18 steve Exp $"
|
||||
#ident "$Id: PGenerate.cc,v 1.4 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PGenerate.h"
|
||||
@@ -26,6 +26,7 @@
|
||||
PGenerate::PGenerate(unsigned id)
|
||||
: id_number(id)
|
||||
{
|
||||
parent = 0;
|
||||
}
|
||||
|
||||
PGenerate::~PGenerate()
|
||||
@@ -42,9 +43,9 @@ PWire* PGenerate::add_wire(PWire*wire)
|
||||
return wire;
|
||||
}
|
||||
|
||||
PWire* PGenerate::get_wire(const hname_t&name) const
|
||||
PWire* PGenerate::get_wire(const pform_name_t&name) const
|
||||
{
|
||||
map<hname_t,PWire*>::const_iterator obj = wires.find(name);
|
||||
map<pform_name_t,PWire*>::const_iterator obj = wires.find(name);
|
||||
if (obj == wires.end())
|
||||
return 0;
|
||||
else
|
||||
@@ -55,3 +56,8 @@ void PGenerate::add_gate(PGate*gate)
|
||||
{
|
||||
gates.push_back(gate);
|
||||
}
|
||||
|
||||
void PGenerate::add_behavior(PProcess*proc)
|
||||
{
|
||||
behaviors.push_back(proc);
|
||||
}
|
||||
|
||||
+12
-4
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PGenerate.h,v 1.1 2006/04/10 02:40:18 steve Exp $"
|
||||
#ident "$Id: PGenerate.h,v 1.4 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
@@ -27,10 +27,12 @@
|
||||
# include "HName.h"
|
||||
# include <list>
|
||||
# include <map>
|
||||
# include "pform_types.h"
|
||||
|
||||
class Design;
|
||||
class NetScope;
|
||||
class PExpr;
|
||||
class PProcess;
|
||||
class PGate;
|
||||
class PWire;
|
||||
|
||||
@@ -58,13 +60,19 @@ class PGenerate : public LineInfo {
|
||||
PExpr*loop_test;
|
||||
PExpr*loop_step;
|
||||
|
||||
map<hname_t,PWire*>wires;
|
||||
map<pform_name_t,PWire*>wires;
|
||||
PWire* add_wire(PWire*);
|
||||
PWire* get_wire(const hname_t&name) const;
|
||||
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.
|
||||
@@ -73,7 +81,7 @@ class PGenerate : public LineInfo {
|
||||
bool elaborate_sig(Design*des) const;
|
||||
bool elaborate(Design*des) const;
|
||||
|
||||
void dump(ostream&out) const;
|
||||
void dump(ostream&out, unsigned indent) const;
|
||||
|
||||
private:
|
||||
bool generate_scope_loop_(Design*des, NetScope*container);
|
||||
|
||||
@@ -17,13 +17,15 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PSpec.cc,v 1.1 2006/09/26 19:48:40 steve Exp $"
|
||||
#ident "$Id: PSpec.cc,v 1.2 2007/02/12 01:52:21 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "PSpec.h"
|
||||
|
||||
PSpecPath::PSpecPath(unsigned src_cnt, unsigned dst_cnt)
|
||||
: src(src_cnt), dst(dst_cnt)
|
||||
: conditional(false), condition(0), edge(0),
|
||||
src(src_cnt), dst(dst_cnt),
|
||||
data_source_expression(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -19,13 +19,37 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PSpec.h,v 1.1 2006/09/23 04:57:19 steve Exp $"
|
||||
#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:
|
||||
@@ -37,10 +61,17 @@ class PSpecPath : public LineInfo {
|
||||
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;
|
||||
};
|
||||
|
||||
@@ -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.13 2004/05/31 23:34:36 steve Exp $"
|
||||
#ident "$Id: PTask.h,v 1.14 2007/03/06 05:22:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "LineInfo.h"
|
||||
@@ -35,6 +35,7 @@ class PExpr;
|
||||
enum PTaskFuncEnum {
|
||||
PTF_NONE,
|
||||
PTF_REG,
|
||||
PTF_REG_S,
|
||||
PTF_INTEGER,
|
||||
PTF_REAL,
|
||||
PTF_REALTIME,
|
||||
@@ -117,6 +118,9 @@ 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 2004/05/31 23:34:36 steve
|
||||
* Rewire/generalize parsing an elaboration of
|
||||
* function return values to allow for better
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2007 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,29 +17,14 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PWire.cc,v 1.11 2005/07/07 16:22:49 steve Exp $"
|
||||
#ident "$Id: PWire.cc,v 1.14 2007/05/24 04:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "PWire.h"
|
||||
# include <assert.h>
|
||||
|
||||
PWire::PWire(const hname_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),
|
||||
lidx_(0), ridx_(0)
|
||||
{
|
||||
if (t == NetNet::INTEGER) {
|
||||
type_ = NetNet::REG;
|
||||
signed_ = true;
|
||||
isint_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
PWire::PWire(char*n,
|
||||
PWire::PWire(const pform_name_t&n,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt)
|
||||
@@ -59,7 +44,7 @@ NetNet::Type PWire::get_wire_type() const
|
||||
return type_;
|
||||
}
|
||||
|
||||
const hname_t& PWire::path() const
|
||||
const pform_name_t& PWire::path() const
|
||||
{
|
||||
return hname_;
|
||||
}
|
||||
@@ -154,13 +139,25 @@ 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.
|
||||
*
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#ifndef __PWire_H
|
||||
#define __PWire_H
|
||||
/*
|
||||
* Copyright (c) 1998-2000 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1998-2007 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -19,13 +19,14 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: PWire.h,v 1.19 2006/04/10 00:37:42 steve Exp $"
|
||||
#ident "$Id: PWire.h,v 1.21 2007/05/24 04:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
# include "LineInfo.h"
|
||||
# include <map>
|
||||
# include "svector.h"
|
||||
# include "StringHeap.h"
|
||||
|
||||
#ifdef HAVE_IOSFWD
|
||||
# include <iosfwd>
|
||||
@@ -42,24 +43,21 @@ class Design;
|
||||
* identifies a port by keeping it in its port list.
|
||||
*
|
||||
* The hname parameter to the constructor is a hierarchical name. It
|
||||
* 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.
|
||||
* is the name of the wire within a module, so does not include the
|
||||
* current scope or any instances. Modules contain all the wires, so
|
||||
* from that perspective, sub-scopes within the module are a part of
|
||||
* the wire name.
|
||||
*/
|
||||
class PWire : public LineInfo {
|
||||
|
||||
public:
|
||||
PWire(const hname_t&hname,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt);
|
||||
PWire(char*name,
|
||||
PWire(const pform_name_t&hname,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt);
|
||||
|
||||
// Return a hierarchical name.
|
||||
const hname_t&path() const;
|
||||
const pform_name_t&path() const;
|
||||
|
||||
NetNet::Type get_wire_type() const;
|
||||
bool set_wire_type(NetNet::Type);
|
||||
@@ -83,10 +81,10 @@ class PWire : public LineInfo {
|
||||
// Write myself to the specified stream.
|
||||
void dump(ostream&out, unsigned ind=4) const;
|
||||
|
||||
void elaborate_sig(Design*, NetScope*scope) const;
|
||||
NetNet* elaborate_sig(Design*, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
hname_t hname_;
|
||||
pform_name_t hname_;
|
||||
NetNet::Type type_;
|
||||
NetNet::PortType port_type_;
|
||||
ivl_variable_type_t data_type_;
|
||||
@@ -110,6 +108,13 @@ 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.
|
||||
*
|
||||
@@ -146,40 +151,5 @@ 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
|
||||
|
||||
+15
-5
@@ -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.29 2004/02/18 17:11:54 steve Exp $"
|
||||
#ident "$Id: Statement.cc,v 1.30 2007/05/24 04:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -107,16 +107,22 @@ PBlock::~PBlock()
|
||||
delete list_[idx];
|
||||
}
|
||||
|
||||
PCallTask::PCallTask(const hname_t&n, const svector<PExpr*>&p)
|
||||
PCallTask::PCallTask(const pform_name_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 hname_t& PCallTask::path() const
|
||||
const pform_name_t& PCallTask::path() const
|
||||
{
|
||||
return path_;
|
||||
}
|
||||
@@ -178,7 +184,7 @@ PDelayStatement::~PDelayStatement()
|
||||
{
|
||||
}
|
||||
|
||||
PDisable::PDisable(const hname_t&sc)
|
||||
PDisable::PDisable(const pform_name_t&sc)
|
||||
: scope_(sc)
|
||||
{
|
||||
}
|
||||
@@ -273,7 +279,7 @@ PRepeat::~PRepeat()
|
||||
delete statement_;
|
||||
}
|
||||
|
||||
PTrigger::PTrigger(const hname_t&e)
|
||||
PTrigger::PTrigger(const pform_name_t&e)
|
||||
: event_(e)
|
||||
{
|
||||
}
|
||||
@@ -295,6 +301,10 @@ 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.
|
||||
*
|
||||
|
||||
+18
-8
@@ -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.42 2005/12/05 21:21:18 steve Exp $"
|
||||
#ident "$Id: Statement.h,v 1.44 2007/05/24 04:07:11 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <string>
|
||||
@@ -55,6 +55,8 @@ class PProcess : public LineInfo {
|
||||
|
||||
virtual ~PProcess();
|
||||
|
||||
bool elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
Type type() const { return type_; }
|
||||
Statement*statement() { return statement_; }
|
||||
|
||||
@@ -171,10 +173,11 @@ class PBlock : public Statement {
|
||||
class PCallTask : public Statement {
|
||||
|
||||
public:
|
||||
explicit PCallTask(const hname_t&n, const svector<PExpr*>&parms);
|
||||
explicit PCallTask(const pform_name_t&n, const svector<PExpr*>&parms);
|
||||
explicit PCallTask(perm_string n, const svector<PExpr*>&parms);
|
||||
~PCallTask();
|
||||
|
||||
const hname_t& path() const;
|
||||
const pform_name_t& path() const;
|
||||
|
||||
unsigned nparms() const { return parms_.count(); }
|
||||
|
||||
@@ -195,7 +198,7 @@ class PCallTask : public Statement {
|
||||
NetProc* elaborate_sys(Design*des, NetScope*scope) const;
|
||||
NetProc* elaborate_usr(Design*des, NetScope*scope) const;
|
||||
|
||||
hname_t path_;
|
||||
pform_name_t path_;
|
||||
svector<PExpr*> parms_;
|
||||
};
|
||||
|
||||
@@ -294,14 +297,14 @@ class PDelayStatement : public Statement {
|
||||
class PDisable : public Statement {
|
||||
|
||||
public:
|
||||
explicit PDisable(const hname_t&sc);
|
||||
explicit PDisable(const pform_name_t&sc);
|
||||
~PDisable();
|
||||
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
|
||||
private:
|
||||
hname_t scope_;
|
||||
pform_name_t scope_;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -431,14 +434,14 @@ class PRelease : public Statement {
|
||||
class PTrigger : public Statement {
|
||||
|
||||
public:
|
||||
explicit PTrigger(const hname_t&ev);
|
||||
explicit PTrigger(const pform_name_t&ev);
|
||||
~PTrigger();
|
||||
|
||||
virtual NetProc* elaborate(Design*des, NetScope*scope) const;
|
||||
virtual void dump(ostream&out, unsigned ind) const;
|
||||
|
||||
private:
|
||||
hname_t event_;
|
||||
pform_name_t event_;
|
||||
};
|
||||
|
||||
class PWhile : public Statement {
|
||||
@@ -458,6 +461,13 @@ 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.
|
||||
*
|
||||
|
||||
+6
-3
@@ -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.7 2003/11/12 02:38:44 steve Exp $"
|
||||
#ident "$Id: _pli_types.h.in,v 1.8 2007/06/05 21:32:30 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 signed char PLI_BYTE8;
|
||||
typedef char PLI_BYTE8;
|
||||
typedef unsigned char PLI_UBYTE8;
|
||||
|
||||
# define PLI_UINT64_FMT PRIu64
|
||||
@@ -84,12 +84,15 @@ typedef signed int PLI_INT32;
|
||||
typedef unsigned int PLI_UINT32;
|
||||
typedef signed short PLI_INT16;
|
||||
typedef unsigned short PLI_UINT16;
|
||||
typedef signed char PLI_BYTE8;
|
||||
typedef char PLI_BYTE8;
|
||||
typedef unsigned char PLI_UBYTE8;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $Log: _pli_types.h.in,v $
|
||||
* Revision 1.8 2007/06/05 21:32:30 steve
|
||||
* More standard PLI_BYTE8.
|
||||
*
|
||||
* Revision 1.7 2003/11/12 02:38:44 steve
|
||||
* Clean up manual definitions of PLI_UINT64_FMT.
|
||||
*
|
||||
|
||||
Vendored
+3
-3
@@ -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.6 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: aclocal.m4,v 1.7 2007/05/16 23:59:12 steve Exp $"
|
||||
],[while (0) {}],
|
||||
[AS_VAR_SET(ax_cv_cpp_ident, yes)],
|
||||
[AS_VAR_SET(ax_cv_cpp_ident, no)])])
|
||||
@@ -48,7 +48,7 @@ AC_DEFUN([AX_C_UNDERSCORES_LEADING],
|
||||
[AS_VAR_SET(ax_cv_c_underscores_leading, yes)],
|
||||
[AS_VAR_SET(ax_cv_c_underscores_leading, no)])])
|
||||
if test $ax_cv_c_underscores_leading = yes -a "$CYGWIN" != "yes" -a "$MINGW32" != "yes"; then
|
||||
AC_DEFINE(NEED_LU)
|
||||
AC_DEFINE([NEED_LU], [1], [Symbol names in object files produced by C compiler have leading underscores.])
|
||||
fi
|
||||
])# AX_C_UNDERSCORES_LEADING
|
||||
|
||||
@@ -63,7 +63,7 @@ AC_DEFUN([AX_C_UNDERSCORES_TRAILING],
|
||||
[AS_VAR_SET(ax_cv_c_underscores_trailing, yes)],
|
||||
[AS_VAR_SET(ax_cv_c_underscores_trailing, no)])])
|
||||
if test $ax_cv_c_underscores_trailing = yes; then
|
||||
AC_DEFINE(NEED_TU)
|
||||
AC_DEFINE([NEED_TU], [1], [Symbol names in object files produced by C compiler have trailing underscores.])
|
||||
fi
|
||||
])# AX_C_UNDERSCORES_TRAILING
|
||||
|
||||
|
||||
+2
-5
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.12 2006/02/15 18:42:42 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.13 2007/02/06 05:07:31 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -35,8 +35,6 @@ includedir = $(prefix)/include
|
||||
|
||||
vpidir = @libdir@/ivl/@vpidir1@
|
||||
|
||||
strip_dynamic=@strip_dynamic@
|
||||
|
||||
CC = @CC@
|
||||
INSTALL = @INSTALL@
|
||||
INSTALL_PROGRAM = @INSTALL_PROGRAM@
|
||||
@@ -45,7 +43,6 @@ INSTALL_DATA = @INSTALL_DATA@
|
||||
CPPFLAGS = @ident_support@ -I$(srcdir) -I$(srcdir)/.. -I.. @CPPFLAGS@ @DEFS@ @PICFLAG@
|
||||
CFLAGS = -Wall @CFLAGS@
|
||||
LDFLAGS = @LDFLAGS@
|
||||
STRIP = @STRIP@
|
||||
|
||||
SHARED = @shared@
|
||||
|
||||
@@ -74,7 +71,7 @@ dep:
|
||||
O = cadpli.o
|
||||
|
||||
SYSTEM_VPI_LDFLAGS = -L../vvp -lvpi
|
||||
ifeq (@WIN32@,yes)
|
||||
ifeq (@MING32@,yes)
|
||||
SYSTEM_VPI_LDFLAGS += @EXTRALIBS@
|
||||
endif
|
||||
|
||||
|
||||
+1
-1
@@ -37,7 +37,7 @@ AC_SUBST(DLLIB)
|
||||
|
||||
AX_CPP_PRECOMP
|
||||
|
||||
# Compiler option for position independent code, needed whan making shared objects.
|
||||
# Compiler option for position independent code, needed when making shared objects.
|
||||
AX_C_PICFLAG
|
||||
|
||||
# Linker option used when compiling the target
|
||||
|
||||
+17
-7
@@ -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.31 2006/09/28 04:35:18 steve Exp $"
|
||||
#ident "$Id: compiler.h,v 1.33 2007/04/19 02:52:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <list>
|
||||
@@ -32,11 +32,8 @@
|
||||
*/
|
||||
|
||||
|
||||
/* 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 integer_width is the width of integer variables. */
|
||||
extern unsigned integer_width;
|
||||
|
||||
/* The TIME_WIDTH is the width of time variables. */
|
||||
#ifndef TIME_WIDTH
|
||||
@@ -120,13 +117,20 @@ 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.
|
||||
@@ -148,6 +152,12 @@ 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.32 2007/03/07 04:24:59 steve
|
||||
* Make integer width controllable.
|
||||
*
|
||||
* Revision 1.31 2006/09/28 04:35:18 steve
|
||||
* Support selective control of specify and xtypes features.
|
||||
*
|
||||
|
||||
+9
-1
@@ -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.11 2004/10/04 01:10:52 steve Exp $"
|
||||
#ident "$Id: config.h.in,v 1.12 2007/02/02 04:33:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
@@ -37,6 +37,7 @@
|
||||
# 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
|
||||
@@ -48,8 +49,15 @@
|
||||
# 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.
|
||||
*
|
||||
|
||||
+2
-2
@@ -66,7 +66,7 @@ AC_TRY_LINK(
|
||||
#include <sys/times.h>
|
||||
,{clock_t a = times(0)/sysconf(_SC_CLK_TCK);},
|
||||
do_times=yes
|
||||
AC_DEFINE(HAVE_TIMES,1),
|
||||
AC_DEFINE([HAVE_TIMES], [1], [The times system call is available in the host operating system.]),
|
||||
do_times=no
|
||||
)
|
||||
AC_MSG_RESULT($do_times)
|
||||
@@ -93,7 +93,7 @@ AC_C_BIGENDIAN
|
||||
|
||||
AX_LD_EXTRALIBS
|
||||
|
||||
# Compiler option for position independent code, needed whan making shared objects.
|
||||
# Compiler option for position independent code, needed when making shared objects.
|
||||
# CFLAGS inherited by cadpli/Makefile?
|
||||
AX_C_PICFLAG
|
||||
|
||||
|
||||
@@ -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.55 2006/05/24 04:32:57 steve Exp $"
|
||||
#ident "$Id: cprop.cc,v 1.56 2007/03/07 00:38:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -215,7 +215,9 @@ void cprop_functor::lpm_ff(Design*des, NetFF*obj)
|
||||
|
||||
void cprop_functor::lpm_logic(Design*des, NetLogic*obj)
|
||||
{
|
||||
#if 0
|
||||
NetScope*scope = obj->scope();
|
||||
#endif
|
||||
|
||||
switch (obj->type()) {
|
||||
#if 0
|
||||
@@ -948,6 +950,9 @@ void cprop(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: cprop.cc,v $
|
||||
* Revision 1.56 2007/03/07 00:38:15 steve
|
||||
* Lint fixes.
|
||||
*
|
||||
* Revision 1.55 2006/05/24 04:32:57 steve
|
||||
* Fix handling of ternary-to-bufif0 constant propagation.
|
||||
*
|
||||
|
||||
+89
-76
@@ -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.171 2006/10/30 05:44:49 steve Exp $"
|
||||
#ident "$Id: design_dump.cc,v 1.176 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -30,6 +30,7 @@
|
||||
# include <iomanip>
|
||||
# include "netlist.h"
|
||||
# include "compiler.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
static ostream& operator<< (ostream&o, NetBlock::Type t)
|
||||
{
|
||||
@@ -90,9 +91,31 @@ ostream& operator << (ostream&o, ivl_variable_type_t val)
|
||||
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 src "
|
||||
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]
|
||||
@@ -112,8 +135,8 @@ void NetDelaySrc::dump(ostream&o, unsigned ind) const
|
||||
/* Dump a net. This can be a wire or register. */
|
||||
void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << type() << ": " << name() << "[" <<
|
||||
pin_count() << "]";
|
||||
o << setw(ind) << "" << type() << ": " << name()
|
||||
<< "[" << s0_ << ":" << e0_ << " count=" << pin_count() << "]";
|
||||
if (local_flag_)
|
||||
o << " (local)";
|
||||
o << " " << data_type_;
|
||||
@@ -137,7 +160,7 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||
}
|
||||
o << " (eref=" << peek_eref() << ", lref=" << peek_lref() << ")";
|
||||
if (scope())
|
||||
o << " scope=" << scope()->name();
|
||||
o << " scope=" << scope_path(scope());
|
||||
o << " #(" << rise_time() << "," << fall_time() << ","
|
||||
<< decay_time() << ") vector_width=" << vector_width()
|
||||
<< " pin_count=" << pin_count()
|
||||
@@ -167,13 +190,6 @@ void NetNet::dump_net(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
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. */
|
||||
@@ -239,6 +255,15 @@ void NetAddSub::dump_node(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetArrayDq::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetArrayDq: " << name()
|
||||
<< " array=" << mem_->name()
|
||||
<< endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetCLShift::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Combinatorial shift (NetCLShift): " <<
|
||||
@@ -258,7 +283,7 @@ void NetConcat::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetConcat: "
|
||||
<< name()
|
||||
<< " scope=" << (scope()? scope()->name() : "")
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< " width=" << width_ << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
@@ -282,7 +307,7 @@ void NetMux::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "Multiplexer (NetMux): " << name()
|
||||
<< " width=" << width_ << " swidth=" << swidth_ << " size=" << size_
|
||||
<< " scope=" << scope()->name() << endl;
|
||||
<< " scope=" << scope_path(scope()) << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
@@ -290,7 +315,7 @@ 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()? scope()->name() : "")
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< " delay=(" << rise_time() << "," << fall_time() << "," <<
|
||||
decay_time() << ") width=" << width() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
@@ -318,7 +343,7 @@ 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()? scope()->name() : "")
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< " aset_value=" << aset_value_ << endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
@@ -393,7 +418,7 @@ void NetLogic::dump_node(ostream&o, unsigned ind) const
|
||||
}
|
||||
o << " #(" << rise_time()
|
||||
<< "," << fall_time() << "," << decay_time() << ") " << name()
|
||||
<< " scope=" << (scope()? scope()->name() : "")
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
@@ -427,14 +452,6 @@ void NetPartSelect::dump_node(ostream&o, unsigned ind) const
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetRamDq::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "LPM_RAM_DQ (" << mem_->name() << "): "
|
||||
<< name() << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
|
||||
void NetReplicate::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "NetReplicate: "
|
||||
@@ -480,7 +497,7 @@ void NetUReduce::dump_node(ostream&o, unsigned ind) const
|
||||
}
|
||||
o << " #(" << rise_time()
|
||||
<< "," << fall_time() << "," << decay_time() << ") " << name()
|
||||
<< " scope=" << (scope()? scope()->name() : "")
|
||||
<< " scope=" << scope_path(scope())
|
||||
<< endl;
|
||||
|
||||
dump_node_pins(o, ind+4);
|
||||
@@ -496,7 +513,7 @@ void NetSysFunc::dump_node(ostream&o, unsigned ind) const
|
||||
|
||||
void NetUserFunc::dump_node(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << def_->name() << "(";
|
||||
o << setw(ind) << "" << scope_path(def_) << "(";
|
||||
o << ")" << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
@@ -504,7 +521,7 @@ void NetUserFunc::dump_node(ostream&o, unsigned ind) const
|
||||
|
||||
void NetTaskDef::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "task " << name_ << ";" << endl;
|
||||
o << setw(ind) << "" << "task " << scope_path(scope_) << ";" << endl;
|
||||
|
||||
for (unsigned idx = 0 ; idx < ports_.count() ; idx += 1) {
|
||||
o << setw(ind+4) << "";
|
||||
@@ -546,11 +563,11 @@ void NetProcTop::dump(ostream&o, unsigned ind) const
|
||||
switch (type_) {
|
||||
case NetProcTop::KINITIAL:
|
||||
o << "initial /* " << get_line() << " in "
|
||||
<< scope_->name() << " */" << endl;
|
||||
<< scope_path(scope_) << " */" << endl;
|
||||
break;
|
||||
case NetProcTop::KALWAYS:
|
||||
o << "always /* " << get_line() << " in "
|
||||
<< scope_->name() << " */" << endl;
|
||||
<< scope_path(scope_) << " */" << endl;
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -566,21 +583,9 @@ void NetAssign_::dump_lval(ostream&o) const
|
||||
{
|
||||
if (sig_) {
|
||||
o << sig_->name();
|
||||
if (bmux_) {
|
||||
o << "[" << *bmux_ << "]";
|
||||
|
||||
} else if (base_) {
|
||||
o << "[" << *base_ << " +: " << lwid_ << "]";
|
||||
if (word_) {
|
||||
o << "[word=" << *word_ << "]";
|
||||
}
|
||||
} 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 << "]";
|
||||
|
||||
if (base_) {
|
||||
o << "[" << *base_ << " +: " << lwid_ << "]";
|
||||
}
|
||||
@@ -644,7 +649,7 @@ void NetBlock::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << type_;
|
||||
if (subscope_)
|
||||
o << " : " << subscope_->name();
|
||||
o << " : " << scope_path(subscope_);
|
||||
o << endl;
|
||||
|
||||
if (last_) {
|
||||
@@ -721,7 +726,7 @@ void NetDeassign::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetDisable::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "disable " << target_->name() << "; "
|
||||
o << setw(ind) << "" << "disable " << scope_path(target_) << "; "
|
||||
<< "/* " << get_line() << " */" << endl;
|
||||
}
|
||||
|
||||
@@ -740,7 +745,7 @@ void NetEvProbe::dump_node(ostream&o, unsigned ind) const
|
||||
o << "negedge ";
|
||||
break;
|
||||
}
|
||||
o << setw(ind) << "" << "-> " << event_->full_name() << "; " << endl;
|
||||
o << setw(ind) << "" << "-> " << event_->name() << "; " << endl;
|
||||
dump_node_pins(o, ind+4);
|
||||
dump_obj_attr(o, ind+4);
|
||||
}
|
||||
@@ -753,11 +758,13 @@ void NetEvTrig::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetEvWait::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
assert(nevents() > 0);
|
||||
o << setw(ind) <<"" << "@(" << event(0)->full_name();
|
||||
o << setw(ind) <<"" << "@(";
|
||||
|
||||
if (nevents() > 0)
|
||||
o << event(0)->name();
|
||||
|
||||
for (unsigned idx = 1 ; idx < nevents() ; idx += 1)
|
||||
o << " or " << event(idx)->full_name();
|
||||
o << " or " << event(idx)->name();
|
||||
|
||||
o << ") // " << get_line() << endl;
|
||||
|
||||
@@ -782,7 +789,7 @@ void NetForever::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetFuncDef::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << "function " << scope_->name() << endl;
|
||||
o << setw(ind) << "" << "function " << scope_path(scope_) << endl;
|
||||
if (result_sig_)
|
||||
o << setw(ind+2) << "" << "Return signal: "
|
||||
<< result_sig_->name() << endl;
|
||||
@@ -825,7 +832,7 @@ void NetRepeat::dump(ostream&o, unsigned ind) const
|
||||
void NetScope::dump(ostream&o) const
|
||||
{
|
||||
/* This is a constructed hierarchical name. */
|
||||
o << name();
|
||||
o << scope_path(this);
|
||||
|
||||
switch (type_) {
|
||||
case BEGIN_END:
|
||||
@@ -883,7 +890,7 @@ void NetScope::dump(ostream&o) const
|
||||
|
||||
/* Dump the saved defparam assignments here. */
|
||||
{
|
||||
map<hname_t,NetExpr*>::const_iterator pp;
|
||||
map<pform_name_t,NetExpr*>::const_iterator pp;
|
||||
for (pp = defparams.begin()
|
||||
; pp != defparams.end() ; pp ++ ) {
|
||||
o << " defparam " << (*pp).first << " = " <<
|
||||
@@ -894,7 +901,8 @@ void NetScope::dump(ostream&o) const
|
||||
/* Dump the events in this scope. */
|
||||
for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) {
|
||||
o << " event " << cur->name() << "; nprobe="
|
||||
<< cur->nprobe() << " // " << cur->get_line() << endl;
|
||||
<< cur->nprobe() << " scope=" << scope_path(cur->scope())
|
||||
<< " // " << cur->get_line() << endl;
|
||||
}
|
||||
|
||||
// Dump the signals,
|
||||
@@ -906,15 +914,6 @@ void NetScope::dump(ostream&o) const
|
||||
} while (cur != signals_->sig_next_);
|
||||
}
|
||||
|
||||
// Dump the memories,
|
||||
if (memories_) {
|
||||
NetMemory*cur = memories_->snext_;
|
||||
do {
|
||||
cur->dump(o, 4);
|
||||
cur = cur->snext_;
|
||||
} while (cur != memories_->snext_);
|
||||
}
|
||||
|
||||
// Dump specparams
|
||||
typedef map<perm_string,spec_val_t>::const_iterator specparam_it_t;
|
||||
for (specparam_it_t cur = specparams.begin()
|
||||
@@ -977,7 +976,7 @@ void NetSTask::dump(ostream&o, unsigned ind) const
|
||||
|
||||
void NetUTask::dump(ostream&o, unsigned ind) const
|
||||
{
|
||||
o << setw(ind) << "" << task_->name() << ";" << endl;
|
||||
o << setw(ind) << "" << scope_path(task_) << ";" << endl;
|
||||
}
|
||||
|
||||
void NetWhile::dump(ostream&o, unsigned ind) const
|
||||
@@ -1112,7 +1111,7 @@ void NetEEvent::dump(ostream&o) const
|
||||
|
||||
void NetEScope::dump(ostream&o) const
|
||||
{
|
||||
o << "<scope=" << scope_->name() << ">";
|
||||
o << "<scope=" << scope_path(scope_) << ">";
|
||||
}
|
||||
|
||||
void NetESelect::dump(ostream&o) const
|
||||
@@ -1148,24 +1147,19 @@ void NetESignal::dump(ostream&o) const
|
||||
{
|
||||
if (has_sign())
|
||||
o << "+";
|
||||
o << name() << "[" << msi()<<":"<<lsi() << "]";
|
||||
}
|
||||
|
||||
void NetEMemory::dump(ostream&o) const
|
||||
{
|
||||
o << mem_->name() << "[";
|
||||
if (idx_) idx_->dump(o);
|
||||
o << "]";
|
||||
o << name();
|
||||
if (word_) o << "[word=" << *word_ << "]";
|
||||
o << "[" << msi()<<":"<<lsi() << "]";
|
||||
}
|
||||
|
||||
void NetEParam::dump(ostream&o) const
|
||||
{
|
||||
if (scope_ != 0)
|
||||
o << "<" << scope_->name() << "." << name_ << ">";
|
||||
o << "<" << scope_path(scope_) << "." << name_ << ">";
|
||||
else if (name_)
|
||||
o << "<" << name_ << ">";
|
||||
else
|
||||
o << "<???>";
|
||||
o << "<" "???" ">";
|
||||
}
|
||||
|
||||
void NetETernary::dump(ostream&o) const
|
||||
@@ -1176,7 +1170,7 @@ void NetETernary::dump(ostream&o) const
|
||||
|
||||
void NetEUFunc::dump(ostream&o) const
|
||||
{
|
||||
o << name() << "(";
|
||||
o << func_->basename() << "(";
|
||||
if (parms_.count() > 0) {
|
||||
parms_[0]->dump(o);
|
||||
for (unsigned idx = 1 ; idx < parms_.count() ; idx += 1) {
|
||||
@@ -1231,6 +1225,25 @@ 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.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.174 2007/03/02 06:13:22 steve
|
||||
* Add support for edge sensitive spec paths.
|
||||
*
|
||||
* Revision 1.173 2007/02/01 03:14:33 steve
|
||||
* Detect and report arrays without index in net contexts.
|
||||
*
|
||||
* 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.171 2006/10/30 05:44:49 steve
|
||||
* Expression widths with unsized literals are pseudo-infinite width.
|
||||
*
|
||||
|
||||
+3
-3
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.25 2006/10/30 22:45:37 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.26 2007/02/06 05:07:31 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -80,7 +80,7 @@ iverilog.ps: $(srcdir)/iverilog.man
|
||||
iverilog.pdf: iverilog.ps
|
||||
ps2pdf iverilog.ps iverilog.pdf
|
||||
|
||||
ifeq (@WIN32@,yes)
|
||||
ifeq (@MING32@,yes)
|
||||
INSTALL_DOC = $(prefix)/iverilog.pdf $(mandir)/man1/iverilog.1
|
||||
INSTALL_DOCDIR = $(mandir)/man1
|
||||
all: iverilog.pdf
|
||||
@@ -105,4 +105,4 @@ installdirs: ../mkinstalldirs
|
||||
|
||||
uninstall:
|
||||
rm -f $(bindir)/iverilog@EXEEXT@
|
||||
rm -f $(mandir)/man1/iverilog.1
|
||||
rm -f $(mandir)/man1/iverilog.1 $(prefix)/iverilog.pdf
|
||||
|
||||
+3
-2
@@ -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.9 2006/11/30 06:00:28 steve Exp $"
|
||||
#ident "$Id: cflexor.lex,v 1.11 2007/03/22 16:08:18 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "cfparse.h"
|
||||
@@ -78,6 +78,7 @@ 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+]* {
|
||||
@@ -120,7 +121,7 @@ static int comment_enter;
|
||||
"/"[^\*\/] { /* A file name that starts with "/". */
|
||||
yymore();
|
||||
BEGIN(FILE_NAME); }
|
||||
[^/\n \t\b\r+-][^/\n\r]* { /* A file name that starts with other then "/" */
|
||||
[^/\n \t\b\r+-][^/\n\r]* { /* A file name that starts with other than "/" */
|
||||
yymore();
|
||||
BEGIN(FILE_NAME); }
|
||||
|
||||
|
||||
+13
-5
@@ -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.10 2003/09/26 21:25:58 steve Exp $"
|
||||
#ident "$Id: cfparse.y,v 1.12 2007/04/19 02:52:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
@@ -62,6 +62,7 @@ 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
|
||||
|
||||
%%
|
||||
@@ -83,7 +84,7 @@ item
|
||||
: TOK_STRING
|
||||
{ char*tmp = substitutions($1);
|
||||
translate_file_name(tmp);
|
||||
process_file_name(tmp);
|
||||
process_file_name(tmp, 0);
|
||||
free($1);
|
||||
free(tmp);
|
||||
}
|
||||
@@ -98,9 +99,7 @@ item
|
||||
| TOK_Dv TOK_STRING
|
||||
{ char*tmp = substitutions($2);
|
||||
translate_file_name(tmp);
|
||||
process_file_name(tmp);
|
||||
fprintf(stderr, "%s:%u: Ignoring -v in front of %s\n",
|
||||
@1.text, @1.first_line, $2);
|
||||
process_file_name(tmp, 1);
|
||||
free($2);
|
||||
free(tmp);
|
||||
}
|
||||
@@ -145,6 +144,15 @@ 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. */
|
||||
|
||||
+11
-2
@@ -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.19 2003/11/18 06:31:46 steve Exp $"
|
||||
#ident "$Id: globals.h,v 1.21 2007/04/19 02:52:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stddef.h>
|
||||
@@ -49,11 +49,14 @@ 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);
|
||||
extern void process_file_name(const char*name, int lib_flag);
|
||||
|
||||
/* Add the name to the list of library directories. */
|
||||
extern void process_library_switch(const char*name);
|
||||
@@ -77,6 +80,12 @@ 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.
|
||||
*
|
||||
|
||||
+14
-6
@@ -1,4 +1,4 @@
|
||||
.TH iverilog 1 "$Date: 2006/09/28 04:35:18 $" Version "$Date: 2006/09/28 04:35:18 $"
|
||||
.TH iverilog 1 "$Date: 2007/06/05 01:56:12 $" Version "$Date: 2007/06/05 01:56:12 $"
|
||||
.SH NAME
|
||||
iverilog - Icarus Verilog compiler
|
||||
|
||||
@@ -62,13 +62,13 @@ 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 acuracy of
|
||||
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
|
||||
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
|
||||
@@ -89,6 +89,8 @@ 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
|
||||
@@ -199,7 +201,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 then \fBall\fP) can also be
|
||||
switch. All the warning types (other than \fBall\fP) can also be
|
||||
prefixed with \fBno-\fP to turn off that warning. This is most useful
|
||||
after a \fB-Wall\fP argument to suppress isolated warning types.
|
||||
|
||||
@@ -264,7 +266,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 substitued in file names.
|
||||
character. Variables are substituted in file names.
|
||||
|
||||
.TP 8
|
||||
.B -y\ \fIlibdir\fP
|
||||
@@ -319,13 +321,19 @@ 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
|
||||
substitued in contexts that explicitly support them, including file
|
||||
substituted in contexts that explicitly support them, including file
|
||||
and directory strings.
|
||||
|
||||
Variable values come from the operating system environment, and not
|
||||
|
||||
+81
-7
@@ -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.72 2006/10/02 18:15:47 steve Exp $"
|
||||
#ident "$Id: main.c,v 1.76 2007/06/05 01:56:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -113,6 +113,8 @@ const char*gen_xtypes = "xtypes";
|
||||
|
||||
char warning_flags[16] = "";
|
||||
|
||||
unsigned integer_width = 32;
|
||||
|
||||
char*mod_list = 0;
|
||||
char*command_filename = 0;
|
||||
|
||||
@@ -134,7 +136,6 @@ char*iconfig_common_path = iconfig_common_path_buf;
|
||||
|
||||
int synth_flag = 0;
|
||||
int verbose_flag = 0;
|
||||
int command_file = 0;
|
||||
|
||||
FILE *fp;
|
||||
|
||||
@@ -143,6 +144,48 @@ 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>
|
||||
@@ -360,7 +403,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)
|
||||
void process_file_name(const char*name, int lib_flag)
|
||||
{
|
||||
if (strlen(name) > 4 && strcasecmp(".sft", name+strlen(name)-4) == 0) {
|
||||
fprintf(iconfig_file,"sys_func:%s\n", name);
|
||||
@@ -368,6 +411,8 @@ void process_file_name(const char*name)
|
||||
} else {
|
||||
fprintf(source_file, "%s\n", name);
|
||||
source_count += 1;
|
||||
if (lib_flag)
|
||||
fprintf(iconfig_file,"library_file:%s\n", name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -410,6 +455,20 @@ int process_generation(const char*name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* If it exists add the SFT file for the given module.
|
||||
*/
|
||||
void add_sft_file(const char *module)
|
||||
{
|
||||
char *file;
|
||||
|
||||
file = (char *) malloc(strlen(base)+1+strlen(module)+4+1);
|
||||
sprintf(file, "%s%c%s.sft", base, sep, module);
|
||||
if (access(file, R_OK) == 0)
|
||||
fprintf(iconfig_file, "sys_func:%s\n", file);
|
||||
free(file);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
char*cmd;
|
||||
@@ -520,8 +579,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
case 'c':
|
||||
command_filename = malloc(strlen(optarg)+1);
|
||||
strcpy(command_filename, optarg);
|
||||
add_cmd_file(optarg);
|
||||
break;
|
||||
case 'D':
|
||||
process_define(optarg);
|
||||
@@ -554,6 +612,7 @@ int main(int argc, char **argv)
|
||||
|
||||
case 'm':
|
||||
fprintf(iconfig_file, "module:%s\n", optarg);
|
||||
add_sft_file(optarg);
|
||||
break;
|
||||
|
||||
case 'N':
|
||||
@@ -639,7 +698,7 @@ int main(int argc, char **argv)
|
||||
fprintf(iconfig_file, "out:%s\n", opath);
|
||||
if (depfile) fprintf(iconfig_file, "depfile:%s\n", depfile);
|
||||
|
||||
if (command_filename) {
|
||||
while ( (command_filename = get_cmd_file()) ) {
|
||||
int rc;
|
||||
|
||||
if (( fp = fopen(command_filename, "r")) == NULL ) {
|
||||
@@ -655,6 +714,7 @@ int main(int argc, char **argv)
|
||||
command_filename);
|
||||
return 1;
|
||||
}
|
||||
free(command_filename);
|
||||
}
|
||||
|
||||
if (depfile) {
|
||||
@@ -664,7 +724,7 @@ int main(int argc, char **argv)
|
||||
/* 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]);
|
||||
process_file_name(argv[idx], 0);
|
||||
|
||||
|
||||
fclose(source_file);
|
||||
@@ -724,6 +784,8 @@ 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. */
|
||||
@@ -740,6 +802,18 @@ 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.75 2007/04/19 02:52:53 steve
|
||||
* Add support for -v flag in command file.
|
||||
*
|
||||
* Revision 1.74 2007/04/18 03:23:38 steve
|
||||
* Add support for multiple command files. (Cary R.)
|
||||
*
|
||||
* Revision 1.73 2007/03/07 04:24:59 steve
|
||||
* Make integer width controllable.
|
||||
*
|
||||
* Revision 1.72 2006/10/02 18:15:47 steve
|
||||
* Fix handling of dep path in new argument passing method.
|
||||
*
|
||||
|
||||
+5
-2
@@ -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.12 2006/05/01 20:47:58 steve Exp $"
|
||||
#ident "$Id: elab_anet.cc,v 1.13 2007/03/22 16:08:14 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -84,7 +84,7 @@ 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 then 1 by repeating the
|
||||
Allow for a repeat count other than 1 by repeating the
|
||||
connect loop as many times as necessary. */
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
@@ -169,6 +169,9 @@ 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.
|
||||
*
|
||||
|
||||
+308
-261
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_expr.cc,v 1.116 2006/11/10 04:54:26 steve Exp $"
|
||||
#ident "$Id: elab_expr.cc,v 1.126 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -27,6 +27,7 @@
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "util.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
/*
|
||||
* The default behavor for the test_width method is to just return the
|
||||
@@ -321,7 +322,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
not lead to executable code but takes the single parameter
|
||||
and makes it into a signed expression. No bits are changed,
|
||||
it just changes the interpretation. */
|
||||
if (strcmp(path_.peek_name(0), "$signed") == 0) {
|
||||
if (strcmp(peek_tail_name(path_), "$signed") == 0) {
|
||||
if ((parms_.count() != 1) || (parms_[0] == 0)) {
|
||||
cerr << get_line() << ": error: The $signed() function "
|
||||
<< "takes exactly one(1) argument." << endl;
|
||||
@@ -335,7 +336,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
return sub;
|
||||
}
|
||||
/* add $unsigned to match $signed */
|
||||
if (strcmp(path_.peek_name(0), "$unsigned") == 0) {
|
||||
if (strcmp(peek_tail_name(path_), "$unsigned") == 0) {
|
||||
if ((parms_.count() != 1) || (parms_[0] == 0)) {
|
||||
cerr << get_line() << ": error: The $unsigned() function "
|
||||
<< "takes exactly one(1) argument." << endl;
|
||||
@@ -353,8 +354,8 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
the bit width of the sub-expression. The value of the
|
||||
sub-expression is not used, so the expression itself can be
|
||||
deleted. */
|
||||
if ((strcmp(path_.peek_name(0), "$sizeof") == 0)
|
||||
|| (strcmp(path_.peek_name(0), "$bits") == 0)) {
|
||||
if ((strcmp(peek_tail_name(path_), "$sizeof") == 0)
|
||||
|| (strcmp(peek_tail_name(path_), "$bits") == 0)) {
|
||||
if ((parms_.count() != 1) || (parms_[0] == 0)) {
|
||||
cerr << get_line() << ": error: The $bits() function "
|
||||
<< "takes exactly one(1) argument." << endl;
|
||||
@@ -362,7 +363,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (strcmp(path_.peek_name(0), "$sizeof") == 0)
|
||||
if (strcmp(peek_tail_name(path_), "$sizeof") == 0)
|
||||
cerr << get_line() << ": warning: $sizeof is deprecated."
|
||||
<< " Use $bits() instead." << endl;
|
||||
|
||||
@@ -381,7 +382,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
a single bit flag -- 1 if the expression is signed, 0
|
||||
otherwise. The subexpression is elaborated but not
|
||||
evaluated. */
|
||||
if (strcmp(path_.peek_name(0), "$is_signed") == 0) {
|
||||
if (strcmp(peek_tail_name(path_), "$is_signed") == 0) {
|
||||
if ((parms_.count() != 1) || (parms_[0] == 0)) {
|
||||
cerr << get_line() << ": error: The $is_signed() function "
|
||||
<< "takes exactly one(1) argument." << endl;
|
||||
@@ -404,7 +405,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
/* Get the return type of the system function by looking it up
|
||||
in the sfunc_table. */
|
||||
const struct sfunc_return_type*sfunc_info
|
||||
= lookup_sys_func(path_.peek_name(0));
|
||||
= lookup_sys_func(peek_tail_name(path_));
|
||||
|
||||
ivl_variable_type_t sfunc_type = sfunc_info->type;
|
||||
unsigned wid = sfunc_info->wid;
|
||||
@@ -422,7 +423,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
if ((nparms == 1) && (parms_[0] == 0))
|
||||
nparms = 0;
|
||||
|
||||
NetESFunc*fun = new NetESFunc(path_.peek_name(0), sfunc_type,
|
||||
NetESFunc*fun = new NetESFunc(peek_tail_name(path_), sfunc_type,
|
||||
wid, nparms);
|
||||
if (sfunc_info->signed_flag)
|
||||
fun->cast_signed(true);
|
||||
@@ -454,7 +455,7 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
|
||||
if (missing_parms > 0) {
|
||||
cerr << get_line() << ": error: The function "
|
||||
<< path_.peek_name(0)
|
||||
<< peek_tail_name(path_)
|
||||
<< " has been called with empty parameters." << endl;
|
||||
cerr << get_line() << ": : Verilog doesn't allow "
|
||||
<< "passing empty parameters to functions." << endl;
|
||||
@@ -467,13 +468,13 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope) const
|
||||
NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||
int expr_wid, bool) const
|
||||
{
|
||||
if (path_.peek_name(0)[0] == '$')
|
||||
if (peek_tail_name(path_)[0] == '$')
|
||||
return elaborate_sfunc_(des, scope);
|
||||
|
||||
NetFuncDef*def = des->find_function(scope, path_);
|
||||
if (def == 0) {
|
||||
cerr << get_line() << ": error: No function " << path_ <<
|
||||
" in this context (" << scope->name() << ")." << endl;
|
||||
" in this context (" << scope_path(scope) << ")." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -502,7 +503,7 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||
for (unsigned idx = 0 ; idx < parms.count() ; idx += 1) {
|
||||
PExpr*tmp = parms_[idx];
|
||||
if (tmp) {
|
||||
parms[idx] = tmp->elaborate_expr(des, scope, -1, false);
|
||||
parms[idx] = elab_and_eval(des, scope, tmp, -1);
|
||||
|
||||
} else {
|
||||
missing_parms += 1;
|
||||
@@ -530,12 +531,14 @@ NetExpr* PECallFunction::elaborate_expr(Design*des, NetScope*scope,
|
||||
if (NetNet*res = dscope->find_signal(dscope->basename())) {
|
||||
NetESignal*eres = new NetESignal(res);
|
||||
NetEUFunc*func = new NetEUFunc(dscope, eres, parms);
|
||||
func->set_line(*this);
|
||||
func->cast_signed(res->get_signed());
|
||||
return func;
|
||||
}
|
||||
|
||||
cerr << get_line() << ": internal error: Unable to locate "
|
||||
"function return value for " << path_
|
||||
<< " in " << def->name() << "." << endl;
|
||||
<< " in " << dscope->basename() << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -617,33 +620,38 @@ NetExpr* PEFNumber::elaborate_expr(Design*des, NetScope*scope, int, bool) const
|
||||
bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
|
||||
long&msb, long&lsb) const
|
||||
{
|
||||
assert(lsb_ != 0);
|
||||
assert(msb_ != 0);
|
||||
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.sel == index_component_t::SEL_PART);
|
||||
ivl_assert(*this, index_tail.msb && index_tail.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. */
|
||||
NetExpr*lsb_ex = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetExpr*lsb_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
|
||||
NetEConst*lsb_c = dynamic_cast<NetEConst*>(lsb_ex);
|
||||
if (lsb_c == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
cerr << index_tail.lsb->get_line() << ": error: "
|
||||
"Part select expressions must be constant."
|
||||
<< endl;
|
||||
cerr << lsb_->get_line() << ": : This lsb expression "
|
||||
"violates the rule: " << *lsb_ << endl;
|
||||
cerr << index_tail.lsb->get_line() << ": : "
|
||||
"This lsb expression violates the rule: "
|
||||
<< *index_tail.lsb << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
NetExpr*msb_ex = elab_and_eval(des, scope, msb_, -1);
|
||||
NetExpr*msb_ex = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
NetEConst*msb_c = dynamic_cast<NetEConst*>(msb_ex);
|
||||
if (msb_c == 0) {
|
||||
cerr << msb_->get_line() << ": error: "
|
||||
cerr << index_tail.msb->get_line() << ": error: "
|
||||
"Part select expressions must be constant."
|
||||
<< endl;
|
||||
cerr << msb_->get_line() << ": : This msb expression "
|
||||
"violates the rule: " << *msb_ << endl;
|
||||
cerr << index_tail.msb->get_line() << ": : This msb expression "
|
||||
"violates the rule: " << *index_tail.msb << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
@@ -659,13 +667,18 @@ bool PEIdent::calculate_parts_(Design*des, NetScope*scope,
|
||||
bool PEIdent::calculate_up_do_width_(Design*des, NetScope*scope,
|
||||
unsigned long&wid) const
|
||||
{
|
||||
assert(lsb_);
|
||||
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.lsb && index_tail.msb);
|
||||
|
||||
bool flag = true;
|
||||
|
||||
/* Calculate the width expression (in the lsb_ position)
|
||||
first. If the expression is not constant, error but guess 1
|
||||
so we can keep going and find more errors. */
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
|
||||
NetEConst*wid_c = dynamic_cast<NetEConst*>(wid_ex);
|
||||
|
||||
if (wid_c == 0) {
|
||||
@@ -687,36 +700,41 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope,
|
||||
bool&unsized_flag) const
|
||||
{
|
||||
NetNet* net = 0;
|
||||
NetMemory* mem = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
const NetExpr*ex1, *ex2;
|
||||
|
||||
NetScope*found_in = symbol_search(des, scope, path_,
|
||||
net, mem, par, eve,
|
||||
ex1, ex2);
|
||||
symbol_search(des, scope, path_, net, par, eve, ex1, ex2);
|
||||
|
||||
if (net != 0) {
|
||||
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;
|
||||
|
||||
unsigned use_width = net->vector_width();
|
||||
switch (sel_) {
|
||||
case SEL_NONE:
|
||||
switch (use_sel) {
|
||||
case index_component_t::SEL_NONE:
|
||||
break;
|
||||
case SEL_PART:
|
||||
case index_component_t::SEL_PART:
|
||||
{ long msb, lsb;
|
||||
bool flag = calculate_parts_(des, scope, msb, lsb);
|
||||
calculate_parts_(des, scope, msb, lsb);
|
||||
use_width = 1 + ((msb>lsb)? (msb-lsb) : (lsb-msb));
|
||||
break;
|
||||
}
|
||||
case SEL_IDX_UP:
|
||||
case SEL_IDX_DO:
|
||||
case index_component_t::SEL_IDX_UP:
|
||||
case index_component_t::SEL_IDX_DO:
|
||||
{ unsigned long tmp = 0;
|
||||
calculate_up_do_width_(des, scope, tmp);
|
||||
use_width = tmp;
|
||||
break;
|
||||
}
|
||||
case index_component_t::SEL_BIT:
|
||||
use_width = 1;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
ivl_assert(*this, 0);
|
||||
}
|
||||
return use_width;
|
||||
}
|
||||
@@ -741,14 +759,13 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
assert(scope);
|
||||
|
||||
NetNet* net = 0;
|
||||
NetMemory* mem = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
const NetExpr*ex1, *ex2;
|
||||
|
||||
NetScope*found_in = symbol_search(des, scope, path_,
|
||||
net, mem, par, eve,
|
||||
net, par, eve,
|
||||
ex1, ex2);
|
||||
|
||||
// If the identifier name is a parameter name, then return
|
||||
@@ -760,126 +777,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
// If the identifier names a signal (a register or wire)
|
||||
// then create a NetESignal node to handle it.
|
||||
if (net != 0)
|
||||
return elaborate_expr_net(des, scope, net, found_in);
|
||||
|
||||
|
||||
// If the identifier names a memory, then this is a
|
||||
// memory reference and I must generate a NetEMemory
|
||||
// object to handle it.
|
||||
if (mem != 0) {
|
||||
|
||||
if (idx_.empty()) {
|
||||
|
||||
if (msb_ || lsb_) {
|
||||
cerr << get_line() << ": error: "
|
||||
<< "Part select of a memory: "
|
||||
<< mem->name() << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
// If this memory is an argument to a system task,
|
||||
// then it is OK for it to not have an index.
|
||||
if (sys_task_arg) {
|
||||
NetEMemory*node = new NetEMemory(mem);
|
||||
node->set_line(*this);
|
||||
return node;
|
||||
}
|
||||
|
||||
// If it is not a simple system task argument,
|
||||
// this a missing index is an error.
|
||||
cerr << get_line() << ": error: memory " << mem->name()
|
||||
<< " needs an index in this context." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (idx_.size() != mem->dimensions()) {
|
||||
cerr << get_line() << ": error: " << idx_.size()
|
||||
<< " indices do not properly address a "
|
||||
<< mem->dimensions() << "-dimension memory/array."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// XXXX For now, only support single word index.
|
||||
assert(idx_.size() == 1);
|
||||
PExpr*addr = idx_[0];
|
||||
assert(addr);
|
||||
|
||||
NetExpr*i = addr->elaborate_expr(des, scope, -1, false);
|
||||
if (i == 0) {
|
||||
cerr << get_line() << ": error: Unable to elaborate "
|
||||
"index expression `" << *addr << "'" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEMemory*node = new NetEMemory(mem, i);
|
||||
node->set_line(*this);
|
||||
|
||||
if (msb_ == 0 && lsb_ == 0)
|
||||
return node;
|
||||
|
||||
assert(msb_ && lsb_);
|
||||
|
||||
assert(sel_ != SEL_NONE);
|
||||
|
||||
if (sel_ == SEL_PART) {
|
||||
|
||||
NetExpr*le = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetExpr*me = elab_and_eval(des, scope, msb_, -1);
|
||||
|
||||
NetEConst*lec = dynamic_cast<NetEConst*>(le);
|
||||
NetEConst*mec = dynamic_cast<NetEConst*>(me);
|
||||
|
||||
if (lec == 0 || mec == 0) {
|
||||
cerr << get_line() << ": error: Part select "
|
||||
<< "expressions must be constant." << endl;
|
||||
des->errors += 1;
|
||||
delete le;
|
||||
delete me;
|
||||
return node;
|
||||
}
|
||||
|
||||
verinum wedv = mec->value() - lec->value();
|
||||
unsigned wid = wedv.as_long() + 1;
|
||||
|
||||
NetESelect*se = new NetESelect(node, le, wid);
|
||||
|
||||
delete me;
|
||||
return se;
|
||||
}
|
||||
|
||||
assert(sel_ == SEL_IDX_UP || sel_ == SEL_IDX_DO);
|
||||
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
|
||||
if (wid_ec == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
<< "Second expression of indexed part select "
|
||||
<< "most be constant." << endl;
|
||||
des->errors += 1;
|
||||
return node;
|
||||
}
|
||||
|
||||
unsigned wid = wid_ec->value().as_ulong();
|
||||
|
||||
NetExpr*idx_ex = elab_and_eval(des, scope, msb_, -1);
|
||||
if (idx_ex == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sel_ == SEL_IDX_DO && wid > 1) {
|
||||
idx_ex = make_add_expr(idx_ex, 1-(long)wid);
|
||||
}
|
||||
|
||||
|
||||
/* Wrap the param expression with a part select. */
|
||||
NetESelect*se = new NetESelect(node, idx_ex, wid);
|
||||
se->set_line(*this);
|
||||
return se;
|
||||
}
|
||||
return elaborate_expr_net(des, scope, net, found_in, sys_task_arg);
|
||||
|
||||
// If the identifier is a named event.
|
||||
// is a variable reference.
|
||||
@@ -892,9 +790,9 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
// Hmm... maybe this is a genvar? This is only possible while
|
||||
// processing generate blocks, but then the genvar_tmp will be
|
||||
// set in the scope.
|
||||
if (path_.component_count() == 1
|
||||
if (path_.size() == 1
|
||||
&& scope->genvar_tmp.str()
|
||||
&& strcmp(path_.peek_name(0), scope->genvar_tmp) == 0) {
|
||||
&& strcmp(peek_tail_name(path_), scope->genvar_tmp) == 0) {
|
||||
verinum val (scope->genvar_tmp_val);
|
||||
NetEConst*tmp = new NetEConst(val);
|
||||
tmp->set_line(*this);
|
||||
@@ -908,8 +806,8 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
|
||||
if (gn_specify_blocks_flag) {
|
||||
map<perm_string,NetScope::spec_val_t>::const_iterator specp;
|
||||
perm_string key = perm_string::literal(path_.peek_name(0));
|
||||
if (path_.component_count() == 1
|
||||
perm_string key = peek_tail_name(path_);
|
||||
if (path_.size() == 1
|
||||
&& ((specp = scope->specparams.find(key)) != scope->specparams.end())) {
|
||||
NetScope::spec_val_t value = (*specp).second;
|
||||
NetExpr*tmp = 0;
|
||||
@@ -932,22 +830,26 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
// Finally, if this is a scope name, then return that. Look
|
||||
// first to see if this is a name of a local scope. Failing
|
||||
// that, search globally for a hierarchical name.
|
||||
if ((path_.peek_name(1) == 0))
|
||||
if (NetScope*nsc = scope->child(path_.peek_name(0))) {
|
||||
if ((path_.size() == 1)) {
|
||||
hname_t use_name ( peek_tail_name(path_) );
|
||||
if (NetScope*nsc = scope->child(use_name)) {
|
||||
NetEScope*tmp = new NetEScope(nsc);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
}
|
||||
|
||||
list<hname_t> spath = eval_scope_path(des, scope, path_);
|
||||
|
||||
// Try full hierarchical scope name.
|
||||
if (NetScope*nsc = des->find_scope(path_)) {
|
||||
if (NetScope*nsc = des->find_scope(spath)) {
|
||||
NetEScope*tmp = new NetEScope(nsc);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
// Try relative scope name.
|
||||
if (NetScope*nsc = des->find_scope(scope, path_)) {
|
||||
if (NetScope*nsc = des->find_scope(scope, spath)) {
|
||||
NetEScope*tmp = new NetEScope(nsc);
|
||||
tmp->set_line(*this);
|
||||
return tmp;
|
||||
@@ -955,7 +857,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope,
|
||||
|
||||
// I cannot interpret this identifier. Error message.
|
||||
cerr << get_line() << ": error: Unable to bind wire/reg/memory "
|
||||
"`" << path_ << "' in `" << scope->name() << "'" << endl;
|
||||
"`" << path_ << "' in `" << scope_path(scope) << "'" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -972,13 +874,18 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
||||
const NetExpr*par_msb,
|
||||
const NetExpr*par_lsb) const
|
||||
{
|
||||
NetExpr*tmp;
|
||||
NetExpr*tmp = par->dup_expr();
|
||||
|
||||
tmp = par->dup_expr();
|
||||
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;
|
||||
|
||||
if (sel_ == SEL_PART) {
|
||||
assert(msb_ && lsb_);
|
||||
assert(idx_.empty());
|
||||
if (use_sel == index_component_t::SEL_PART) {
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb);
|
||||
ivl_assert(*this, index_tail.lsb);
|
||||
|
||||
/* If the identifier has a part select, we support
|
||||
it by pulling the right bits out and making a
|
||||
@@ -986,8 +893,8 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
||||
lsb of a parameter is 0 and the msb is the
|
||||
width of the parameter. */
|
||||
|
||||
verinum*lsn = lsb_->eval_const(des, scope);
|
||||
verinum*msn = msb_->eval_const(des, scope);
|
||||
verinum*lsn = index_tail.lsb->eval_const(des, scope);
|
||||
verinum*msn = index_tail.msb->eval_const(des, scope);
|
||||
if ((lsn == 0) || (msn == 0)) {
|
||||
cerr << get_line() << ": error: "
|
||||
"Part select expressions must be "
|
||||
@@ -1044,17 +951,19 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
||||
delete tmp;
|
||||
tmp = new NetEConst(result);
|
||||
|
||||
} else if (sel_ == SEL_IDX_UP || sel_ == SEL_IDX_DO) {
|
||||
assert(msb_);
|
||||
assert(lsb_);
|
||||
assert(idx_.empty());
|
||||
} else if (use_sel == index_component_t::SEL_IDX_UP || use_sel == index_component_t::SEL_IDX_DO) {
|
||||
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb);
|
||||
ivl_assert(*this, index_tail.lsb);
|
||||
|
||||
/* Get and evaluate the width of the index
|
||||
select. This must be constant. */
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
|
||||
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
|
||||
if (wid_ec == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
cerr << index_tail.lsb->get_line() << ": error: "
|
||||
<< "Second expression of indexed part select "
|
||||
<< "most be constant." << endl;
|
||||
des->errors += 1;
|
||||
@@ -1063,12 +972,12 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
||||
|
||||
unsigned wid = wid_ec->value().as_ulong();
|
||||
|
||||
NetExpr*idx_ex = elab_and_eval(des, scope, msb_, -1);
|
||||
NetExpr*idx_ex = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
if (idx_ex == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sel_ == SEL_IDX_DO && wid > 1) {
|
||||
if (use_sel == index_component_t::SEL_IDX_DO && wid > 1) {
|
||||
idx_ex = make_add_expr(idx_ex, 1-(long)wid);
|
||||
}
|
||||
|
||||
@@ -1077,16 +986,16 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
||||
tmp = new NetESelect(tmp, idx_ex, wid);
|
||||
|
||||
|
||||
} else if (!idx_.empty()) {
|
||||
assert(!msb_);
|
||||
assert(!lsb_);
|
||||
assert(idx_.size() == 1);
|
||||
assert(sel_ == SEL_NONE);
|
||||
} else if (use_sel == index_component_t::SEL_BIT) {
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb);
|
||||
ivl_assert(*this, !index_tail.lsb);
|
||||
|
||||
/* Handle the case where a parameter has a bit
|
||||
select attached to it. Generate a NetESelect
|
||||
object to select the bit as desired. */
|
||||
NetExpr*mtmp = idx_[0]->elaborate_expr(des, scope, -1,false);
|
||||
NetExpr*mtmp = index_tail.msb->elaborate_expr(des, scope, -1,false);
|
||||
if (! dynamic_cast<NetEConst*>(mtmp)) {
|
||||
NetExpr*re = mtmp->eval_tree();
|
||||
if (re) {
|
||||
@@ -1163,8 +1072,7 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
||||
NetEConstParam if possible. */
|
||||
NetEConst*ctmp = dynamic_cast<NetEConst*>(tmp);
|
||||
if (ctmp != 0) {
|
||||
perm_string name
|
||||
= lex_strings.make(path_.peek_tail_name());
|
||||
perm_string name = peek_tail_name(path_);
|
||||
NetEConstParam*ptmp
|
||||
= new NetEConstParam(found_in, name, ctmp->value());
|
||||
delete tmp;
|
||||
@@ -1176,14 +1084,95 @@ NetExpr* PEIdent::elaborate_expr_param(Design*des,
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle word selects of vector arrays.
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in,
|
||||
bool sys_task_arg) const
|
||||
{
|
||||
const name_component_t&name_tail = path_.back();
|
||||
|
||||
if (name_tail.index.empty() && !sys_task_arg) {
|
||||
cerr << get_line() << ": error: Array " << path()
|
||||
<< " Needs an array index here." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
index_component_t index_front;
|
||||
if (! name_tail.index.empty()) {
|
||||
index_front = name_tail.index.front();
|
||||
ivl_assert(*this, index_front.sel != index_component_t::SEL_NONE);
|
||||
if (index_front.sel != index_component_t::SEL_BIT) {
|
||||
cerr << get_line() << ": error: Array " << path_
|
||||
<< " cannot be indexed by a range." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
ivl_assert(*this, index_front.msb);
|
||||
ivl_assert(*this, !index_front.lsb);
|
||||
}
|
||||
|
||||
NetExpr*word_index = index_front.sel == index_component_t::SEL_NONE
|
||||
? 0
|
||||
: elab_and_eval(des, scope, index_front.msb, -1);
|
||||
if (word_index == 0 && !sys_task_arg)
|
||||
return 0;
|
||||
|
||||
if (NetEConst*word_addr = dynamic_cast<NetEConst*>(word_index)) {
|
||||
long addr = word_addr->value().as_long();
|
||||
|
||||
// Special case: The index is out of range, so the value
|
||||
// of this expression is a 'bx vector the width of a word.
|
||||
if (!net->array_index_is_valid(addr)) {
|
||||
verinum xxx (verinum::Vx, net->vector_width());
|
||||
NetEConst*resx = new NetEConst(xxx);
|
||||
resx->set_line(*this);
|
||||
delete word_index;
|
||||
return resx;
|
||||
}
|
||||
|
||||
// Recalculate the constant address with the adjusted base.
|
||||
unsigned use_addr = net->array_index_to_address(addr);
|
||||
if (use_addr != addr) {
|
||||
verinum val (use_addr, 8*sizeof(use_addr));
|
||||
NetEConst*tmp = new NetEConst(val);
|
||||
tmp->set_line(*this);
|
||||
delete word_index;
|
||||
word_index = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
NetESignal*res = new NetESignal(net, word_index);
|
||||
res->set_line(*this);
|
||||
|
||||
// Detect that the word has a part select as well.
|
||||
|
||||
index_component_t::ctype_t word_sel = index_component_t::SEL_NONE;
|
||||
if (name_tail.index.size() > 1)
|
||||
word_sel = name_tail.index.back().sel;
|
||||
|
||||
if (word_sel == index_component_t::SEL_PART)
|
||||
return elaborate_expr_net_part_(des, scope, res, found_in);
|
||||
|
||||
if (word_sel == index_component_t::SEL_IDX_UP)
|
||||
return elaborate_expr_net_idx_up_(des, scope, res, found_in);
|
||||
|
||||
if (word_sel == index_component_t::SEL_IDX_DO)
|
||||
return elaborate_expr_net_idx_do_(des, scope, res, found_in);
|
||||
|
||||
ivl_assert(*this, word_sel == index_component_t::SEL_NONE);
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* Handle part selects of NetNet identifiers.
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in)const
|
||||
NetESignal*net, NetScope*found_in) const
|
||||
{
|
||||
long msv, lsv;
|
||||
assert(idx_.empty());
|
||||
bool flag = calculate_parts_(des, scope, msv, lsv);
|
||||
if (!flag)
|
||||
return 0;
|
||||
@@ -1199,40 +1188,37 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
||||
des->errors += 1;
|
||||
//delete lsn;
|
||||
//delete msn;
|
||||
return 0;
|
||||
return net;
|
||||
}
|
||||
assert(wid <= net->vector_width());
|
||||
ivl_assert(*this, wid <= net->vector_width());
|
||||
|
||||
if (net->sb_to_idx(msv) < net->sb_to_idx(lsv)) {
|
||||
if (net->sig()->sb_to_idx(msv) < net->sig()->sb_to_idx(lsv)) {
|
||||
cerr << get_line() << ": error: part select ["
|
||||
<< msv << ":" << lsv << "] out of order." << endl;
|
||||
des->errors += 1;
|
||||
//delete lsn;
|
||||
//delete msn;
|
||||
return 0;
|
||||
return net;
|
||||
}
|
||||
|
||||
|
||||
if (net->sb_to_idx(msv) >= net->vector_width()) {
|
||||
if (net->sig()->sb_to_idx(msv) >= net->vector_width()) {
|
||||
cerr << get_line() << ": error: part select ["
|
||||
<< msv << ":" << lsv << "] out of range." << endl;
|
||||
des->errors += 1;
|
||||
//delete lsn;
|
||||
//delete msn;
|
||||
return 0;
|
||||
return net;
|
||||
}
|
||||
|
||||
NetESignal*tmp = new NetESignal(net);
|
||||
tmp->set_line(*this);
|
||||
|
||||
// If the part select convers exactly the entire
|
||||
// vector, then do not bother with it. Return the
|
||||
// signal itself.
|
||||
if (net->sb_to_idx(lsv) == 0 && wid == net->vector_width())
|
||||
return tmp;
|
||||
if (net->sig()->sb_to_idx(lsv) == 0 && wid == net->vector_width())
|
||||
return net;
|
||||
|
||||
NetExpr*ex = new NetEConst(verinum(net->sb_to_idx(lsv)));
|
||||
NetESelect*ss = new NetESelect(tmp, ex, wid);
|
||||
NetExpr*ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv)));
|
||||
NetESelect*ss = new NetESelect(net, ex, wid);
|
||||
ss->set_line(*this);
|
||||
|
||||
return ss;
|
||||
@@ -1242,16 +1228,16 @@ NetExpr* PEIdent::elaborate_expr_net_part_(Design*des, NetScope*scope,
|
||||
* Part select indexed up, i.e. net[<m> +: <l>]
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in)const
|
||||
NetESignal*net, NetScope*found_in) const
|
||||
{
|
||||
assert(lsb_ != 0);
|
||||
assert(msb_ != 0);
|
||||
assert(idx_.empty());
|
||||
const name_component_t&name_tail = path_.back();
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
|
||||
NetESignal*sig = new NetESignal(net);
|
||||
sig->set_line(*this);
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.lsb != 0);
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
|
||||
NetExpr*base = elab_and_eval(des, scope, msb_, -1);
|
||||
NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
|
||||
unsigned long wid = 0;
|
||||
calculate_up_do_width_(des, scope, wid);
|
||||
@@ -1266,11 +1252,22 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||
// If the part select convers exactly the entire
|
||||
// vector, then do not bother with it. Return the
|
||||
// signal itself.
|
||||
if (net->sb_to_idx(lsv) == 0 && wid == net->vector_width())
|
||||
return sig;
|
||||
if (net->sig()->sb_to_idx(lsv) == 0 && wid == net->vector_width())
|
||||
return net;
|
||||
|
||||
// Otherwise, make a part select that covers the right range.
|
||||
NetExpr*ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv)));
|
||||
NetESelect*ss = new NetESelect(net, ex, wid);
|
||||
ss->set_line(*this);
|
||||
|
||||
delete base;
|
||||
return ss;
|
||||
}
|
||||
|
||||
NetESelect*ss = new NetESelect(sig, base, wid);
|
||||
if (long offset = net->lsi())
|
||||
base = make_add_expr(base, 0-offset);
|
||||
|
||||
NetESelect*ss = new NetESelect(net, base, wid);
|
||||
ss->set_line(*this);
|
||||
|
||||
if (debug_elaborate) {
|
||||
@@ -1285,16 +1282,16 @@ NetExpr* PEIdent::elaborate_expr_net_idx_up_(Design*des, NetScope*scope,
|
||||
* Part select up, i.e. net[<m> +: <l>]
|
||||
*/
|
||||
NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in)const
|
||||
NetESignal*net, NetScope*found_in)const
|
||||
{
|
||||
assert(lsb_ != 0);
|
||||
assert(msb_ != 0);
|
||||
assert(idx_.empty());
|
||||
const name_component_t&name_tail = path_.back();
|
||||
ivl_assert(*this, ! name_tail.index.empty());
|
||||
|
||||
NetESignal*sig = new NetESignal(net);
|
||||
sig->set_line(*this);
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.lsb != 0);
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
|
||||
NetExpr*base = elab_and_eval(des, scope, msb_, -1);
|
||||
NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
|
||||
unsigned long wid = 0;
|
||||
calculate_up_do_width_(des, scope, wid);
|
||||
@@ -1308,37 +1305,51 @@ NetExpr* PEIdent::elaborate_expr_net_idx_do_(Design*des, NetScope*scope,
|
||||
// If the part select convers exactly the entire
|
||||
// vector, then do not bother with it. Return the
|
||||
// signal itself.
|
||||
if (net->sb_to_idx(lsv) == (wid-1) && wid == net->vector_width())
|
||||
return sig;
|
||||
if (net->sig()->sb_to_idx(lsv) == (wid-1) && wid == net->vector_width())
|
||||
return net;
|
||||
|
||||
// Otherwise, make a part select that covers the right range.
|
||||
NetExpr*ex = new NetEConst(verinum(net->sig()->sb_to_idx(lsv)-wid+1));
|
||||
NetESelect*ss = new NetESelect(net, ex, wid);
|
||||
ss->set_line(*this);
|
||||
|
||||
delete base;
|
||||
return ss;
|
||||
}
|
||||
|
||||
NetExpr*base_adjusted = wid > 1? make_add_expr(base,1-wid) : base;
|
||||
NetESelect*ss = new NetESelect(sig, base_adjusted, wid);
|
||||
long offset = net->lsi();
|
||||
NetExpr*base_adjusted = wid > 1
|
||||
? make_add_expr(base,1-(long)wid-offset)
|
||||
: (offset == 0? base : make_add_expr(base, 0-offset));
|
||||
NetESelect*ss = new NetESelect(net, base_adjusted, wid);
|
||||
ss->set_line(*this);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Elaborate part "
|
||||
<< "select base="<< *base << ", wid="<< wid << endl;
|
||||
<< "select base="<< *base_adjusted << ", wid="<< wid << endl;
|
||||
}
|
||||
|
||||
return ss;
|
||||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in) const
|
||||
NetESignal*net, NetScope*found_in) const
|
||||
{
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_.size() == 1);
|
||||
const name_component_t&name_tail = path_.back();
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
|
||||
NetExpr*ex = elab_and_eval(des, scope, idx_[0], -1);
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
ivl_assert(*this, index_tail.lsb == 0);
|
||||
|
||||
NetExpr*ex = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
|
||||
// If the bit select is constant, then treat it similar
|
||||
// to the part select, so that I save the effort of
|
||||
// making a mux part in the netlist.
|
||||
if (NetEConst*msc = dynamic_cast<NetEConst*> (ex)) {
|
||||
long msv = msc->value().as_long();
|
||||
unsigned idx = net->sb_to_idx(msv);
|
||||
unsigned idx = net->sig()->sb_to_idx(msv);
|
||||
|
||||
if (idx >= net->vector_width()) {
|
||||
/* The bit select is out of range of the
|
||||
@@ -1350,80 +1361,82 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope,
|
||||
|
||||
cerr << get_line() << ": warning: Bit select ["
|
||||
<< msv << "] out of range of vector "
|
||||
<< net->name() << "[" << net->msb()
|
||||
<< ":" << net->lsb() << "]." << endl;
|
||||
<< net->name() << "[" << net->sig()->msb()
|
||||
<< ":" << net->sig()->lsb() << "]." << endl;
|
||||
cerr << get_line() << ": : Replacing "
|
||||
<< "expression with a constant 1'bx." << endl;
|
||||
delete ex;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
NetESignal*tmp = new NetESignal(net);
|
||||
tmp->set_line(*this);
|
||||
// If the vector is only one bit, we are done. The
|
||||
// bit select will return the scaler itself.
|
||||
if (net->vector_width() == 1)
|
||||
return tmp;
|
||||
return net;
|
||||
|
||||
// Make an expression out of the index
|
||||
NetEConst*idx_c = new NetEConst(verinum(idx));
|
||||
idx_c->set_line(*net);
|
||||
|
||||
// Make a bit select with the canonical index
|
||||
NetESelect*res = new NetESelect(tmp, idx_c, 1);
|
||||
NetESelect*res = new NetESelect(net, idx_c, 1);
|
||||
res->set_line(*net);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
NetESignal*node = new NetESignal(net);
|
||||
|
||||
// Non-constant bit select? punt and make a subsignal
|
||||
// device to mux the bit in the net. This is a fairly
|
||||
// complicated task because we need to generate
|
||||
// expressions to convert calculated bit select
|
||||
// values to canonical values that are used internally.
|
||||
|
||||
if (net->msb() < net->lsb()) {
|
||||
ex = make_sub_expr(net->lsb(), ex);
|
||||
if (net->sig()->msb() < net->sig()->lsb()) {
|
||||
ex = make_sub_expr(net->sig()->lsb(), ex);
|
||||
} else {
|
||||
ex = make_add_expr(ex, - net->lsb());
|
||||
ex = make_add_expr(ex, - net->sig()->lsb());
|
||||
}
|
||||
|
||||
NetESelect*ss = new NetESelect(node, ex, 1);
|
||||
NetESelect*ss = new NetESelect(net, ex, 1);
|
||||
ss->set_line(*this);
|
||||
return ss;
|
||||
}
|
||||
|
||||
NetExpr* PEIdent::elaborate_expr_net(Design*des, NetScope*scope,
|
||||
NetNet*net, NetScope*found_in) const
|
||||
NetNet*net, NetScope*found_in,
|
||||
bool sys_task_arg) const
|
||||
{
|
||||
if (net->array_dimensions() > 0)
|
||||
return elaborate_expr_net_word_(des, scope, net, found_in, sys_task_arg);
|
||||
|
||||
NetESignal*node = new NetESignal(net);
|
||||
node->set_line(*this);
|
||||
|
||||
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
|
||||
if (! path_.back().index.empty())
|
||||
use_sel = path_.back().index.back().sel;
|
||||
|
||||
// If this is a part select of a signal, then make a new
|
||||
// temporary signal that is connected to just the
|
||||
// selected bits. The lsb_ and msb_ expressions are from
|
||||
// the foo[msb:lsb] expression in the original.
|
||||
if (sel_ == SEL_PART)
|
||||
return elaborate_expr_net_part_(des, scope, net, found_in);
|
||||
if (use_sel == index_component_t::SEL_PART)
|
||||
return elaborate_expr_net_part_(des, scope, node, found_in);
|
||||
|
||||
if (sel_ == SEL_IDX_UP)
|
||||
return elaborate_expr_net_idx_up_(des, scope, net, found_in);
|
||||
if (use_sel == index_component_t::SEL_IDX_UP)
|
||||
return elaborate_expr_net_idx_up_(des, scope, node, found_in);
|
||||
|
||||
if (sel_ == SEL_IDX_DO)
|
||||
return elaborate_expr_net_idx_do_(des, scope, net, found_in);
|
||||
if (use_sel == index_component_t::SEL_IDX_DO)
|
||||
return elaborate_expr_net_idx_do_(des, scope, node, found_in);
|
||||
|
||||
if (!idx_.empty())
|
||||
return elaborate_expr_net_bit_(des, scope, net, found_in);
|
||||
if (use_sel == index_component_t::SEL_BIT)
|
||||
return elaborate_expr_net_bit_(des, scope, node, found_in);
|
||||
|
||||
// It's not anything else, so this must be a simple identifier
|
||||
// expression with no part or bit select. Return the signal
|
||||
// itself as the expression.
|
||||
assert(sel_ == SEL_NONE);
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_.empty());
|
||||
assert(use_sel == index_component_t::SEL_NONE);
|
||||
|
||||
NetESignal*node = new NetESignal(net);
|
||||
node->set_line(*this);
|
||||
return node;
|
||||
}
|
||||
|
||||
@@ -1675,6 +1688,40 @@ NetExpr* PEUnary::elaborate_expr(Design*des, NetScope*scope,
|
||||
|
||||
/*
|
||||
* $Log: elab_expr.cc,v $
|
||||
* Revision 1.126 2007/06/02 03:42:12 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.125 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.124 2007/04/01 05:28:26 steve
|
||||
* Get offsets into indexed part selects correct.
|
||||
*
|
||||
* Revision 1.123 2007/03/26 19:23:13 steve
|
||||
* Handle part select of array words.
|
||||
*
|
||||
* Revision 1.122 2007/03/14 05:06:49 steve
|
||||
* Replace some asserts with ivl_asserts.
|
||||
*
|
||||
* Revision 1.121 2007/03/07 00:38:15 steve
|
||||
* Lint fixes.
|
||||
*
|
||||
* Revision 1.120 2007/03/06 05:22:49 steve
|
||||
* Support signed function return values.
|
||||
*
|
||||
* Revision 1.119 2007/03/02 01:55:36 steve
|
||||
* Better error message when operating on array.
|
||||
*
|
||||
* Revision 1.118 2007/01/19 05:42:40 steve
|
||||
* Precalculate constant power expressions, and constant function arguments.
|
||||
*
|
||||
* Revision 1.117 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.116 2006/11/10 04:54:26 steve
|
||||
* Add test_width methods for PETernary and PEString.
|
||||
*
|
||||
|
||||
+182
-157
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000 Stephen Williams ([email protected])
|
||||
* Copyright (c) 2000-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: elab_lval.cc,v 1.37 2006/11/04 06:19:25 steve Exp $"
|
||||
#ident "$Id: elab_lval.cc,v 1.44 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -25,8 +25,9 @@
|
||||
# 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
|
||||
@@ -149,51 +150,63 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
bool is_force) const
|
||||
{
|
||||
NetNet* reg = 0;
|
||||
NetMemory* mem = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(des, scope, path_, reg, mem, par, eve);
|
||||
|
||||
if (mem) {
|
||||
if (is_force) {
|
||||
cerr << get_line() << ": error: Memories "
|
||||
<< "(" << path_ << " in this case)"
|
||||
<< " are not allowed"
|
||||
<< " as l-values to force statements." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return elaborate_mem_lval_(des, scope, mem);
|
||||
}
|
||||
|
||||
symbol_search(des, scope, path_, reg, par, eve);
|
||||
if (reg == 0) {
|
||||
cerr << get_line() << ": error: Could not find variable ``"
|
||||
<< path_ << "'' in ``" << scope->name() <<
|
||||
<< path_ << "'' in ``" << scope_path(scope) <<
|
||||
"''" << endl;
|
||||
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(reg);
|
||||
ivl_assert(*this, reg);
|
||||
|
||||
if (sel_ == SEL_PART)
|
||||
return elaborate_lval_net_part_(des, scope, reg);
|
||||
const name_component_t&name_tail = path_.back();
|
||||
|
||||
if (sel_ == SEL_IDX_UP)
|
||||
return elaborate_lval_net_idx_up_(des, scope, reg);
|
||||
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
|
||||
if (!name_tail.index.empty())
|
||||
use_sel = name_tail.index.back().sel;
|
||||
|
||||
if (sel_ == SEL_IDX_DO)
|
||||
return elaborate_lval_net_idx_do_(des, scope, reg);
|
||||
// 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;
|
||||
}
|
||||
|
||||
/* 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) {
|
||||
cerr << get_line() << ": error: " << path_ <<
|
||||
" is not a reg/integer/time in " << scope->name() <<
|
||||
" is not a valid l-value in " << scope_path(scope) <<
|
||||
"." << endl;
|
||||
cerr << reg->get_line() << ": : " << path_ <<
|
||||
" is declared here as " << reg->type() << "." << endl;
|
||||
@@ -201,32 +214,32 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
return 0;
|
||||
}
|
||||
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
long msb, lsb;
|
||||
NetExpr*mux;
|
||||
|
||||
if (! idx_.empty()) {
|
||||
if (use_sel == index_component_t::SEL_BIT) {
|
||||
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
ivl_assert(*this, index_tail.lsb == 0);
|
||||
|
||||
/* If there is only a single select expression, it is a
|
||||
bit select. Evaluate the constant value and treat it
|
||||
as a part select with a bit width of 1. If the
|
||||
expression it not constant, then return the
|
||||
expression as a mux. */
|
||||
assert(idx_.size() == 1);
|
||||
verinum*v = idx_[0]->eval_const(des, scope);
|
||||
if (v == 0) {
|
||||
NetExpr*m = idx_[0]->elaborate_expr(des, scope, -1, false);
|
||||
assert(m);
|
||||
msb = 0;
|
||||
lsb = 0;
|
||||
mux = m;
|
||||
|
||||
NetExpr*index_expr = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
|
||||
if (NetEConst*index_con = dynamic_cast<NetEConst*> (index_expr)) {
|
||||
msb = index_con->value().as_long();
|
||||
lsb = index_con->value().as_long();
|
||||
mux = 0;
|
||||
|
||||
} else {
|
||||
|
||||
msb = v->as_long();
|
||||
lsb = v->as_long();
|
||||
mux = 0;
|
||||
msb = 0;
|
||||
lsb = 0;
|
||||
mux = index_expr;
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -300,22 +313,85 @@ NetAssign_* PEIdent::elaborate_lval(Design*des,
|
||||
return lv;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
NetAssign_* PEIdent::elaborate_lval_net_word_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*reg) const
|
||||
{
|
||||
const name_component_t&name_tail = path_.back();
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
|
||||
const index_component_t&index_head = name_tail.index.front();
|
||||
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 0;
|
||||
return false;
|
||||
|
||||
NetAssign_*lv = 0;
|
||||
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. */
|
||||
lv = new NetAssign_(reg);
|
||||
|
||||
} else {
|
||||
|
||||
@@ -331,7 +407,7 @@ NetAssign_* PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is reversed." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* If the part select extends beyond the extreme of the
|
||||
@@ -344,37 +420,43 @@ NetAssign_* PEIdent::elaborate_lval_net_part_(Design*des,
|
||||
<< reg->name() << "[" << msb<<":"<<lsb<<"]"
|
||||
<< " is out of range." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
lv = new NetAssign_(reg);
|
||||
lv->set_part(new NetEConst(verinum(loff)), wid);
|
||||
}
|
||||
|
||||
return lv;
|
||||
return true;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_lval_net_idx_up_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*reg) const
|
||||
bool PEIdent::elaborate_lval_net_idx_up_(Design*des,
|
||||
NetScope*scope,
|
||||
NetAssign_*lv) const
|
||||
{
|
||||
assert(lsb_);
|
||||
assert(msb_);
|
||||
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->name() <<
|
||||
" is not a reg/integer/time in " << scope_path(scope) <<
|
||||
"." << endl;
|
||||
cerr << reg->get_line() << ": : " << path_ <<
|
||||
" is declared here as " << reg->type() << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned long wid;
|
||||
calculate_up_do_width_(des, scope, wid);
|
||||
|
||||
NetExpr*base = elab_and_eval(des, scope, msb_, -1);
|
||||
NetExpr*base = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
|
||||
/* Correct the mux for the range of the vector. */
|
||||
if (reg->msb() < reg->lsb())
|
||||
@@ -382,112 +464,30 @@ NetAssign_* PEIdent::elaborate_lval_net_idx_up_(Design*des,
|
||||
else if (reg->lsb() != 0)
|
||||
base = make_add_expr(base, - reg->lsb());
|
||||
|
||||
NetAssign_*lv = new NetAssign_(reg);
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: Set part select width="
|
||||
<< wid << ", base=" << *base << endl;
|
||||
|
||||
lv->set_part(base, wid);
|
||||
|
||||
return lv;
|
||||
return true;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_lval_net_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
NetNet*reg) const
|
||||
bool PEIdent::elaborate_lval_net_idx_do_(Design*des,
|
||||
NetScope*scope,
|
||||
NetAssign_*lv) const
|
||||
{
|
||||
assert(lsb_);
|
||||
assert(msb_);
|
||||
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 0;
|
||||
}
|
||||
|
||||
NetAssign_* PEIdent::elaborate_mem_lval_(Design*des, NetScope*scope,
|
||||
NetMemory*mem) const
|
||||
{
|
||||
if (idx_.empty()) {
|
||||
cerr << get_line() << ": error: Assign to memory \""
|
||||
<< mem->name() << "\" requires a word select index."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (idx_.size() != mem->dimensions()) {
|
||||
cerr << get_line() << ": error: " << idx_.size()
|
||||
<< " indices do not properly address a "
|
||||
<< mem->dimensions() << "-dimension memory/array."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// XXXX For now, require exactly 1 index.
|
||||
assert(idx_.size() == 1);
|
||||
|
||||
/* Elaborate the address expression. */
|
||||
NetExpr*ix = elab_and_eval(des, scope, idx_[0], -1);
|
||||
if (ix == 0)
|
||||
return 0;
|
||||
|
||||
NetAssign_*lv = new NetAssign_(mem);
|
||||
lv->set_bmux(ix);
|
||||
|
||||
/* If there is no extra part select, then we are done. */
|
||||
if (msb_ == 0 && lsb_ == 0) {
|
||||
lv->set_part(0, mem->width());
|
||||
return lv;
|
||||
}
|
||||
|
||||
assert(sel_ != SEL_NONE);
|
||||
assert(msb_ && lsb_);
|
||||
|
||||
if (sel_ == SEL_PART) {
|
||||
NetExpr*le = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetExpr*me = elab_and_eval(des, scope, msb_, -1);
|
||||
|
||||
NetEConst*lec = dynamic_cast<NetEConst*>(le);
|
||||
NetEConst*mec = dynamic_cast<NetEConst*>(me);
|
||||
|
||||
if (lec == 0 || mec == 0) {
|
||||
cerr << get_line() << ": error: Part select "
|
||||
<< "expressions must be constant." << endl;
|
||||
des->errors += 1;
|
||||
delete le;
|
||||
delete me;
|
||||
return lv;
|
||||
}
|
||||
|
||||
verinum wedv = mec->value() - lec->value();
|
||||
unsigned wid = wedv.as_long() + 1;
|
||||
|
||||
lv->set_part(lec, wid);
|
||||
return lv;
|
||||
}
|
||||
|
||||
assert(sel_ == SEL_IDX_UP || sel_ == SEL_IDX_DO);
|
||||
|
||||
NetExpr*wid_ex = elab_and_eval(des, scope, lsb_, -1);
|
||||
NetEConst*wid_ec = dynamic_cast<NetEConst*> (wid_ex);
|
||||
if (wid_ec == 0) {
|
||||
cerr << lsb_->get_line() << ": error: "
|
||||
<< "Second expression of indexed part select "
|
||||
<< "most be constant." << endl;
|
||||
des->errors += 1;
|
||||
return lv;
|
||||
}
|
||||
|
||||
unsigned wid = wid_ec->value().as_ulong();
|
||||
|
||||
NetExpr*base_ex = elab_and_eval(des, scope, msb_, -1);
|
||||
if (base_ex == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (sel_ == SEL_IDX_DO && wid > 1) {
|
||||
base_ex = make_add_expr(base_ex, 1-(long)wid);
|
||||
}
|
||||
|
||||
lv->set_part(base_ex, wid);
|
||||
return lv;
|
||||
return false;
|
||||
}
|
||||
|
||||
NetAssign_* PENumber::elaborate_lval(Design*des, NetScope*, bool) const
|
||||
@@ -500,6 +500,31 @@ 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
|
||||
|
||||
+373
-153
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1999-2005 Stephen Williams ([email protected])
|
||||
* Copyright (c) 1999-2007 Stephen Williams ([email protected])
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_net.cc,v 1.191 2006/12/08 03:43:26 steve Exp $"
|
||||
#ident "$Id: elab_net.cc,v 1.207 2007/06/12 04:05:45 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -28,6 +28,7 @@
|
||||
# include "compiler.h"
|
||||
|
||||
# include <iostream>
|
||||
# include "ivl_assert.h"
|
||||
|
||||
/*
|
||||
* This is a state flag that determines whether an elaborate_net must
|
||||
@@ -760,7 +761,7 @@ NetNet* PEBinary::elaborate_net_div_(Design*des, NetScope*scope,
|
||||
|
||||
// Make an output signal that is the width of the l-value.
|
||||
// Due to above calculation of rwidth, we know that the result
|
||||
// will be no more then the l-value, so it is safe to connect
|
||||
// will be no more than the l-value, so it is safe to connect
|
||||
// all the result pins to the osig.
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
@@ -947,14 +948,17 @@ NetNet* PEBinary::elaborate_net_mul_(Design*des, NetScope*scope,
|
||||
}
|
||||
|
||||
NetConst*odev = new NetConst(scope, scope->local_symbol(), res);
|
||||
des->add_node(odev);
|
||||
odev->set_line(*this);
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, lwidth);
|
||||
for (unsigned idx = 0 ; idx < lwidth ; idx += 1)
|
||||
connect(odev->pin(idx), osig->pin(idx));
|
||||
|
||||
des->add_node(odev);
|
||||
osig->data_type(IVL_VT_LOGIC);
|
||||
osig->set_line(*this);
|
||||
osig->local_flag(true);
|
||||
osig->data_type(IVL_VT_LOGIC);
|
||||
|
||||
connect(odev->pin(0), osig->pin(0));
|
||||
|
||||
return osig;
|
||||
}
|
||||
|
||||
@@ -1096,6 +1100,8 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, 1);
|
||||
tmp->data_type( data_type );
|
||||
tmp->local_flag(true);
|
||||
tmp->set_line(*this);
|
||||
connect(sign_bit->pin(0), tmp->pin(0));
|
||||
connect(sign_bit->pin(0), sign_pad->pin(1));
|
||||
|
||||
@@ -1141,6 +1147,13 @@ NetNet* PEBinary::elaborate_net_shift_(Design*des, NetScope*scope,
|
||||
|
||||
des->add_node(part);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Elaborate shift "
|
||||
<< "(" << op_ << ") as concatenation of "
|
||||
<< pad_width << " zeros with " << part_width
|
||||
<< " bits of expression." << endl;
|
||||
}
|
||||
|
||||
/* Attach a signal to the part select output (NetConcat
|
||||
input) */
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
@@ -1217,7 +1230,7 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
|
||||
unsigned errors = 0;
|
||||
unsigned func_pins = 0;
|
||||
|
||||
if (path_.peek_name(0)[0] == '$')
|
||||
if (path_.front().name[0] == '$')
|
||||
return elaborate_net_sfunc_(des, scope,
|
||||
width, rise, fall, decay,
|
||||
drive0, drive1);
|
||||
@@ -1227,7 +1240,7 @@ NetNet* PECallFunction::elaborate_net(Design*des, NetScope*scope,
|
||||
NetFuncDef*def = des->find_function(scope, path_);
|
||||
if (def == 0) {
|
||||
cerr << get_line() << ": error: No function " << path_ <<
|
||||
" in this context (" << scope->name() << ")." << endl;
|
||||
" in this context (" << scope_path(scope) << ")." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -1307,11 +1320,13 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const
|
||||
{
|
||||
perm_string name = peek_tail_name(path_);
|
||||
|
||||
/* Handle the special case that the function call is to
|
||||
$signed. This takes a single expression argument, and
|
||||
forces it to be a signed result. Otherwise, it is as if the
|
||||
$signed did not exist. */
|
||||
if (strcmp(path_.peek_name(0), "$signed") == 0) {
|
||||
if (strcmp(name, "$signed") == 0) {
|
||||
if ((parms_.count() != 1) || (parms_[0] == 0)) {
|
||||
cerr << get_line() << ": error: The $signed() function "
|
||||
<< "takes exactly one(1) argument." << endl;
|
||||
@@ -1327,7 +1342,7 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
|
||||
}
|
||||
|
||||
/* handle $unsigned like $signed */
|
||||
if (strcmp(path_.peek_name(0), "$unsigned") == 0) {
|
||||
if (strcmp(name, "$unsigned") == 0) {
|
||||
if ((parms_.count() != 1) || (parms_[0] == 0)) {
|
||||
cerr << get_line() << ": error: The $unsigned() function "
|
||||
<< "takes exactly one(1) argument." << endl;
|
||||
@@ -1342,11 +1357,11 @@ NetNet* PECallFunction::elaborate_net_sfunc_(Design*des, NetScope*scope,
|
||||
return sub;
|
||||
}
|
||||
|
||||
const struct sfunc_return_type*def = lookup_sys_func(path_.peek_name(0));
|
||||
const struct sfunc_return_type*def = lookup_sys_func(name);
|
||||
|
||||
if (def == 0) {
|
||||
cerr << get_line() << ": error: System function "
|
||||
<< path_.peek_name(0) << " not defined." << endl;
|
||||
<< peek_tail_name(path_) << " not defined." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -1407,7 +1422,7 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
|
||||
NetEConst*erep = dynamic_cast<NetEConst*>(etmp);
|
||||
|
||||
if (erep == 0) {
|
||||
cerr << get_line() << ": internal error: Unable to "
|
||||
cerr << get_line() << ": error: Unable to "
|
||||
<< "evaluate constant repeat expression." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
@@ -1497,7 +1512,7 @@ NetNet* PEConcat::elaborate_net(Design*des, NetScope*scope,
|
||||
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 then 1 by repeating the
|
||||
Allow for a repeat count other than 1 by repeating the
|
||||
connect loop as many times as necessary. */
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
@@ -1532,15 +1547,19 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const
|
||||
{
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_.size() == 1);
|
||||
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.sel == index_component_t::SEL_BIT);
|
||||
ivl_assert(*this, index_tail.msb != 0);
|
||||
ivl_assert(*this, index_tail.lsb == 0);
|
||||
|
||||
/* Elaborate the selector. */
|
||||
NetNet*sel;
|
||||
|
||||
if (sig->msb() < sig->lsb()) {
|
||||
NetExpr*sel_expr = idx_[0]->elaborate_expr(des, scope, -1, false);
|
||||
NetExpr*sel_expr = index_tail.msb->elaborate_expr(des, scope, -1, false);
|
||||
sel_expr = make_sub_expr(sig->lsb(), sel_expr);
|
||||
if (NetExpr*tmp = sel_expr->eval_tree()) {
|
||||
delete sel_expr;
|
||||
@@ -1550,7 +1569,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
|
||||
sel = sel_expr->synthesize(des);
|
||||
|
||||
} else if (sig->lsb() != 0) {
|
||||
NetExpr*sel_expr = idx_[0]->elaborate_expr(des, scope, -1,false);
|
||||
NetExpr*sel_expr = index_tail.msb->elaborate_expr(des, scope, -1,false);
|
||||
sel_expr = make_add_expr(sel_expr, - sig->lsb());
|
||||
if (NetExpr*tmp = sel_expr->eval_tree()) {
|
||||
delete sel_expr;
|
||||
@@ -1560,7 +1579,7 @@ NetNet* PEIdent::elaborate_net_bitmux_(Design*des, NetScope*scope,
|
||||
sel = sel_expr->synthesize(des);
|
||||
|
||||
} else {
|
||||
sel = idx_[0]->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
sel = index_tail.msb->elaborate_net(des, scope, 0, 0, 0, 0);
|
||||
}
|
||||
|
||||
if (debug_elaborate) {
|
||||
@@ -1591,21 +1610,15 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
||||
Link::strength_t drive0,
|
||||
Link::strength_t drive1) const
|
||||
{
|
||||
assert(scope);
|
||||
ivl_assert(*this, scope);
|
||||
|
||||
const name_component_t&name_tail = path_.back();
|
||||
|
||||
NetNet* sig = 0;
|
||||
NetMemory* mem = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(des, scope, path_, sig, mem, par, eve);
|
||||
|
||||
/* If the identifier is a memory instead of a signal,
|
||||
then handle it elsewhere. Create a RAM. */
|
||||
if (mem != 0) {
|
||||
return elaborate_net_ram_(des, scope, mem, lwidth,
|
||||
rise, fall, decay);
|
||||
}
|
||||
symbol_search(des, scope, path_, sig, par, eve);
|
||||
|
||||
/* If this is a parameter name, then create a constant node
|
||||
that connects to a signal with the correct name. */
|
||||
@@ -1615,7 +1628,7 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
||||
assert(pc);
|
||||
verinum pvalue = pc->value();
|
||||
|
||||
/* If the desired lwidth is more then the width of the
|
||||
/* If the desired lwidth is more than the width of the
|
||||
constant value, extend the value to fit the desired
|
||||
output. */
|
||||
if (lwidth > pvalue.len()) {
|
||||
@@ -1641,15 +1654,16 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
||||
/* Check for the error case that the name is not found, and it
|
||||
is hierarchical. We can't just create a name in another
|
||||
scope, it's just not allowed. */
|
||||
if (sig == 0 && path_.component_count() != 1) {
|
||||
if (sig == 0 && path_.size() != 1) {
|
||||
cerr << get_line() << ": error: The hierarchical name "
|
||||
<< path_ << " is undefined in "
|
||||
<< scope->name() << "." << endl;
|
||||
<< scope_path(scope) << "." << endl;
|
||||
|
||||
hname_t tmp_path = path_;
|
||||
delete[] tmp_path.remove_tail_name();
|
||||
pform_name_t tmp_path = path_;
|
||||
tmp_path.pop_back();
|
||||
|
||||
NetScope*tmp_scope = des->find_scope(scope, tmp_path);
|
||||
list<hname_t> stmp_path = eval_scope_path(des, scope, tmp_path);
|
||||
NetScope*tmp_scope = des->find_scope(scope, stmp_path);
|
||||
if (tmp_scope == 0) {
|
||||
cerr << get_line() << ": : I can't even find "
|
||||
<< "the scope " << tmp_path << "." << endl;
|
||||
@@ -1662,33 +1676,49 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
||||
/* Fallback, this may be an implicitly declared net. */
|
||||
if (sig == 0) {
|
||||
NetNet::Type nettype = scope->default_nettype();
|
||||
sig = new NetNet(scope, lex_strings.make(path_.peek_name(0)),
|
||||
sig = new NetNet(scope, name_tail.name,
|
||||
nettype, 1);
|
||||
sig->data_type(IVL_VT_LOGIC);
|
||||
|
||||
if (error_implicit || (nettype == NetNet::NONE)) {
|
||||
cerr << get_line() << ": error: "
|
||||
<< scope->name() << "." << path_.peek_name(0)
|
||||
<< scope_path(scope) << "." << name_tail.name
|
||||
<< " not defined in this scope." << endl;
|
||||
des->errors += 1;
|
||||
|
||||
} else if (warn_implicit) {
|
||||
cerr << get_line() << ": warning: implicit "
|
||||
"definition of wire " << scope->name()
|
||||
<< "." << path_.peek_name(0) << "." << endl;
|
||||
"definition of wire " << scope_path(scope)
|
||||
<< "." << name_tail.name << "." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
assert(sig);
|
||||
ivl_assert(*this, sig);
|
||||
|
||||
/* Handle the case that this is an array elsewhere. */
|
||||
if (sig->array_dimensions() > 0) {
|
||||
if (name_tail.index.size() == 0) {
|
||||
cerr << get_line() << ": error: Array " << sig->name()
|
||||
<< " cannot be used here without an index." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return elaborate_net_array_(des, scope, sig, lwidth,
|
||||
rise, fall, decay,
|
||||
drive0, drive1);
|
||||
}
|
||||
|
||||
index_component_t::ctype_t use_sel = index_component_t::SEL_NONE;
|
||||
if (!name_tail.index.empty())
|
||||
use_sel = name_tail.index.back().sel;
|
||||
|
||||
/* Catch the case of a non-constant bit select. That should be
|
||||
handled elsewhere. */
|
||||
if (! idx_.empty()) {
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_.size() == 1);
|
||||
if (use_sel == index_component_t::SEL_BIT) {
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
|
||||
verinum*mval = idx_[0]->eval_const(des, scope);
|
||||
verinum*mval = index_tail.msb->eval_const(des, scope);
|
||||
if (mval == 0) {
|
||||
return elaborate_net_bitmux_(des, scope, sig, rise,
|
||||
fall, decay, drive0, drive1);
|
||||
@@ -1728,68 +1758,174 @@ NetNet* PEIdent::elaborate_net(Design*des, NetScope*scope,
|
||||
return sig;
|
||||
}
|
||||
|
||||
/*
|
||||
* When I run into an identifier in an expression that refers to a
|
||||
* memory, create a RAM port object.
|
||||
*/
|
||||
NetNet* PEIdent::elaborate_net_ram_(Design*des, NetScope*scope,
|
||||
NetMemory*mem, unsigned lwidth,
|
||||
const NetExpr* rise,
|
||||
const NetExpr* fall,
|
||||
const NetExpr* decay) const
|
||||
NetNet* PEIdent::process_select_(Design*des, NetScope*scope,
|
||||
NetNet*sig) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
if (idx_.empty()) {
|
||||
cerr << get_line() << ": error: memory reference without"
|
||||
" the required index expression." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
// If there are more index items then there are array
|
||||
// dimensions, then treat them as word part selects. For
|
||||
// example, if this is a memory array, then array dimensions
|
||||
// is 1 and
|
||||
unsigned midx, lidx;
|
||||
if (! eval_part_select_(des, scope, sig, midx, lidx))
|
||||
return sig;
|
||||
|
||||
unsigned part_count = midx-lidx+1;
|
||||
|
||||
// Maybe this is a full-width constant part select? If
|
||||
// so, do nothing.
|
||||
if (part_count == sig->vector_width())
|
||||
return sig;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Elaborate part select"
|
||||
<< " of word from " << sig->name() << "[base="<<lidx
|
||||
<< " wid=" << part_count << "]" << endl;
|
||||
}
|
||||
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_.size() == 1);
|
||||
NetPartSelect*ps = new NetPartSelect(sig, lidx, part_count,
|
||||
NetPartSelect::VP);
|
||||
ps->set_line(*sig);
|
||||
des->add_node(ps);
|
||||
|
||||
/* Even if this expression must be fully self determined, the
|
||||
index expression does not, so make sure this flag is off
|
||||
while elaborating the address expression. */
|
||||
const bool must_be_self_determined_save = must_be_self_determined_flag;
|
||||
must_be_self_determined_flag = false;
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, part_count-1, 0);
|
||||
tmp->data_type( sig->data_type() );
|
||||
tmp->local_flag(true);
|
||||
connect(tmp->pin(0), ps->pin(0));
|
||||
|
||||
NetExpr*adr_expr = elab_and_eval(des, scope, idx_[0], -1);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/* If an offset is needed, subtract it from the address to get
|
||||
an expression for the canonical address. */
|
||||
if (mem->index_to_address(0) != 0) {
|
||||
adr_expr = make_add_expr(adr_expr, mem->index_to_address(0));
|
||||
if (NetExpr*tmp = adr_expr->eval_tree()) {
|
||||
delete adr_expr;
|
||||
adr_expr = tmp;
|
||||
NetNet* PEIdent::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
|
||||
{
|
||||
const name_component_t&name_tail = path_.back();
|
||||
ivl_assert(*this, name_tail.index.size() >= 1);
|
||||
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);
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: elaborate array "
|
||||
<< name_tail.name << " with index " << index_head << endl;
|
||||
|
||||
NetExpr*index_ex = elab_and_eval(des, scope, index_head.msb, -1);
|
||||
if (index_ex == 0)
|
||||
return 0;
|
||||
|
||||
if (NetEConst*index_co = dynamic_cast<NetEConst*> (index_ex)) {
|
||||
long index = index_co->value().as_long();
|
||||
|
||||
if (!sig->array_index_is_valid(index)) {
|
||||
// Oops! The index is a constant known to be
|
||||
// outside the array. Change the expression to a
|
||||
// constant X vector.
|
||||
verinum xxx (verinum::Vx, sig->vector_width());
|
||||
NetConst*con_n = new NetConst(scope, scope->local_symbol(), xxx);
|
||||
des->add_node(con_n);
|
||||
con_n->set_line(*index_co);
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, sig->vector_width());
|
||||
tmp->set_line(*this);
|
||||
tmp->local_flag(true);
|
||||
tmp->data_type(sig->data_type());
|
||||
connect(tmp->pin(0), con_n->pin(0));
|
||||
return tmp;
|
||||
}
|
||||
|
||||
assert(sig->array_index_is_valid(index));
|
||||
index = sig->array_index_to_address(index);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Elaborate word "
|
||||
<< index << " of " << sig->name() << endl;
|
||||
}
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, sig->vector_width());
|
||||
tmp->set_line(*this);
|
||||
tmp->local_flag(true);
|
||||
tmp->data_type(sig->data_type());
|
||||
connect(tmp->pin(0), sig->pin(index));
|
||||
|
||||
// If there are more indices then needed to get to the
|
||||
// word, then there is a part/bit select for the word.
|
||||
if (name_tail.index.size() > sig->array_dimensions())
|
||||
tmp = process_select_(des, scope, tmp);
|
||||
|
||||
return tmp;
|
||||
}
|
||||
NetNet*adr = adr_expr->synthesize(des);
|
||||
delete adr_expr;
|
||||
|
||||
must_be_self_determined_flag = must_be_self_determined_save;
|
||||
unsigned selwid = index_ex->expr_width();
|
||||
|
||||
if (adr == 0)
|
||||
return 0;
|
||||
NetArrayDq*mux = new NetArrayDq(scope, scope->local_symbol(),
|
||||
sig, selwid);
|
||||
mux->set_line(*this);
|
||||
des->add_node(mux);
|
||||
|
||||
NetRamDq*ram = new NetRamDq(scope, scope->local_symbol(),
|
||||
mem, adr->vector_width());
|
||||
des->add_node(ram);
|
||||
// Adjust the expression to calculate the canonical offset?
|
||||
if (long array_base = sig->array_first()) {
|
||||
index_ex = make_add_expr(index_ex, 0-array_base);
|
||||
}
|
||||
|
||||
connect(ram->pin_Address(), adr->pin(0));
|
||||
NetNet*index_net = index_ex->synthesize(des);
|
||||
connect(mux->pin_Address(), index_net->pin(0));
|
||||
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, ram->width());
|
||||
osig->data_type(IVL_VT_LOGIC);
|
||||
osig->local_flag(true);
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, sig->vector_width());
|
||||
tmp->set_line(*this);
|
||||
tmp->local_flag(true);
|
||||
tmp->data_type(sig->data_type());
|
||||
connect(tmp->pin(0), mux->pin_Result());
|
||||
#if 0
|
||||
|
||||
connect(ram->pin_Q(), osig->pin(0));
|
||||
// If there are more index items then there are array
|
||||
// dimensions, then treat them as word part selects. For
|
||||
// example, if this is a memory array, then array dimensions
|
||||
// is 1 and
|
||||
unsigned midx, lidx;
|
||||
if (eval_part_select_(des, scope, sig, midx, lidx)) do {
|
||||
|
||||
return osig;
|
||||
unsigned part_count = midx-lidx+1;
|
||||
|
||||
// Maybe this is a full-width constant part select? If
|
||||
// so, do nothing.
|
||||
if (part_count == sig->vector_width())
|
||||
break;
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Elaborate part select"
|
||||
<< " of word from " << sig->name() << "[base="<<lidx
|
||||
<< " wid=" << part_count << "]" << endl;
|
||||
}
|
||||
|
||||
NetPartSelect*ps = new NetPartSelect(sig, lidx, part_count,
|
||||
NetPartSelect::VP);
|
||||
ps->set_line(*sig);
|
||||
des->add_node(ps);
|
||||
|
||||
NetNet*tmp2 = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, part_count-1, 0);
|
||||
tmp2->data_type( tmp->data_type() );
|
||||
tmp2->local_flag(true);
|
||||
connect(tmp2->pin(0), ps->pin(0));
|
||||
|
||||
tmp = tmp2;
|
||||
} while (0);
|
||||
#else
|
||||
if (name_tail.index.size() > sig->array_dimensions())
|
||||
tmp = process_select_(des, scope, sig);
|
||||
|
||||
#endif
|
||||
return tmp;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1864,6 +2000,8 @@ NetNet* PEConcat::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
/* Assume that the data types of the nets are all the same, so
|
||||
we can take the data type of any, the first will do. */
|
||||
osig->data_type(nets[0]->data_type());
|
||||
osig->local_flag(true);
|
||||
osig->set_line(*this);
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Generating part selects "
|
||||
@@ -1942,15 +2080,15 @@ NetNet* PEIdent::make_implicit_net_(Design*des, NetScope*scope) const
|
||||
NetNet*sig = 0;
|
||||
|
||||
if (!error_implicit && nettype!=NetNet::NONE) {
|
||||
sig = new NetNet(scope, lex_strings.make(path_.peek_name(0)),
|
||||
sig = new NetNet(scope, peek_tail_name(path_),
|
||||
NetNet::IMPLICIT, 1);
|
||||
/* Implicit nets are always scalar logic. */
|
||||
sig->data_type(IVL_VT_LOGIC);
|
||||
|
||||
if (warn_implicit) {
|
||||
cerr << get_line() << ": warning: implicit "
|
||||
"definition of wire logic " << scope->name()
|
||||
<< "." << path_.peek_name(0) << "." << endl;
|
||||
"definition of wire logic " << scope_path(scope)
|
||||
<< "." << peek_tail_name(path_) << "." << endl;
|
||||
}
|
||||
|
||||
} else {
|
||||
@@ -1973,20 +2111,30 @@ NetNet* PEIdent::make_implicit_net_(Design*des, NetScope*scope) const
|
||||
bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
unsigned&midx, unsigned&lidx) const
|
||||
{
|
||||
switch (sel_) {
|
||||
const name_component_t&name_tail = path_.back();
|
||||
// Only treat as part/bit selects any index that is beyond the
|
||||
// word selects for an array. This is not an array, then
|
||||
// dimensions==0 and any index is treated as a select.
|
||||
if (name_tail.index.size() <= sig->array_dimensions()) {
|
||||
midx = sig->vector_width()-1;
|
||||
lidx = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
ivl_assert(*this, !name_tail.index.empty());
|
||||
|
||||
const index_component_t&index_tail = name_tail.index.back();
|
||||
|
||||
switch (index_tail.sel) {
|
||||
default:
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Unexpected sel_ value = " << sel_ << endl;
|
||||
assert(0);
|
||||
<< "Unexpected sel_ value = " << index_tail.sel << endl;
|
||||
ivl_assert(*this, 0);
|
||||
break;
|
||||
|
||||
case PEIdent::SEL_IDX_DO:
|
||||
case PEIdent::SEL_IDX_UP: {
|
||||
assert(msb_);
|
||||
assert(lsb_);
|
||||
assert(idx_.empty());
|
||||
|
||||
NetExpr*tmp_ex = elab_and_eval(des, scope, msb_, -1);
|
||||
case index_component_t::SEL_IDX_DO:
|
||||
case index_component_t::SEL_IDX_UP: {
|
||||
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||
assert(tmp);
|
||||
|
||||
@@ -1994,14 +2142,14 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
midx = sig->sb_to_idx(midx_val);
|
||||
delete tmp_ex;
|
||||
|
||||
tmp_ex = elab_and_eval(des, scope, lsb_, -1);
|
||||
tmp_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
|
||||
tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||
assert(tmp);
|
||||
|
||||
long wid = tmp->value().as_long();
|
||||
delete tmp_ex;
|
||||
|
||||
if (sel_ == PEIdent::SEL_IDX_UP)
|
||||
if (index_tail.sel == index_component_t::SEL_IDX_UP)
|
||||
lidx = sig->sb_to_idx(midx_val+wid-1);
|
||||
else
|
||||
lidx = sig->sb_to_idx(midx_val-wid+1);
|
||||
@@ -2015,12 +2163,9 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
break;
|
||||
}
|
||||
|
||||
case PEIdent::SEL_PART: {
|
||||
assert(msb_);
|
||||
assert(lsb_);
|
||||
assert(idx_.empty());
|
||||
case index_component_t::SEL_PART: {
|
||||
|
||||
NetExpr*tmp_ex = elab_and_eval(des, scope, msb_, -1);
|
||||
NetExpr*tmp_ex = elab_and_eval(des, scope, index_tail.msb, -1);
|
||||
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||
assert(tmp);
|
||||
|
||||
@@ -2028,12 +2173,12 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
midx = sig->sb_to_idx(midx_val);
|
||||
delete tmp_ex;
|
||||
|
||||
tmp_ex = elab_and_eval(des, scope, lsb_, -1);
|
||||
tmp_ex = elab_and_eval(des, scope, index_tail.lsb, -1);
|
||||
tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||
if (tmp == 0) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "lsb expression is not constant?: "
|
||||
<< *tmp_ex << ", " << *lsb_ << endl;
|
||||
<< *tmp_ex << ", " << *index_tail.lsb << endl;
|
||||
}
|
||||
assert(tmp);
|
||||
|
||||
@@ -2067,18 +2212,17 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
break;
|
||||
}
|
||||
|
||||
case PEIdent::SEL_NONE:
|
||||
if (!idx_.empty()) {
|
||||
assert(msb_ == 0);
|
||||
assert(lsb_ == 0);
|
||||
assert(idx_.size() == 1);
|
||||
verinum*mval = idx_[0]->eval_const(des, scope);
|
||||
case index_component_t::SEL_BIT:
|
||||
if (name_tail.index.size() > sig->array_dimensions()) {
|
||||
verinum*mval = index_tail.msb->eval_const(des, scope);
|
||||
if (mval == 0) {
|
||||
cerr << get_line() << ": error: Index of " << path_ <<
|
||||
" needs to be constant in this context." <<
|
||||
endl;
|
||||
cerr << get_line() << ": : Index expression is: "
|
||||
<< *(idx_[0]) << endl;
|
||||
<< *index_tail.msb << endl;
|
||||
cerr << get_line() << ": : Context scope is: "
|
||||
<< scope_path(scope) << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
@@ -2095,17 +2239,9 @@ bool PEIdent::eval_part_select_(Design*des, NetScope*scope, NetNet*sig,
|
||||
lidx = midx;
|
||||
|
||||
} else {
|
||||
if (msb_ || lsb_) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Unexpected msb_/lsb_ values?" << endl;
|
||||
if (msb_)
|
||||
cerr << get_line() << " : "
|
||||
<< *msb_ << endl;
|
||||
if (lsb_)
|
||||
cerr << get_line() << " : "
|
||||
<< *lsb_ << endl;
|
||||
}
|
||||
assert(msb_ == 0 && lsb_ == 0);
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Bit select " << path_ << endl;
|
||||
ivl_assert(*this, 0);
|
||||
midx = sig->vector_width() - 1;
|
||||
lidx = 0;
|
||||
}
|
||||
@@ -2127,19 +2263,10 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
assert(scope);
|
||||
|
||||
NetNet* sig = 0;
|
||||
NetMemory* mem = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
symbol_search(des, scope, path_, sig, mem, par, eve);
|
||||
|
||||
if (mem != 0) {
|
||||
cerr << get_line() << ": error: memories (" << path_
|
||||
<< ") cannot be l-values in continuous "
|
||||
<< "assignments." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
symbol_search(des, scope, path_, sig, par, eve);
|
||||
|
||||
if (eve != 0) {
|
||||
cerr << get_line() << ": error: named events (" << path_
|
||||
@@ -2184,12 +2311,50 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
sig->port_type(NetNet::PINOUT);
|
||||
}
|
||||
|
||||
unsigned midx, lidx;
|
||||
if (! eval_part_select_(des, scope, sig, midx, lidx))
|
||||
return 0;
|
||||
// Default part select is the entire word.
|
||||
unsigned midx = sig->vector_width()-1, lidx = 0;
|
||||
// The default word select is the first.
|
||||
unsigned widx = 0;
|
||||
|
||||
const name_component_t&name_tail = path_.back();
|
||||
|
||||
if (sig->array_dimensions() > 0) {
|
||||
|
||||
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);
|
||||
|
||||
NetExpr*tmp_ex = elab_and_eval(des, scope, index_head.msb, -1);
|
||||
NetEConst*tmp = dynamic_cast<NetEConst*>(tmp_ex);
|
||||
assert(tmp);
|
||||
|
||||
long widx_val = tmp->value().as_long();
|
||||
widx = sig->array_index_to_address(widx_val);
|
||||
delete tmp_ex;
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: Use [" << widx << "]"
|
||||
<< " to index l-value array." << endl;
|
||||
|
||||
} else if (!name_tail.index.empty()) {
|
||||
if (! eval_part_select_(des, scope, sig, midx, lidx))
|
||||
return 0;
|
||||
}
|
||||
|
||||
unsigned subnet_wid = midx-lidx+1;
|
||||
|
||||
if (sig->pin_count() > 1) {
|
||||
assert(widx < sig->pin_count());
|
||||
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
sig->type(), sig->vector_width());
|
||||
tmp->set_line(*this);
|
||||
tmp->local_flag(true);
|
||||
connect(sig->pin(widx), tmp->pin(0));
|
||||
sig = tmp;
|
||||
}
|
||||
|
||||
/* If the desired l-value vector is narrower then the
|
||||
signal itself, then use a NetPartSelect node to
|
||||
arrange for connection to the desired bits. All this
|
||||
@@ -2218,6 +2383,8 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope,
|
||||
sig->scope()->local_symbol(),
|
||||
NetNet::WIRE, subnet_wid);
|
||||
subsig->data_type( sig->data_type() );
|
||||
subsig->local_flag(true);
|
||||
subsig->set_line(*this);
|
||||
|
||||
NetPartSelect*sub = new NetPartSelect(sig, lidx, subnet_wid,
|
||||
part_dir);
|
||||
@@ -2258,7 +2425,7 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
|
||||
NetNet*sig = des->find_signal(scope, path_);
|
||||
if (sig == 0) {
|
||||
cerr << get_line() << ": error: no wire/reg " << path_
|
||||
<< " in module " << scope->name() << "." << endl;
|
||||
<< " in module " << scope_path(scope) << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -2277,7 +2444,7 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
|
||||
|
||||
case NetNet::NOT_A_PORT:
|
||||
cerr << get_line() << ": error: signal " << path_ << " in"
|
||||
<< " module " << scope->name() << " is not a port." << endl;
|
||||
<< " module " << scope_path(scope) << " is not a port." << endl;
|
||||
cerr << get_line() << ": : Are you missing an input/"
|
||||
<< "output/inout declaration?" << endl;
|
||||
des->errors += 1;
|
||||
@@ -2289,7 +2456,7 @@ NetNet* PEIdent::elaborate_port(Design*des, NetScope*scope) const
|
||||
|
||||
case NetNet::PIMPLICIT:
|
||||
cerr << get_line() << ": internal error: signal " << path_
|
||||
<< " in module " << scope->name() << " is left as "
|
||||
<< " in module " << scope_path(scope) << " is left as "
|
||||
<< "port type PIMPLICIT." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
@@ -2619,7 +2786,8 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
|
||||
if (rise || fall || decay) {
|
||||
NetNet*tmp = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, dwidth);
|
||||
sig->data_type(expr_type);
|
||||
tmp->data_type(expr_type);
|
||||
tmp->local_flag(true);
|
||||
|
||||
NetBUFZ*tmpz = new NetBUFZ(scope, scope->local_symbol(), dwidth);
|
||||
tmpz->rise_time(rise);
|
||||
@@ -2646,8 +2814,8 @@ NetNet* PETernary::elaborate_net(Design*des, NetScope*scope,
|
||||
|
||||
/* If the MUX device results is too narrow to fill out the
|
||||
desired result, then pad it. It is OK to have a too-narrow
|
||||
result here because the dwidth choise is >= the width of
|
||||
both alternatives. Thus, padding here is equivilent to
|
||||
result here because the dwidth choice is >= the width of
|
||||
both alternatives. Thus, padding here is equivalent to
|
||||
padding inside, and is cheaper. */
|
||||
if (dwidth < width)
|
||||
sig = pad_to_width(des, sig, width);
|
||||
@@ -2850,6 +3018,58 @@ NetNet* PEUnary::elaborate_net(Design*des, NetScope*scope,
|
||||
|
||||
/*
|
||||
* $Log: elab_net.cc,v $
|
||||
* Revision 1.207 2007/06/12 04:05:45 steve
|
||||
* Put instantiated modules in the proper generated scope.
|
||||
*
|
||||
* Revision 1.206 2007/06/04 02:19:07 steve
|
||||
* Handle bit/part select of array words in nets.
|
||||
*
|
||||
* Revision 1.205 2007/06/02 03:42:12 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.204 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.203 2007/04/18 01:40:49 steve
|
||||
* Fix elaboration of multiply of two constants.
|
||||
*
|
||||
* Revision 1.202 2007/04/17 04:18:10 steve
|
||||
* Support part select of array words in net contexts.
|
||||
*
|
||||
* Revision 1.201 2007/03/22 16:08:14 steve
|
||||
* Spelling fixes from Larry
|
||||
*
|
||||
* Revision 1.200 2007/02/27 06:10:16 steve
|
||||
* Better error message around repeat concatenation syntax.
|
||||
*
|
||||
* Revision 1.199 2007/02/26 19:49:48 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.198 2007/02/05 01:42:31 steve
|
||||
* Set some missing local flags.
|
||||
*
|
||||
* Revision 1.197 2007/02/01 19:06:06 steve
|
||||
* Ternary output node is local.
|
||||
*
|
||||
* Revision 1.196 2007/02/01 03:14:33 steve
|
||||
* Detect and report arrays without index in net contexts.
|
||||
*
|
||||
* Revision 1.195 2007/01/31 04:21:10 steve
|
||||
* Add method to bind assertions to verilog source lines.
|
||||
*
|
||||
* Revision 1.194 2007/01/20 02:10:45 steve
|
||||
* Get argument widths right for shift results.
|
||||
*
|
||||
* Revision 1.193 2007/01/19 04:26:24 steve
|
||||
* Fix missing data_type mark for array words.
|
||||
*
|
||||
* Revision 1.192 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.191 2006/12/08 03:43:26 steve
|
||||
* Prevent name clash when processing parameter in net.
|
||||
*
|
||||
|
||||
+36
-19
@@ -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.25 2006/11/04 06:19:25 steve Exp $"
|
||||
#ident "$Id: elab_pexpr.cc,v 1.28 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -25,6 +25,7 @@
|
||||
# include "PExpr.h"
|
||||
# include "compiler.h"
|
||||
# include "util.h"
|
||||
# include "netmisc.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
@@ -130,47 +131,53 @@ NetExpr*PEFNumber::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
*/
|
||||
NetExpr*PEIdent::elaborate_pexpr(Design*des, NetScope*scope) const
|
||||
{
|
||||
hname_t path = path_;
|
||||
char*name = path.remove_tail_name();
|
||||
pform_name_t path = path_;
|
||||
name_component_t name_tail = path_.back();
|
||||
path.pop_back();
|
||||
|
||||
NetScope*pscope = scope;
|
||||
if (path.peek_name(0))
|
||||
pscope = des->find_scope(scope, path);
|
||||
|
||||
perm_string perm_name = lex_strings.make(name);
|
||||
delete name;
|
||||
if (path_.size() > 0) {
|
||||
list<hname_t> tmp = eval_scope_path(des, scope, path);
|
||||
pscope = des->find_scope(scope, tmp);
|
||||
}
|
||||
|
||||
const NetExpr*ex_msb;
|
||||
const NetExpr*ex_lsb;
|
||||
const NetExpr*ex = pscope->get_parameter(perm_name, ex_msb, ex_lsb);
|
||||
const NetExpr*ex = pscope->get_parameter(name_tail.name, ex_msb, ex_lsb);
|
||||
if (ex == 0) {
|
||||
cerr << get_line() << ": error: identifier ``" << path_ <<
|
||||
"'' is not a parameter in " << scope->name() << "." << endl;
|
||||
cerr << get_line() << ": error: identifier ``" << name_tail.name <<
|
||||
"'' is not a parameter in "<< scope_path(scope)<< "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetExpr*res = new NetEParam(des, pscope, perm_name);
|
||||
NetExpr*res = new NetEParam(des, pscope, name_tail.name);
|
||||
res->set_line(*this);
|
||||
assert(res);
|
||||
|
||||
if (msb_ && lsb_) {
|
||||
assert(idx_.empty());
|
||||
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:
|
||||
cerr << get_line() << ": sorry: Cannot part select "
|
||||
"bits of parameters." << endl;
|
||||
des->errors += 1;
|
||||
break;
|
||||
|
||||
} else if (!idx_.empty()) {
|
||||
assert(msb_==0);
|
||||
assert(lsb_==0);
|
||||
assert(idx_.size() == 1);
|
||||
case index_component_t::SEL_BIT:
|
||||
|
||||
/* We have here a bit select. Insert a NetESelect node
|
||||
to handle it. */
|
||||
NetExpr*tmp = idx_[0]->elaborate_pexpr(des, scope);
|
||||
NetExpr*tmp = name_tail.index.back().msb->elaborate_pexpr(des, scope);
|
||||
if (tmp != 0) {
|
||||
res = new NetESelect(res, tmp, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
@@ -236,6 +243,16 @@ 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
|
||||
|
||||
+47
-23
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elab_scope.cc,v 1.41 2006/06/02 04:48:50 steve Exp $"
|
||||
#ident "$Id: elab_scope.cc,v 1.46 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -51,7 +51,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
{
|
||||
if (debug_scopes) {
|
||||
cerr << get_line() << ": debug: Elaborate scope "
|
||||
<< scope->name() << "." << endl;
|
||||
<< scope_path(scope) << "." << endl;
|
||||
}
|
||||
|
||||
// Generate all the parameters that this instance of this
|
||||
@@ -66,7 +66,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<hname_t,PExpr*>::const_iterator hparm_it_t;
|
||||
typedef map<pform_name_t,PExpr*>::const_iterator pform_parm_it_t;
|
||||
|
||||
|
||||
// This loop scans the parameters in the module, and creates
|
||||
@@ -156,7 +156,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
if (! flag) {
|
||||
cerr << val->get_line() << ": warning: parameter "
|
||||
<< (*cur).first << " not found in "
|
||||
<< scope->name() << "." << endl;
|
||||
<< scope_path(scope) << "." << endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,7 +200,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 (hparm_it_t cur = defparms.begin()
|
||||
for (pform_parm_it_t cur = defparms.begin()
|
||||
; cur != defparms.end() ; cur ++ ) {
|
||||
|
||||
PExpr*ex = (*cur).second;
|
||||
@@ -243,7 +243,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
for (tasks_it_t cur = tasks_.begin()
|
||||
; cur != tasks_.end() ; cur ++ ) {
|
||||
|
||||
NetScope*task_scope = new NetScope(scope, (*cur).first,
|
||||
hname_t use_name( (*cur).first );
|
||||
NetScope*task_scope = new NetScope(scope, use_name,
|
||||
NetScope::TASK);
|
||||
(*cur).second->elaborate_scope(des, task_scope);
|
||||
}
|
||||
@@ -258,7 +259,8 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
for (funcs_it_t cur = funcs_.begin()
|
||||
; cur != funcs_.end() ; cur ++ ) {
|
||||
|
||||
NetScope*func_scope = new NetScope(scope, (*cur).first,
|
||||
hname_t use_name( (*cur).first );
|
||||
NetScope*func_scope = new NetScope(scope, use_name,
|
||||
NetScope::FUNC);
|
||||
(*cur).second->elaborate_scope(des, func_scope);
|
||||
}
|
||||
@@ -288,7 +290,7 @@ bool Module::elaborate_scope(Design*des, NetScope*scope,
|
||||
}
|
||||
|
||||
// Scan through all the named events in this scope. We do not
|
||||
// need anything more then the current scope to do this
|
||||
// need anything more than the current scope to do this
|
||||
// elaboration, so do it now. This allows for normal
|
||||
// elaboration to reference these events.
|
||||
|
||||
@@ -351,11 +353,7 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
// that each instance has a unique name in the
|
||||
// container. The format of using [] is part of the
|
||||
// Verilog standard.
|
||||
char name_buf[128];
|
||||
snprintf(name_buf, sizeof name_buf,
|
||||
"%s[%d]", scope_name.str(), genvar);
|
||||
perm_string use_name = lex_strings.make(name_buf);
|
||||
|
||||
hname_t use_name (scope_name, genvar);
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Create generated scope " << use_name << endl;
|
||||
@@ -374,6 +372,19 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
||||
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);
|
||||
@@ -418,7 +429,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(get_name())) {
|
||||
if (sc->child(hname_t(get_name()))) {
|
||||
cerr << get_line() << ": error: Instance/Scope name " <<
|
||||
get_name() << " already used in this context." <<
|
||||
endl;
|
||||
@@ -441,8 +452,8 @@ 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 "
|
||||
<< sc->name() << "." << get_name() << " within "
|
||||
<< scn->name() << "." << endl;
|
||||
<< scope_path(sc) << "." << get_name() << " within "
|
||||
<< scope_path(scn) << "." << endl;
|
||||
|
||||
des->errors += 1;
|
||||
return;
|
||||
@@ -485,24 +496,21 @@ void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
||||
// instantiation line.
|
||||
for (int idx = 0 ; idx < instance_count ; idx += 1) {
|
||||
|
||||
perm_string use_name = get_name();
|
||||
hname_t 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;
|
||||
|
||||
snprintf(name_buf, sizeof name_buf,
|
||||
"%s[%d]", get_name().str(), instance_idx);
|
||||
use_name = lex_strings.make(name_buf);
|
||||
use_name = hname_t(get_name(), instance_idx);
|
||||
}
|
||||
|
||||
if (debug_scopes) {
|
||||
cerr << get_line() << ": debug: Module instance " << use_name
|
||||
<< " becomes child of " << sc->name()
|
||||
<< " becomes child of " << scope_path(sc)
|
||||
<< "." << endl;
|
||||
}
|
||||
|
||||
@@ -639,7 +647,7 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
|
||||
NetScope*my_scope = scope;
|
||||
|
||||
if (name_ != 0) {
|
||||
my_scope = new NetScope(scope, name_, bl_type_==BL_PAR
|
||||
my_scope = new NetScope(scope, hname_t(name_), bl_type_==BL_PAR
|
||||
? NetScope::FORK_JOIN
|
||||
: NetScope::BEGIN_END);
|
||||
}
|
||||
@@ -748,6 +756,22 @@ 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
|
||||
|
||||
+205
-126
@@ -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.42 2006/06/02 04:48:50 steve Exp $"
|
||||
#ident "$Id: elab_sig.cc,v 1.52 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -34,6 +34,7 @@
|
||||
# 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
|
||||
@@ -41,8 +42,10 @@
|
||||
* within the port_t that have a matching name.
|
||||
*/
|
||||
static bool signal_is_in_port(const svector<Module::port_t*>&ports,
|
||||
const hname_t&name)
|
||||
NetNet*sig)
|
||||
{
|
||||
perm_string name = sig->name();
|
||||
|
||||
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
||||
|
||||
Module::port_t*pp = ports[idx];
|
||||
@@ -53,9 +56,15 @@ 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 (pp->expr[cc]->path() == name)
|
||||
if (pname == name)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -63,14 +72,28 @@ 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) {
|
||||
@@ -78,12 +101,12 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (pp == 0)
|
||||
continue;
|
||||
|
||||
map<hname_t,PWire*>::const_iterator wt;
|
||||
map<pform_name_t,PWire*>::const_iterator wt;
|
||||
for (unsigned cc = 0 ; cc < pp->expr.count() ; cc += 1) {
|
||||
hname_t port_path (pp->expr[cc]->path());
|
||||
wt = wl.find(port_path);
|
||||
pform_name_t port_path (pp->expr[cc]->path());
|
||||
wt = wires_.find(port_path);
|
||||
|
||||
if (wt == wl.end()) {
|
||||
if (wt == wires_.end()) {
|
||||
cerr << get_line() << ": error: "
|
||||
<< "Port " << pp->expr[cc]->path() << " ("
|
||||
<< (idx+1) << ") of module " << name_
|
||||
@@ -103,14 +126,11 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
}
|
||||
}
|
||||
|
||||
for (map<hname_t,PWire*>::const_iterator wt = wl.begin()
|
||||
; wt != wl.end()
|
||||
; wt ++ ) {
|
||||
for (map<pform_name_t,PWire*>::const_iterator wt = wires_.begin()
|
||||
; wt != wires_.end() ; wt ++ ) {
|
||||
|
||||
PWire*cur = (*wt).second;
|
||||
cur->elaborate_sig(des, scope);
|
||||
|
||||
NetNet*sig = scope->find_signal_in_child(cur->path());
|
||||
NetNet*sig = cur->elaborate_sig(des, scope);
|
||||
|
||||
// If this wire is a signal of the module (as opposed to
|
||||
// a port of a function) and is a port, then check that
|
||||
@@ -122,12 +142,10 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if (sig && (sig->scope() == scope)
|
||||
&& (cur->get_port_type() != NetNet::NOT_A_PORT)) {
|
||||
|
||||
hname_t name = (*wt).first;
|
||||
|
||||
if (! signal_is_in_port(ports, name)) {
|
||||
if (! signal_is_in_port(ports, sig)) {
|
||||
|
||||
cerr << cur->get_line() << ": error: Signal "
|
||||
<< name << " has a declared direction "
|
||||
<< sig->name() << " has a declared direction "
|
||||
<< "but is not a port." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
@@ -190,11 +208,13 @@ bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
for (mfunc_it_t cur = funcs_.begin()
|
||||
; cur != funcs_.end() ; cur ++) {
|
||||
NetScope*fscope = scope->child((*cur).first);
|
||||
|
||||
hname_t use_name ( (*cur).first );
|
||||
NetScope*fscope = scope->child(use_name);
|
||||
if (scope == 0) {
|
||||
cerr << (*cur).second->get_line() << ": internal error: "
|
||||
<< "Child scope for function " << (*cur).first
|
||||
<< " missing in " << scope->name() << "." << endl;
|
||||
<< " missing in " << scope_path(scope) << "." << endl;
|
||||
des->errors += 1;
|
||||
continue;
|
||||
}
|
||||
@@ -211,7 +231,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((*cur).first);
|
||||
NetScope*tscope = scope->child( hname_t((*cur).first) );
|
||||
assert(tscope);
|
||||
(*cur).second->elaborate_sig(des, tscope);
|
||||
}
|
||||
@@ -234,9 +254,9 @@ bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
|
||||
|
||||
if (my_scope->parent() != scope) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Instance " << my_scope->name()
|
||||
<< " is in parent " << my_scope->parent()->name()
|
||||
<< " instead of " << scope->name()
|
||||
<< "Instance " << scope_path(my_scope)
|
||||
<< " is in parent " << scope_path(my_scope->parent())
|
||||
<< " instead of " << scope_path(scope)
|
||||
<< endl;
|
||||
}
|
||||
assert(my_scope->parent() == scope);
|
||||
@@ -259,7 +279,7 @@ bool PGenerate::elaborate_sig(Design*des) const
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: Elaborate nets in "
|
||||
<< "scope " << (*cur)->name() << endl;
|
||||
<< "scope " << scope_path(*cur) << endl;
|
||||
flag = elaborate_sig_(des, *cur) & flag;
|
||||
}
|
||||
|
||||
@@ -270,7 +290,7 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
|
||||
{
|
||||
// Scan the declared PWires to elaborate the obvious signals
|
||||
// in the current scope.
|
||||
typedef map<hname_t,PWire*>::const_iterator wires_it_t;
|
||||
typedef map<pform_name_t,PWire*>::const_iterator wires_it_t;
|
||||
for (wires_it_t wt = wires.begin()
|
||||
; wt != wires.end() ; wt ++ ) {
|
||||
|
||||
@@ -278,11 +298,17 @@ bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: Elaborate PWire "
|
||||
<< cur->path() << " in scope " << scope->name() << endl;
|
||||
<< 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;
|
||||
}
|
||||
|
||||
@@ -316,6 +342,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
||||
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);
|
||||
@@ -349,12 +376,13 @@ 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);
|
||||
@@ -396,22 +424,24 @@ 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>. */
|
||||
|
||||
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));
|
||||
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);
|
||||
|
||||
if (ppath != scope->basename()) {
|
||||
cerr << get_line() << ": internal error: function "
|
||||
<< "port " << (*ports_)[idx]->path()
|
||||
<< " has wrong name for function "
|
||||
<< scope->name() << "." << endl;
|
||||
<< scope_path(scope) << "." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
NetNet*tmp = scope->find_signal(pname);
|
||||
if (tmp == 0) {
|
||||
cerr << get_line() << ": internal error: function "
|
||||
<< scope->name() << " is missing port "
|
||||
<< scope_path(scope) << " is missing port "
|
||||
<< pname << "." << endl;
|
||||
scope->dump(cerr);
|
||||
cerr << get_line() << ": Continuing..." << endl;
|
||||
@@ -449,36 +479,34 @@ 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>. */
|
||||
|
||||
hname_t path = (*ports_)[idx]->path();
|
||||
assert(path.peek_name(0) && path.peek_name(1));
|
||||
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);
|
||||
|
||||
/* 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. */
|
||||
if (scope->parent()->child(path.peek_name(0)) != scope) {
|
||||
cerr << "internal error: task scope " << path
|
||||
<< " not the same as scope " << scope->name()
|
||||
<< "?!" << endl;
|
||||
return;
|
||||
}
|
||||
ivl_assert(*this, scope->basename() == scope_name);
|
||||
|
||||
/* 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(path.peek_name(1));
|
||||
NetNet*tmp = scope->find_signal(port_name);
|
||||
|
||||
if (tmp == 0) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Could not find port " << path.peek_name(1)
|
||||
<< " in scope " << scope->name() << endl;
|
||||
<< "Could not find port " << port_name
|
||||
<< " in scope " << scope_path(scope) << endl;
|
||||
scope->dump(cerr);
|
||||
}
|
||||
|
||||
ports[idx] = tmp;
|
||||
}
|
||||
|
||||
NetTaskDef*def = new NetTaskDef(scope->name(), ports);
|
||||
NetTaskDef*def = new NetTaskDef(scope, ports);
|
||||
scope->set_task_def(def);
|
||||
}
|
||||
|
||||
@@ -494,16 +522,19 @@ bool PGate::elaborate_sig(Design*des, NetScope*scope) const
|
||||
* elaboration this creates an object in the design that represent the
|
||||
* defined item.
|
||||
*/
|
||||
void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
NetNet* 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. */
|
||||
{ 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));
|
||||
{ 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) );
|
||||
|
||||
if (scope == 0) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
@@ -556,7 +587,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
"Unable to evaluate constant expression ``" <<
|
||||
*msb_[idx] << "''." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
mnum[idx] = tmp->value().as_long();
|
||||
@@ -569,7 +600,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
"Unable to evaluate constant expression ``" <<
|
||||
*lsb_[idx] << "''." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
lnum[idx] = tmp->value().as_long();
|
||||
@@ -585,7 +616,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
<< "'' declared both as a vector and a scalar."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -598,7 +629,7 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
" vs. [" << mnum[0] << ":" << lnum[0] << "]"
|
||||
" for signal ``" << hname_ << "''" << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -616,6 +647,10 @@ void 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,
|
||||
@@ -629,9 +664,9 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
if ((lexp == 0) || (rexp == 0)) {
|
||||
cerr << get_line() << ": internal error: There is "
|
||||
<< "a problem evaluating indices for ``"
|
||||
<< hname_.peek_tail_name() << "''." << endl;
|
||||
<< hname_ << "''." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst*lcon = dynamic_cast<NetEConst*> (lexp);
|
||||
@@ -639,10 +674,10 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
|
||||
if ((lcon == 0) || (rcon == 0)) {
|
||||
cerr << get_line() << ": internal error: The indices "
|
||||
<< "are not constant for memory ``"
|
||||
<< hname_.peek_tail_name() << "''." << endl;
|
||||
<< "are not constant for array ``"
|
||||
<< hname_ << "''." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
verinum lval = lcon->value();
|
||||
@@ -651,75 +686,119 @@ void PWire::elaborate_sig(Design*des, NetScope*scope) const
|
||||
delete lexp;
|
||||
delete rexp;
|
||||
|
||||
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 {
|
||||
|
||||
/* 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 = lex_strings.make(hname_.peek_tail_name());
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Create signal "
|
||||
<< name << "["<<msb<<":"<<lsb<<"]"
|
||||
<< " in scope " << scope->name() << endl;
|
||||
}
|
||||
|
||||
NetNet*sig = new NetNet(scope, name, wtype, msb, lsb);
|
||||
sig->data_type(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);
|
||||
array_dimensions = 1;
|
||||
array_s0 = lval.as_long();
|
||||
array_e0 = rval.as_long();
|
||||
}
|
||||
|
||||
/* 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
|
||||
|
||||
+267
-124
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: elaborate.cc,v 1.354 2006/12/09 01:59:35 steve Exp $"
|
||||
#ident "$Id: elaborate.cc,v 1.374 2007/06/05 21:35:51 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -41,6 +41,7 @@
|
||||
# include "util.h"
|
||||
# include "parse_api.h"
|
||||
# include "compiler.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
|
||||
static Link::strength_t drive_type(PGate::strength_t drv)
|
||||
@@ -86,10 +87,17 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
||||
assert(pin(0));
|
||||
assert(pin(1));
|
||||
|
||||
/* Normally, l-values to continuous assignments are NOT allowed
|
||||
to implicitly declare nets. However, so many tools do allow
|
||||
it that Icarus Verilog will allow it, at least if extensions
|
||||
are enabled. */
|
||||
bool implicit_lval_ok = false;
|
||||
if (generation_flag == GN_VER2001X)
|
||||
implicit_lval_ok = true;
|
||||
|
||||
/* Elaborate the l-value. */
|
||||
NetNet*lval = pin(0)->elaborate_lnet(des, scope);
|
||||
NetNet*lval = pin(0)->elaborate_lnet(des, scope, implicit_lval_ok);
|
||||
if (lval == 0) {
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -115,8 +123,14 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const
|
||||
return;
|
||||
}
|
||||
|
||||
assert(rid);
|
||||
assert(rid->pin_count() == 1);
|
||||
ivl_assert(*this, rid);
|
||||
if (rid->pin_count() != 1) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Invalid elaborate_net results here:" << endl;
|
||||
rid->dump_net(cerr, 4);
|
||||
des->errors += 1;
|
||||
}
|
||||
ivl_assert(*this, rid->pin_count() == 1);
|
||||
|
||||
/* If the right hand net is the same type as the left
|
||||
side net (i.e., WIRE/WIRE) then it is enough to just
|
||||
@@ -317,7 +331,7 @@ void PGBuiltin::elaborate(Design*des, NetScope*scope) const
|
||||
name = scope->local_symbol();
|
||||
|
||||
/* If the Verilog source has a range specification for the
|
||||
gates, then I am expected to make more then one
|
||||
gates, then I am expected to make more than one
|
||||
gate. Figure out how many are desired. */
|
||||
if (msb_) {
|
||||
NetExpr*msb_exp = elab_and_eval(des, scope, msb_, -1);
|
||||
@@ -643,7 +657,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Instantiate module "
|
||||
<< rmod->mod_name() << " with instance name "
|
||||
<< get_name() << " in scope " << scope->name() << endl;
|
||||
<< get_name() << " in scope " << scope_path(scope) << endl;
|
||||
}
|
||||
|
||||
// This is the array of pin expressions, shuffled to match the
|
||||
@@ -762,8 +776,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
if (mport.count() == 0)
|
||||
continue;
|
||||
|
||||
NetNet*tmp = des->find_signal(instance[0],
|
||||
mport[0]->path());
|
||||
perm_string pname = peek_tail_name(mport[0]->path());
|
||||
|
||||
NetNet*tmp = instance[0]->find_signal(pname);
|
||||
assert(tmp);
|
||||
|
||||
if (tmp->port_type() == NetNet::PINPUT) {
|
||||
@@ -936,7 +951,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: " << get_name()
|
||||
<< ": Port " << idx << " has vector width of "
|
||||
<< ": Port " << (idx+1) << " has vector width of "
|
||||
<< prts_vector_width << "." << endl;
|
||||
}
|
||||
|
||||
@@ -945,8 +960,10 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const
|
||||
// based, but users count parameter positions from 1.
|
||||
if ((instance.count() == 1)
|
||||
&& (prts_vector_width != sig->vector_width())) {
|
||||
const char *tmp3 = rmod->ports[idx]->name.str();
|
||||
if (tmp3 == 0) tmp3 = "???";
|
||||
cerr << get_line() << ": warning: Port " << (idx+1)
|
||||
<< " (" << rmod->ports[idx]->name << ") of "
|
||||
<< " (" << tmp3 << ") of "
|
||||
<< type_ << " expects " << prts_vector_width <<
|
||||
" bits, got " << sig->vector_width() << "." << endl;
|
||||
|
||||
@@ -1441,8 +1458,9 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
||||
bool unsized_flag = false;
|
||||
use_width = rval()->test_width(des, scope, use_width, use_width, unsized_flag);
|
||||
|
||||
/* Now elaborate to the expected width. */
|
||||
NetExpr*rv = elab_and_eval(des, scope, rval(), use_width);
|
||||
/* Now elaborate to the expected width. Pass the lwidth to
|
||||
prune any constant result to fit with the lvalue at hand. */
|
||||
NetExpr*rv = elab_and_eval(des, scope, rval(), use_width, lv->lwidth());
|
||||
if (rv == 0) return 0;
|
||||
assert(rv);
|
||||
|
||||
@@ -1485,7 +1503,6 @@ NetProc* PAssign::elaborate(Design*des, NetScope*scope) const
|
||||
NetESignal*sig = new NetESignal(tmp);
|
||||
|
||||
/* Generate an assignment of the l-value to the temporary... */
|
||||
string n = scope->local_hsymbol();
|
||||
NetAssign_*lvt = new NetAssign_(tmp);
|
||||
|
||||
NetAssign*a1 = new NetAssign(lvt, rv);
|
||||
@@ -1608,10 +1625,10 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
NetScope*nscope = 0;
|
||||
if (name_.str() != 0) {
|
||||
nscope = scope->child(name_);
|
||||
nscope = scope->child(hname_t(name_));
|
||||
if (nscope == 0) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
"unable to find block scope " << scope->name()
|
||||
"unable to find block scope " << scope_path(scope)
|
||||
<< "<" << name_ << ">" << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
@@ -1622,7 +1639,6 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
||||
}
|
||||
|
||||
NetBlock*cur = new NetBlock(type, nscope);
|
||||
bool fail_flag = false;
|
||||
|
||||
if (nscope == 0)
|
||||
nscope = scope;
|
||||
@@ -1640,8 +1656,12 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
||||
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1) {
|
||||
assert(list_[idx]);
|
||||
NetProc*tmp = list_[idx]->elaborate(des, nscope);
|
||||
// If the statement fails to elaborate, then simply
|
||||
// ignore it. Presumably, the elaborate for the
|
||||
// statement already generated an error message and
|
||||
// marked the error count in the design so no need to
|
||||
// do any of that here.
|
||||
if (tmp == 0) {
|
||||
fail_flag = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1655,11 +1675,6 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
|
||||
cur->append(tmp);
|
||||
}
|
||||
|
||||
if (fail_flag) {
|
||||
delete cur;
|
||||
cur = 0;
|
||||
}
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
@@ -1778,7 +1793,7 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
|
||||
return new NetBlock(NetBlock::SEQU, 0);
|
||||
}
|
||||
|
||||
// If the condition expression is more then 1 bits, then
|
||||
// If the condition expression is more than 1 bits, then
|
||||
// generate a comparison operator to get the result down to
|
||||
// one bit. Turn <e> into <e> != 0;
|
||||
|
||||
@@ -1826,7 +1841,7 @@ NetProc* PCondit::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
NetProc* PCallTask::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
if (path_.peek_name(0)[0] == '$')
|
||||
if (peek_tail_name(path_)[0] == '$')
|
||||
return elaborate_sys(des, scope);
|
||||
else
|
||||
return elaborate_usr(des, scope);
|
||||
@@ -1862,16 +1877,15 @@ NetProc* PCallTask::elaborate_sys(Design*des, NetScope*scope) const
|
||||
/* Attempt to pre-evaluate the parameters. It may be
|
||||
possible to at least partially reduce the
|
||||
expression. */
|
||||
if (eparms[idx] && !dynamic_cast<NetEConst*>(eparms[idx])) {
|
||||
NetExpr*tmp = eparms[idx]->eval_tree();
|
||||
if (tmp != 0) {
|
||||
if (eparms[idx]) {
|
||||
if (NetExpr*tmp = eparms[idx]->eval_tree()) {
|
||||
delete eparms[idx];
|
||||
eparms[idx] = tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NetSTask*cur = new NetSTask(path_.peek_name(0), eparms);
|
||||
NetSTask*cur = new NetSTask(peek_tail_name(path_), eparms);
|
||||
return cur;
|
||||
}
|
||||
|
||||
@@ -1920,7 +1934,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
||||
NetTaskDef*def = task->task_def();
|
||||
if (def == 0) {
|
||||
cerr << get_line() << ": internal error: task " << path_
|
||||
<< " doesn't have a definition in " << scope->name()
|
||||
<< " doesn't have a definition in " << scope_path(scope)
|
||||
<< "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
@@ -1929,7 +1943,8 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
||||
|
||||
if (nparms() != def->port_count()) {
|
||||
cerr << get_line() << ": error: Port count mismatch in call to ``"
|
||||
<< path_ << "''." << endl;
|
||||
<< path_ << "''. Got " << nparms()
|
||||
<< " ports, expecting " << def->port_count() << " ports." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -1940,6 +1955,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
||||
to make a sequential block to hold the generated code. */
|
||||
if (nparms() == 0) {
|
||||
cur = new NetUTask(task);
|
||||
cur->set_line(*this);
|
||||
return cur;
|
||||
}
|
||||
|
||||
@@ -1980,6 +1996,7 @@ NetProc* PCallTask::elaborate_usr(Design*des, NetScope*scope) const
|
||||
|
||||
/* Generate the task call proper... */
|
||||
cur = new NetUTask(task);
|
||||
cur->set_line(*this);
|
||||
block->append(cur);
|
||||
|
||||
|
||||
@@ -2128,10 +2145,12 @@ NetProc* PDisable::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
NetScope*target = des->find_scope(scope, scope_);
|
||||
list<hname_t> spath = eval_scope_path(des, scope, scope_);
|
||||
|
||||
NetScope*target = des->find_scope(scope, spath);
|
||||
if (target == 0) {
|
||||
cerr << get_line() << ": error: Cannot find scope "
|
||||
<< scope_ << " in " << scope->name() << endl;
|
||||
<< scope_ << " in " << scope_path(scope) << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
@@ -2295,12 +2314,11 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope,
|
||||
|
||||
if (PEIdent*id = dynamic_cast<PEIdent*>(expr_[idx]->expr())) {
|
||||
NetNet* sig = 0;
|
||||
NetMemory* mem = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
NetScope*found_in = symbol_search(des, scope, id->path(),
|
||||
sig, mem, par, eve);
|
||||
sig, par, eve);
|
||||
|
||||
if (found_in && eve) {
|
||||
wa->add_event(eve);
|
||||
@@ -2408,7 +2426,7 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope,
|
||||
return 0;
|
||||
}
|
||||
|
||||
// If the condition expression is more then 1 bits, then
|
||||
// If the condition expression is more than 1 bits, then
|
||||
// generate a reduction operator to get the result down to
|
||||
// one bit. In other words, Turn <e> into |<e>;
|
||||
|
||||
@@ -2692,8 +2710,7 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const
|
||||
|
||||
/* Make the rvalue of the increment expression, and size it
|
||||
for the lvalue. */
|
||||
etmp = expr2_->elaborate_expr(des, scope, lv->lwidth(), false);
|
||||
etmp->set_width(lv->lwidth());
|
||||
etmp = elab_and_eval(des, scope, expr2_, lv->lwidth());
|
||||
NetAssign*step = new NetAssign(lv, etmp);
|
||||
step->set_line(*this);
|
||||
|
||||
@@ -2750,7 +2767,7 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
|
||||
if (def == 0) {
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "No function definition for function "
|
||||
<< scope->name() << endl;
|
||||
<< scope_path(scope) << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2759,7 +2776,7 @@ void PFunction::elaborate(Design*des, NetScope*scope) const
|
||||
NetProc*st = statement_->elaborate(des, scope);
|
||||
if (st == 0) {
|
||||
cerr << statement_->get_line() << ": error: Unable to elaborate "
|
||||
"statement in function " << def->name() << "." << endl;
|
||||
"statement in function " << scope->basename() << "." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
@@ -2860,7 +2877,7 @@ void PTask::elaborate(Design*des, NetScope*task) const
|
||||
st = statement_->elaborate(des, task);
|
||||
if (st == 0) {
|
||||
cerr << statement_->get_line() << ": Unable to elaborate "
|
||||
"statement in task " << task->name()
|
||||
"statement in task " << scope_path(task)
|
||||
<< " at " << get_line() << "." << endl;
|
||||
return;
|
||||
}
|
||||
@@ -2874,12 +2891,11 @@ NetProc* PTrigger::elaborate(Design*des, NetScope*scope) const
|
||||
assert(scope);
|
||||
|
||||
NetNet* sig = 0;
|
||||
NetMemory* mem = 0;
|
||||
const NetExpr*par = 0;
|
||||
NetEvent* eve = 0;
|
||||
|
||||
NetScope*found_in = symbol_search(des, scope, event_,
|
||||
sig, mem, par, eve);
|
||||
sig, par, eve);
|
||||
|
||||
if (found_in == 0) {
|
||||
cerr << get_line() << ": error: event <" << event_ << ">"
|
||||
@@ -2910,6 +2926,79 @@ NetProc* PWhile::elaborate(Design*des, NetScope*scope) const
|
||||
return loop;
|
||||
}
|
||||
|
||||
bool PProcess::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
NetProc*cur = statement_->elaborate(des, scope);
|
||||
if (cur == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NetProcTop*top=0;
|
||||
switch (type()) {
|
||||
case PProcess::PR_INITIAL:
|
||||
top = new NetProcTop(scope, NetProcTop::KINITIAL, cur);
|
||||
break;
|
||||
case PProcess::PR_ALWAYS:
|
||||
top = new NetProcTop(scope, NetProcTop::KALWAYS, cur);
|
||||
break;
|
||||
}
|
||||
ivl_assert(*this, top);
|
||||
|
||||
// Evaluate the attributes for this process, if there
|
||||
// are any. These attributes are to be attached to the
|
||||
// NetProcTop object.
|
||||
struct attrib_list_t*attrib_list = 0;
|
||||
unsigned attrib_list_n = 0;
|
||||
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, scope);
|
||||
|
||||
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
|
||||
top->attribute(attrib_list[adx].key,
|
||||
attrib_list[adx].val);
|
||||
|
||||
delete[]attrib_list;
|
||||
|
||||
top->set_line(*this);
|
||||
des->add_process(top);
|
||||
|
||||
/* Detect the special case that this is a combinational
|
||||
always block. We want to attach an _ivl_schedule_push
|
||||
attribute to this process so that it starts up and
|
||||
gets into its wait statement before non-combinational
|
||||
code is executed. */
|
||||
do {
|
||||
if (top->type() != NetProcTop::KALWAYS)
|
||||
break;
|
||||
|
||||
NetEvWait*st = dynamic_cast<NetEvWait*>(top->statement());
|
||||
if (st == 0)
|
||||
break;
|
||||
|
||||
if (st->nevents() != 1)
|
||||
break;
|
||||
|
||||
NetEvent*ev = st->event(0);
|
||||
|
||||
if (ev->nprobe() == 0)
|
||||
break;
|
||||
|
||||
bool anyedge_test = true;
|
||||
for (unsigned idx = 0 ; anyedge_test && (idx<ev->nprobe())
|
||||
; idx += 1) {
|
||||
const NetEvProbe*pr = ev->probe(idx);
|
||||
if (pr->edge() != NetEvProbe::ANYEDGE)
|
||||
anyedge_test = false;
|
||||
}
|
||||
|
||||
if (! anyedge_test)
|
||||
break;
|
||||
|
||||
top->attribute(perm_string::literal("_ivl_schedule_push"),
|
||||
verinum(1));
|
||||
} while (0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PSpecPath::elaborate(Design*des, NetScope*scope) const
|
||||
{
|
||||
uint64_t delay_value[12];
|
||||
@@ -2920,6 +3009,18 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
|
||||
if (!gn_specify_blocks_flag)
|
||||
return;
|
||||
|
||||
/* Check for various path types that are not supported. */
|
||||
if (conditional && !condition) {
|
||||
cerr << get_line() << ": sorry: ifnone specify paths"
|
||||
<< " are not supported." << endl;
|
||||
cerr << get_line() << ": : Use -g no-specify to ignore"
|
||||
<< " specify blocks." << endl;
|
||||
des->errors += 1;
|
||||
return;
|
||||
}
|
||||
|
||||
ivl_assert(*this, conditional || (condition==0));
|
||||
|
||||
ndelays = delays.size();
|
||||
if (ndelays > 12)
|
||||
ndelays = 12;
|
||||
@@ -2964,13 +3065,30 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
|
||||
break;
|
||||
}
|
||||
|
||||
NetNet*condit_sig = 0;
|
||||
if (conditional) {
|
||||
ivl_assert(*this, condition);
|
||||
|
||||
NetExpr*tmp = elab_and_eval(des, scope, condition, -1);
|
||||
ivl_assert(*condition, tmp);
|
||||
|
||||
// FIXME: Look for constant expressions here?
|
||||
|
||||
// Get a net form.
|
||||
condit_sig = tmp->synthesize(des);
|
||||
ivl_assert(*condition, condit_sig);
|
||||
}
|
||||
|
||||
/* Create all the various paths from the path specifier. */
|
||||
typedef std::vector<perm_string>::const_iterator str_vector_iter;
|
||||
for (str_vector_iter cur = dst.begin()
|
||||
; cur != dst.end() ; cur ++) {
|
||||
|
||||
if (debug_elaborate) {
|
||||
cerr << get_line() << ": debug: Path to " << (*cur) << endl;
|
||||
cerr << get_line() << ": debug: Path to " << (*cur);
|
||||
if (condit_sig)
|
||||
cerr << " if " << condit_sig->name();
|
||||
cerr << endl;
|
||||
}
|
||||
|
||||
NetNet*dst_sig = scope->find_signal(*cur);
|
||||
@@ -2981,10 +3099,26 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
|
||||
continue;
|
||||
}
|
||||
|
||||
if (dst_sig->port_type() != NetNet::POUTPUT
|
||||
&& dst_sig->port_type() != NetNet::PINOUT) {
|
||||
|
||||
cerr << get_line() << ": error: Path destination "
|
||||
<< *cur << " must be an output or inout port." << endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
NetDelaySrc*path = new NetDelaySrc(scope, scope->local_symbol(),
|
||||
src.size());
|
||||
src.size(), condit_sig);
|
||||
path->set_line(*this);
|
||||
|
||||
// The presence of the data_source_expression indicates
|
||||
// that this is an edge sensitive path. If so, then set
|
||||
// the edges. Note that edge==0 is BOTH edges.
|
||||
if (data_source_expression) {
|
||||
if (edge >= 0) path->set_posedge();
|
||||
if (edge <= 0) path->set_negedge();
|
||||
}
|
||||
|
||||
switch (ndelays) {
|
||||
case 12:
|
||||
path->set_delays(delay_value[0], delay_value[1],
|
||||
@@ -3017,10 +3151,22 @@ void PSpecPath::elaborate(Design*des, NetScope*scope) const
|
||||
NetNet*src_sig = scope->find_signal(*cur_src);
|
||||
assert(src_sig);
|
||||
|
||||
if (src_sig->port_type() != NetNet::PINPUT
|
||||
& src_sig->port_type() != NetNet::PINOUT) {
|
||||
|
||||
cerr << get_line() << ": error: Path source "
|
||||
<< *cur_src << " must be an input or inout port."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
}
|
||||
|
||||
connect(src_sig->pin(0), path->pin(idx));
|
||||
idx += 1;
|
||||
}
|
||||
|
||||
if (condit_sig)
|
||||
connect(condit_sig->pin(0), path->pin(idx));
|
||||
|
||||
dst_sig->add_delay_path(path);
|
||||
}
|
||||
|
||||
@@ -3089,7 +3235,8 @@ bool Module::elaborate(Design*des, NetScope*scope) const
|
||||
for (mfunc_it_t cur = funcs_.begin()
|
||||
; cur != funcs_.end() ; cur ++) {
|
||||
|
||||
NetScope*fscope = scope->child((*cur).first);
|
||||
hname_t use_name ( (*cur).first );
|
||||
NetScope*fscope = scope->child(use_name);
|
||||
assert(fscope);
|
||||
(*cur).second->elaborate(des, fscope);
|
||||
}
|
||||
@@ -3101,7 +3248,8 @@ bool Module::elaborate(Design*des, NetScope*scope) const
|
||||
for (mtask_it_t cur = tasks_.begin()
|
||||
; cur != tasks_.end() ; cur ++) {
|
||||
|
||||
NetScope*tscope = scope->child((*cur).first);
|
||||
hname_t use_name ( (*cur).first );
|
||||
NetScope*tscope = scope->child(use_name);
|
||||
assert(tscope);
|
||||
(*cur).second->elaborate(des, tscope);
|
||||
}
|
||||
@@ -3124,80 +3272,9 @@ bool Module::elaborate(Design*des, NetScope*scope) const
|
||||
const list<PProcess*>&sl = get_behaviors();
|
||||
|
||||
for (list<PProcess*>::const_iterator st = sl.begin()
|
||||
; st != sl.end()
|
||||
; st ++ ) {
|
||||
|
||||
NetProc*cur = (*st)->statement()->elaborate(des, scope);
|
||||
if (cur == 0) {
|
||||
result_flag = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
NetProcTop*top=NULL;
|
||||
switch ((*st)->type()) {
|
||||
case PProcess::PR_INITIAL:
|
||||
top = new NetProcTop(scope, NetProcTop::KINITIAL, cur);
|
||||
break;
|
||||
case PProcess::PR_ALWAYS:
|
||||
top = new NetProcTop(scope, NetProcTop::KALWAYS, cur);
|
||||
break;
|
||||
}
|
||||
assert(top);
|
||||
|
||||
// Evaluate the attributes for this process, if there
|
||||
// are any. These attributes are to be attached to the
|
||||
// NetProcTop object.
|
||||
struct attrib_list_t*attrib_list = 0;
|
||||
unsigned attrib_list_n = 0;
|
||||
attrib_list = evaluate_attributes((*st)->attributes,
|
||||
attrib_list_n,
|
||||
des, scope);
|
||||
|
||||
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
|
||||
top->attribute(attrib_list[adx].key,
|
||||
attrib_list[adx].val);
|
||||
|
||||
delete[]attrib_list;
|
||||
|
||||
top->set_line(*(*st));
|
||||
des->add_process(top);
|
||||
|
||||
/* Detect the special case that this is a combinational
|
||||
always block. We want to attach an _ivl_schedule_push
|
||||
attribute to this process so that it starts up and
|
||||
gets into its wait statement before non-combinational
|
||||
code is executed. */
|
||||
do {
|
||||
if (top->type() != NetProcTop::KALWAYS)
|
||||
break;
|
||||
|
||||
NetEvWait*st = dynamic_cast<NetEvWait*>(top->statement());
|
||||
if (st == 0)
|
||||
break;
|
||||
|
||||
if (st->nevents() != 1)
|
||||
break;
|
||||
|
||||
NetEvent*ev = st->event(0);
|
||||
|
||||
if (ev->nprobe() == 0)
|
||||
break;
|
||||
|
||||
bool anyedge_test = true;
|
||||
for (unsigned idx = 0 ; anyedge_test && (idx<ev->nprobe())
|
||||
; idx += 1) {
|
||||
const NetEvProbe*pr = ev->probe(idx);
|
||||
if (pr->edge() != NetEvProbe::ANYEDGE)
|
||||
anyedge_test = false;
|
||||
}
|
||||
|
||||
if (! anyedge_test)
|
||||
break;
|
||||
|
||||
top->attribute(perm_string::literal("_ivl_schedule_push"),
|
||||
verinum(1));
|
||||
} while (0);
|
||||
; st != sl.end() ; st ++ ) {
|
||||
|
||||
result_flag &= (*st)->elaborate(des, scope);
|
||||
}
|
||||
|
||||
// Elaborate the specify paths of the module.
|
||||
@@ -3221,7 +3298,7 @@ bool PGenerate::elaborate(Design*des) const
|
||||
|
||||
if (debug_elaborate)
|
||||
cerr << get_line() << ": debug: Elaborate in "
|
||||
<< "scope " << (*cur)->name() << endl;
|
||||
<< "scope " << scope_path(*cur) << endl;
|
||||
|
||||
flag = elaborate_(des, *cur) & flag;
|
||||
}
|
||||
@@ -3232,10 +3309,12 @@ bool PGenerate::elaborate(Design*des) const
|
||||
bool PGenerate::elaborate_(Design*des, NetScope*scope) const
|
||||
{
|
||||
typedef list<PGate*>::const_iterator gates_it_t;
|
||||
for (gates_it_t cur = gates.begin() ; cur != gates.end() ; cur ++ ) {
|
||||
|
||||
for (gates_it_t cur = gates.begin() ; cur != gates.end() ; cur ++ )
|
||||
(*cur)->elaborate(des, scope);
|
||||
|
||||
typedef list<PProcess*>::const_iterator proc_it_t;
|
||||
for (proc_it_t cur = behaviors.begin(); cur != behaviors.end(); cur++)
|
||||
(*cur)->elaborate(des, scope);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -3349,6 +3428,70 @@ Design* elaborate(list<perm_string>roots)
|
||||
|
||||
/*
|
||||
* $Log: elaborate.cc,v $
|
||||
* Revision 1.374 2007/06/05 21:35:51 steve
|
||||
* Error resiliency (ldoolitt)
|
||||
*
|
||||
* Revision 1.373 2007/06/04 02:19:07 steve
|
||||
* Handle bit/part select of array words in nets.
|
||||
*
|
||||
* Revision 1.372 2007/06/02 03:42:12 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.371 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.370 2007/04/16 01:10:07 steve
|
||||
* Properly ignore unsupported ifnone.
|
||||
*
|
||||
* Revision 1.369 2007/04/15 20:45:40 steve
|
||||
* Attach line number information to task calls.
|
||||
*
|
||||
* Revision 1.368 2007/04/13 02:34:35 steve
|
||||
* Parse edge sensitive paths without edge specifier.
|
||||
*
|
||||
* Revision 1.367 2007/04/05 03:09:50 steve
|
||||
* Allow implicit wires in assign l-value.
|
||||
*
|
||||
* Revision 1.366 2007/04/01 23:01:10 steve
|
||||
* Improve port mismatch error message.
|
||||
*
|
||||
* Revision 1.365 2007/03/22 16:08:15 steve
|
||||
* Spelling fixes from Larry
|
||||
*
|
||||
* Revision 1.364 2007/03/08 05:30:02 steve
|
||||
* Limit the calculated widths of constants.
|
||||
*
|
||||
* Revision 1.363 2007/03/05 05:59:10 steve
|
||||
* Handle processes within generate loops.
|
||||
*
|
||||
* Revision 1.362 2007/03/03 05:56:55 steve
|
||||
* Check that path source/destination are ports.
|
||||
*
|
||||
* Revision 1.361 2007/03/02 06:13:22 steve
|
||||
* Add support for edge sensitive spec paths.
|
||||
*
|
||||
* Revision 1.360 2007/03/01 06:19:38 steve
|
||||
* Add support for conditional specify delay paths.
|
||||
*
|
||||
* Revision 1.359 2007/02/12 01:52:21 steve
|
||||
* Parse all specify paths to pform.
|
||||
*
|
||||
* Revision 1.358 2007/02/01 05:52:24 steve
|
||||
* More generous handling of errors in blocks.
|
||||
*
|
||||
* Revision 1.357 2007/01/21 04:26:36 steve
|
||||
* Clean up elaboration of for-loop increment expression.
|
||||
*
|
||||
* Revision 1.356 2007/01/19 05:42:40 steve
|
||||
* Precalculate constant power expressions, and constant function arguments.
|
||||
*
|
||||
* Revision 1.355 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.354 2006/12/09 01:59:35 steve
|
||||
* Fix an uninitialized variable warning.
|
||||
*
|
||||
|
||||
@@ -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.88 2006/11/10 05:44:44 steve Exp $"
|
||||
#ident "$Id: emit.cc,v 1.89 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -57,6 +57,11 @@ 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);
|
||||
@@ -125,12 +130,6 @@ bool NetPartSelect::emit_node(struct target_t*tgt) const
|
||||
return tgt->part_select(this);
|
||||
}
|
||||
|
||||
bool NetRamDq::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
tgt->lpm_ram_dq(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NetReplicate::emit_node(struct target_t*tgt) const
|
||||
{
|
||||
return tgt->replicate(this);
|
||||
@@ -357,13 +356,6 @@ void NetScope::emit_scope(struct target_t*tgt) const
|
||||
} 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
|
||||
@@ -472,11 +464,6 @@ 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."
|
||||
@@ -540,6 +527,12 @@ int emit(const Design*des, const char*type)
|
||||
|
||||
/*
|
||||
* $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.88 2006/11/10 05:44:44 steve
|
||||
* Process delay paths in second path over signals.
|
||||
*
|
||||
|
||||
@@ -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.43 2006/08/08 05:11:37 steve Exp $"
|
||||
#ident "$Id: eval.cc,v 1.47 2007/06/04 19:14:06 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -29,12 +29,12 @@
|
||||
# include "netmisc.h"
|
||||
# include "compiler.h"
|
||||
|
||||
verinum* PExpr::eval_const(const Design*, NetScope*) const
|
||||
verinum* PExpr::eval_const(Design*, NetScope*) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
verinum* PEBinary::eval_const(const Design*des, NetScope*scope) const
|
||||
verinum* PEBinary::eval_const(Design*des, NetScope*scope) const
|
||||
{
|
||||
verinum*l = left_->eval_const(des, scope);
|
||||
if (l == 0) return 0;
|
||||
@@ -143,7 +143,7 @@ verinum* PEBinary::eval_const(const Design*des, NetScope*scope) const
|
||||
delete r;
|
||||
return res;
|
||||
}
|
||||
verinum* PEConcat::eval_const(const Design*des, NetScope*scope) const
|
||||
verinum* PEConcat::eval_const(Design*des, NetScope*scope) const
|
||||
{
|
||||
verinum*accum = parms_[0]->eval_const(des, scope);
|
||||
if (accum == 0)
|
||||
@@ -170,24 +170,24 @@ verinum* PEConcat::eval_const(const Design*des, NetScope*scope) const
|
||||
* Evaluate an identifier as a constant expression. This is only
|
||||
* possible if the identifier is that of a parameter.
|
||||
*/
|
||||
verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const
|
||||
verinum* PEIdent::eval_const(Design*des, NetScope*scope) const
|
||||
{
|
||||
assert(scope);
|
||||
NetNet*net;
|
||||
NetMemory*mem;
|
||||
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(path_.peek_tail_name(),scope->genvar_tmp) == 0) {
|
||||
&& strcmp(name_tail.name,scope->genvar_tmp) == 0) {
|
||||
return new verinum(scope->genvar_tmp_val);
|
||||
}
|
||||
|
||||
NetScope*found_in = symbol_search(des, scope, path_,
|
||||
net, mem, expr, eve);
|
||||
symbol_search(des, scope, path_, net, expr, eve);
|
||||
|
||||
if (expr == 0)
|
||||
return 0;
|
||||
@@ -202,30 +202,30 @@ verinum* PEIdent::eval_const(const Design*des, NetScope*scope) const
|
||||
|
||||
assert(eval);
|
||||
|
||||
if (msb_ || lsb_)
|
||||
if (!name_tail.index.empty())
|
||||
return 0;
|
||||
|
||||
|
||||
return new verinum(eval->value());
|
||||
}
|
||||
|
||||
verinum* PEFNumber::eval_const(const Design*, NetScope*) const
|
||||
verinum* PEFNumber::eval_const(Design*, NetScope*) const
|
||||
{
|
||||
long val = value_->as_long();
|
||||
return new verinum(val);
|
||||
}
|
||||
|
||||
verinum* PENumber::eval_const(const Design*, NetScope*) const
|
||||
verinum* PENumber::eval_const(Design*, NetScope*) const
|
||||
{
|
||||
return new verinum(value());
|
||||
}
|
||||
|
||||
verinum* PEString::eval_const(const Design*, NetScope*) const
|
||||
verinum* PEString::eval_const(Design*, NetScope*) const
|
||||
{
|
||||
return new verinum(string(text_));
|
||||
}
|
||||
|
||||
verinum* PETernary::eval_const(const Design*des, NetScope*scope) const
|
||||
verinum* PETernary::eval_const(Design*des, NetScope*scope) const
|
||||
{
|
||||
verinum*test = expr_->eval_const(des, scope);
|
||||
if (test == 0)
|
||||
@@ -245,7 +245,7 @@ verinum* PETernary::eval_const(const Design*des, NetScope*scope) const
|
||||
}
|
||||
}
|
||||
|
||||
verinum* PEUnary::eval_const(const Design*des, NetScope*scope) const
|
||||
verinum* PEUnary::eval_const(Design*des, NetScope*scope) const
|
||||
{
|
||||
verinum*val = expr_->eval_const(des, scope);
|
||||
if (val == 0)
|
||||
@@ -276,6 +276,22 @@ verinum* PEUnary::eval_const(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.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.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.
|
||||
*
|
||||
|
||||
+5
-3
@@ -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.8 2005/11/27 17:01:57 steve Exp $"
|
||||
#ident "$Id: eval_attrib.cc,v 1.9 2007/06/04 19:14:06 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -35,8 +35,7 @@
|
||||
|
||||
attrib_list_t* evaluate_attributes(const map<perm_string,PExpr*>&att,
|
||||
unsigned&natt,
|
||||
const Design*des,
|
||||
NetScope*scope)
|
||||
Design*des, NetScope*scope)
|
||||
{
|
||||
natt = att.size();
|
||||
if (natt == 0)
|
||||
@@ -74,6 +73,9 @@ 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.
|
||||
*
|
||||
|
||||
+124
-147
@@ -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.72 2006/11/04 06:16:27 steve Exp $"
|
||||
#ident "$Id: eval_tree.cc,v 1.77 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -26,8 +26,9 @@
|
||||
# include <iostream>
|
||||
|
||||
# include "netlist.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
NetExpr* NetExpr::eval_tree()
|
||||
NetExpr* NetExpr::eval_tree(int prune_to_width)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
@@ -51,9 +52,61 @@ void NetEBinary::eval_sub_tree_()
|
||||
}
|
||||
}
|
||||
|
||||
NetEConst* NetEBAdd::eval_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)
|
||||
{
|
||||
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_);
|
||||
NetEConst*rc = dynamic_cast<NetEConst*>(right_);
|
||||
|
||||
@@ -115,7 +168,32 @@ NetEConst* NetEBAdd::eval_tree()
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst* NetEBBits::eval_tree()
|
||||
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)
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
@@ -690,7 +768,7 @@ NetEConst* NetEBComp::eval_neeqeq_()
|
||||
return res;
|
||||
}
|
||||
|
||||
NetEConst* NetEBComp::eval_tree()
|
||||
NetEConst* NetEBComp::eval_tree(int prune_to_width)
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
@@ -728,7 +806,7 @@ NetEConst* NetEBComp::eval_tree()
|
||||
* The NetEBDiv operator includes the / and % operators. First evaluate
|
||||
* the sub-expressions, then perform the required operation.
|
||||
*/
|
||||
NetExpr* NetEBDiv::eval_tree()
|
||||
NetExpr* NetEBDiv::eval_tree(int prune_to_width)
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
@@ -798,7 +876,7 @@ NetExpr* NetEBDiv::eval_tree()
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEConst* NetEBLogic::eval_tree()
|
||||
NetEConst* NetEBLogic::eval_tree(int prune_to_width)
|
||||
{
|
||||
eval_sub_tree_();
|
||||
NetEConst*lc = dynamic_cast<NetEConst*>(left_);
|
||||
@@ -864,52 +942,14 @@ NetEConst* NetEBLogic::eval_tree()
|
||||
return new NetEConst(verinum(res, 1));
|
||||
}
|
||||
|
||||
|
||||
NetExpr* NetEBMult::eval_tree_real_()
|
||||
{
|
||||
verireal lval;
|
||||
verireal rval;
|
||||
|
||||
switch (left_->expr_type()) {
|
||||
case IVL_VT_REAL: {
|
||||
NetECReal*lc = dynamic_cast<NetECReal*> (left_);
|
||||
if (lc == 0) return 0;
|
||||
lval = lc->value();
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC: {
|
||||
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 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);
|
||||
}
|
||||
bool flag = get_real_arguments_(lval, rval);
|
||||
if (! flag) return 0;
|
||||
|
||||
|
||||
NetECReal*res = new NetECReal(lval * rval);
|
||||
@@ -917,7 +957,7 @@ NetExpr* NetEBMult::eval_tree_real_()
|
||||
return res;
|
||||
}
|
||||
|
||||
NetExpr* NetEBMult::eval_tree()
|
||||
NetExpr* NetEBMult::eval_tree(int prune_to_width)
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
@@ -942,55 +982,15 @@ NetExpr* NetEBPow::eval_tree_real_()
|
||||
verireal lval;
|
||||
verireal rval;
|
||||
|
||||
switch (left_->expr_type()) {
|
||||
case IVL_VT_REAL: {
|
||||
NetECReal*lc = dynamic_cast<NetECReal*> (left_);
|
||||
if (lc == 0) return 0;
|
||||
lval = lc->value();
|
||||
break;
|
||||
}
|
||||
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC: {
|
||||
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 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);
|
||||
}
|
||||
|
||||
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()
|
||||
NetExpr* NetEBPow::eval_tree(int prune_to_width)
|
||||
{
|
||||
eval_sub_tree_();
|
||||
|
||||
@@ -1015,7 +1015,7 @@ NetExpr* NetEBPow::eval_tree()
|
||||
* Evaluate the shift operator if possible. For this to work, both
|
||||
* operands must be constant.
|
||||
*/
|
||||
NetEConst* NetEBShift::eval_tree()
|
||||
NetEConst* NetEBShift::eval_tree(int prune_to_width)
|
||||
{
|
||||
eval_sub_tree_();
|
||||
NetEConst*re = dynamic_cast<NetEConst*>(right_);
|
||||
@@ -1042,7 +1042,7 @@ NetEConst* NetEBShift::eval_tree()
|
||||
cerr << get_line() << ": debug: "
|
||||
<< "Evaluate " << lv << "<<" << op() << ">> "
|
||||
<< rv << ", wid=" << wid << ", shift=" << shift
|
||||
<< ", lv.las_len()=" << lv.has_len() << endl;
|
||||
<< ", lv.has_len()=" << lv.has_len() << endl;
|
||||
}
|
||||
|
||||
if ((wid == 0) || ! lv.has_len()) {
|
||||
@@ -1056,6 +1056,9 @@ NetEConst* NetEBShift::eval_tree()
|
||||
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());
|
||||
|
||||
@@ -1096,7 +1099,7 @@ NetEConst* NetEBShift::eval_tree()
|
||||
return res;
|
||||
}
|
||||
|
||||
NetEConst* NetEConcat::eval_tree()
|
||||
NetEConst* NetEConcat::eval_tree(int prune_to_width)
|
||||
{
|
||||
unsigned repeat_val = repeat();
|
||||
unsigned local_errors = 0;
|
||||
@@ -1190,51 +1193,7 @@ NetEConst* NetEConcat::eval_tree()
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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()
|
||||
{
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
NetExpr* NetEParam::eval_tree(int prune_to_width)
|
||||
{
|
||||
if (des_ == 0) {
|
||||
assert(scope_ == 0);
|
||||
@@ -1253,7 +1212,7 @@ NetExpr* NetEParam::eval_tree()
|
||||
if (expr == 0) {
|
||||
cerr << get_line() << ": internal error: Unable to match "
|
||||
<< "parameter " << name_ << " in scope "
|
||||
<< scope_->name() << endl;
|
||||
<< scope_path(scope_) << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1341,7 +1300,7 @@ NetExpr* NetEParam::eval_tree()
|
||||
}
|
||||
}
|
||||
|
||||
NetEConst* NetESelect::eval_tree()
|
||||
NetEConst* NetESelect::eval_tree(int prune_to_width)
|
||||
{
|
||||
NetEConst*expr = dynamic_cast<NetEConst*>(expr_);
|
||||
if (expr == 0) {
|
||||
@@ -1414,7 +1373,7 @@ NetEConst* NetESelect::eval_tree()
|
||||
* evaluates to x or z, then merge the constant bits of the true and
|
||||
* false expressions.
|
||||
*/
|
||||
NetExpr* NetETernary::eval_tree()
|
||||
NetExpr* NetETernary::eval_tree(int prune_to_width)
|
||||
{
|
||||
NetExpr*tmp;
|
||||
|
||||
@@ -1551,7 +1510,7 @@ void NetEUnary::eval_expr_()
|
||||
expr_ = oper;
|
||||
}
|
||||
|
||||
NetEConst* NetEUnary::eval_tree()
|
||||
NetEConst* NetEUnary::eval_tree(int prune_to_width)
|
||||
{
|
||||
eval_expr_();
|
||||
NetEConst*rval = dynamic_cast<NetEConst*>(expr_);
|
||||
@@ -1608,12 +1567,12 @@ NetEConst* NetEUnary::eval_tree()
|
||||
}
|
||||
|
||||
|
||||
NetEConst* NetEUBits::eval_tree()
|
||||
NetEConst* NetEUBits::eval_tree(int prune_to_width)
|
||||
{
|
||||
return NetEUnary::eval_tree();
|
||||
return NetEUnary::eval_tree(prune_to_width);
|
||||
}
|
||||
|
||||
NetEConst* NetEUReduce::eval_tree()
|
||||
NetEConst* NetEUReduce::eval_tree(int prune_to_width)
|
||||
{
|
||||
eval_expr_();
|
||||
NetEConst*rval = dynamic_cast<NetEConst*>(expr_);
|
||||
@@ -1696,6 +1655,24 @@ NetEConst* NetEUReduce::eval_tree()
|
||||
|
||||
/*
|
||||
* $Log: eval_tree.cc,v $
|
||||
* Revision 1.77 2007/06/02 03:42:12 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.76 2007/05/31 18:36:06 steve
|
||||
* Fix warning (ldolittle)
|
||||
*
|
||||
* Revision 1.75 2007/04/07 04:46:18 steve
|
||||
* Handle evaluate of addition of real valued constants.
|
||||
*
|
||||
* Revision 1.74 2007/03/08 05:30:02 steve
|
||||
* Limit the calculated widths of constants.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
|
||||
@@ -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.4 2006/10/30 22:46:25 steve Exp $"
|
||||
#ident "$Id: hello_vpi.c,v 1.5 2007/01/17 05:35:48 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -33,7 +33,7 @@
|
||||
|
||||
# include <vpi_user.h>
|
||||
|
||||
static PIN_INT32 my_hello_calltf(char *xx)
|
||||
static PLI_INT32 my_hello_calltf(char *xx)
|
||||
{
|
||||
vpi_printf("Hello World, from VPI.\n");
|
||||
return 0;
|
||||
@@ -62,6 +62,9 @@ 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)
|
||||
*
|
||||
|
||||
@@ -16,13 +16,13 @@
|
||||
* 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.4 2003/11/25 18:35:31 steve Exp $"
|
||||
* $Id: sqrt-virtex.v,v 1.5 2007/03/22 16:08:18 steve Exp $"
|
||||
*/
|
||||
|
||||
/*
|
||||
* This module is a synthesizeable square-root function. It is also a
|
||||
* detailed example of how to target Xilinx Virtex parts using
|
||||
* Icarus Verilog. In fact, for no particular reason other then to
|
||||
* Icarus Verilog. In fact, for no particular reason other than to
|
||||
* be excessively specific, I will step through the process of
|
||||
* generating a design for a Spartan-II XC2S15-VQ100, and also how to
|
||||
* generate a generic library part for larger Virtex designs.
|
||||
@@ -129,7 +129,7 @@
|
||||
* This command creates from the chip.ngd the file "chip_root.v" that
|
||||
* contains Verilog code that simulates the mapped design. This output
|
||||
* Verilog has the single root module "chip_root", which came from the
|
||||
* name of the root module when we were making hte EDIF file in the
|
||||
* name of the root module when we were making the EDIF file in the
|
||||
* first place. The module has ports named just line the ports of the
|
||||
* chip_root module below.
|
||||
*
|
||||
@@ -183,7 +183,7 @@
|
||||
* where sqrt(y) is the exact square root of y and floor(N) is the
|
||||
* largest integer <= N.
|
||||
*
|
||||
* For 32bit numbers, this will never run more then 16 iterations,
|
||||
* For 32 bit numbers, this will never run more than 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.4 2004/10/04 01:10:56 steve Exp $"
|
||||
* $Id: sqrt.vl,v 1.5 2007/03/22 16:08:18 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 32bit numbers, this will never run more then 16 iterations,
|
||||
* For 32 bit numbers, this will never run more than 16 iterations,
|
||||
* which amounts to 16 clocks.
|
||||
*/
|
||||
|
||||
|
||||
+79
-75
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: expr_synth.cc,v 1.80 2006/08/08 05:11:37 steve Exp $"
|
||||
#ident "$Id: expr_synth.cc,v 1.87 2007/06/02 03:42:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
NetNet* NetExpr::synthesize(Design*des)
|
||||
{
|
||||
@@ -91,7 +92,6 @@ NetNet* NetEBBits::synthesize(Design*des)
|
||||
|
||||
NetScope*scope = lsig->scope();
|
||||
assert(scope);
|
||||
string path = des->local_symbol(scope->name());
|
||||
|
||||
if (lsig->vector_width() != rsig->vector_width()) {
|
||||
cerr << get_line() << ": internal error: bitwise (" << op_
|
||||
@@ -449,10 +449,14 @@ NetNet* NetEBShift::synthesize(Design*des)
|
||||
osig->data_type(expr_type());
|
||||
osig->local_flag(true);
|
||||
|
||||
// ushift is the amount of pad created by the shift.
|
||||
unsigned long ushift = shift>=0? shift : -shift;
|
||||
if (ushift > osig->vector_width())
|
||||
ushift = osig->vector_width();
|
||||
|
||||
// part_width is the bits of the vector that survive the shift.
|
||||
unsigned long part_width = osig->vector_width() - ushift;
|
||||
|
||||
verinum znum (verinum::V0, ushift, true);
|
||||
NetConst*zcon = new NetConst(scope, scope->local_symbol(),
|
||||
znum);
|
||||
@@ -469,8 +473,24 @@ NetNet* NetEBShift::synthesize(Design*des)
|
||||
NetNet*zsig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::WIRE, znum.len());
|
||||
zsig->data_type(osig->data_type());
|
||||
zsig->local_flag(true);
|
||||
zsig->set_line(*this);
|
||||
connect(zcon->pin(0), zsig->pin(0));
|
||||
|
||||
/* Create a part select to reduce the width of the lsig
|
||||
to the amount left by the shift. */
|
||||
NetPartSelect*psel = new NetPartSelect(lsig, shift<0? ushift : 0,
|
||||
part_width,
|
||||
NetPartSelect::VP);
|
||||
des->add_node(psel);
|
||||
|
||||
NetNet*psig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, part_width);
|
||||
psig->data_type(expr_type());
|
||||
psig->local_flag(true);
|
||||
psig->set_line(*this);
|
||||
connect(psig->pin(0), psel->pin(0));
|
||||
|
||||
NetConcat*ccat = new NetConcat(scope, scope->local_symbol(),
|
||||
osig->vector_width(), 2);
|
||||
ccat->set_line(*this);
|
||||
@@ -478,10 +498,12 @@ NetNet* NetEBShift::synthesize(Design*des)
|
||||
|
||||
connect(ccat->pin(0), osig->pin(0));
|
||||
if (shift > 0) {
|
||||
// Left shift.
|
||||
connect(ccat->pin(1), zsig->pin(0));
|
||||
connect(ccat->pin(2), lsig->pin(0));
|
||||
connect(ccat->pin(2), psig->pin(0));
|
||||
} else {
|
||||
connect(ccat->pin(1), lsig->pin(0));
|
||||
// Right shift
|
||||
connect(ccat->pin(1), psig->pin(0));
|
||||
connect(ccat->pin(2), zsig->pin(0));
|
||||
}
|
||||
|
||||
@@ -497,7 +519,6 @@ NetNet* NetEBShift::synthesize(Design*des)
|
||||
osig->data_type(expr_type());
|
||||
osig->local_flag(true);
|
||||
|
||||
assert(op() == 'l');
|
||||
NetCLShift*dev = new NetCLShift(scope, scope->local_symbol(),
|
||||
osig->vector_width(),
|
||||
rsig->vector_width(),
|
||||
@@ -644,47 +665,37 @@ NetNet* NetEUReduce::synthesize(Design*des)
|
||||
osig->data_type(expr_type());
|
||||
osig->local_flag(true);
|
||||
|
||||
perm_string oname = scope->local_symbol();
|
||||
NetLogic*gate;
|
||||
NetUReduce::TYPE rtype = NetUReduce::NONE;
|
||||
|
||||
switch (op()) {
|
||||
case 'N':
|
||||
case '!':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::NOR, 1);
|
||||
rtype = NetUReduce::NOR;
|
||||
break;
|
||||
|
||||
case '&':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::AND, 1);
|
||||
rtype = NetUReduce::AND;
|
||||
break;
|
||||
|
||||
case '|':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::OR, 1);
|
||||
rtype = NetUReduce::OR;
|
||||
break;
|
||||
|
||||
case '^':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::XOR, 1);
|
||||
rtype = NetUReduce::XOR;
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::NAND, 1);
|
||||
rtype = NetUReduce::XNOR;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
gate = new NetLogic(scope, oname, isig->pin_count()+1,
|
||||
NetLogic::XNOR, 1);
|
||||
rtype = NetUReduce::XNOR;
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << get_line() << ": internal error: "
|
||||
<< "Unable to synthesize " << *this << "." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetUReduce*gate = new NetUReduce(scope, scope->local_symbol(),
|
||||
rtype, isig->vector_width());
|
||||
|
||||
des->add_node(gate);
|
||||
connect(gate->pin(0), osig->pin(0));
|
||||
for (unsigned idx = 0 ; idx < isig->pin_count() ; idx += 1)
|
||||
@@ -693,33 +704,6 @@ NetNet* NetEUReduce::synthesize(Design*des)
|
||||
return osig;
|
||||
}
|
||||
|
||||
NetNet* NetEMemory::synthesize(Design *des)
|
||||
{
|
||||
NetNet*adr = idx_->synthesize(des);
|
||||
|
||||
NetScope*scope = adr->scope();
|
||||
|
||||
NetRamDq*ram = new NetRamDq(scope, scope->local_symbol(),
|
||||
mem_, adr->vector_width());
|
||||
des->add_node(ram);
|
||||
ram->set_line(*this);
|
||||
|
||||
connect(ram->pin_Address(), adr->pin(0));
|
||||
|
||||
/* Create an output signal to receive the data. Assume that
|
||||
memories return LOGIC. */
|
||||
NetNet*osig = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, ram->width());
|
||||
osig->data_type(IVL_VT_LOGIC);
|
||||
osig->local_flag(true);
|
||||
osig->set_line(*this);
|
||||
|
||||
connect(ram->pin_Q(), osig->pin(0));
|
||||
|
||||
return osig;
|
||||
|
||||
}
|
||||
|
||||
NetNet* NetESelect::synthesize(Design *des)
|
||||
{
|
||||
|
||||
@@ -729,31 +713,15 @@ NetNet* NetESelect::synthesize(Design *des)
|
||||
|
||||
NetScope*scope = sub->scope();
|
||||
|
||||
unsigned off = 0;
|
||||
NetNet*off = 0;
|
||||
|
||||
// This handles the case that the NetESelect exists to do an
|
||||
// actual part/bit select. Generate a NetPartSelect object to
|
||||
// do the work, and replace "sub" with the selected output.
|
||||
if (base_ != 0) {
|
||||
// For now, only handle constant part selects in this
|
||||
// context. NOTE: the elaboration that created the
|
||||
// NetESelect already translated the part base to
|
||||
// canonical form, so the base_ is canonical already.
|
||||
NetEConst*bcon = dynamic_cast<NetEConst*>(base_);
|
||||
assert(bcon);
|
||||
off = base_->synthesize(des);
|
||||
|
||||
long bval = bcon->value().as_long();
|
||||
assert(bval >= 0);
|
||||
off = bval;
|
||||
}
|
||||
|
||||
/* If there is a part select, then generate a PartSelect node
|
||||
to actually do the part select. This does not expansion,
|
||||
that is handled later. */
|
||||
if ((off != 0) || (off+expr_width() < sub->vector_width())) {
|
||||
unsigned wid = expr_width();
|
||||
if ((wid + off) > sub->vector_width())
|
||||
wid = sub->vector_width() - off;
|
||||
|
||||
NetPartSelect*sel = new NetPartSelect(sub, off, wid,
|
||||
NetPartSelect::VP);
|
||||
NetPartSelect*sel = new NetPartSelect(sub, off, expr_width());
|
||||
sel->set_line(*this);
|
||||
des->add_node(sel);
|
||||
|
||||
@@ -766,13 +734,25 @@ NetNet* NetESelect::synthesize(Design *des)
|
||||
connect(sub->pin(0), sel->pin(0));
|
||||
}
|
||||
|
||||
/* Done? Vector is already the right width? then stop now. */
|
||||
|
||||
// Now look for the case that the NetESelect actually exists
|
||||
// to change the width of the expression. (i.e. to do
|
||||
// padding.) If this was for an actual part select that at
|
||||
// this point the output vector_width is exactly right, and we
|
||||
// are done.
|
||||
if (sub->vector_width() == expr_width())
|
||||
return sub;
|
||||
|
||||
// The vector_width is not exactly right, so the source is
|
||||
// probably asking for padding. Create nodes to do sign
|
||||
// extension or 0 extension, depending on the has_sign() mode
|
||||
// of the expression.
|
||||
|
||||
NetNet*net = new NetNet(scope, scope->local_symbol(),
|
||||
NetNet::IMPLICIT, expr_width());
|
||||
net->data_type(expr_type());
|
||||
net->local_flag(true);
|
||||
net->set_line(*this);
|
||||
if (has_sign()) {
|
||||
NetSignExtend*pad = new NetSignExtend(scope,
|
||||
scope->local_symbol(),
|
||||
@@ -890,6 +870,30 @@ NetNet* NetESignal::synthesize(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: expr_synth.cc,v $
|
||||
* Revision 1.87 2007/06/02 03:42:12 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.86 2007/04/15 01:37:29 steve
|
||||
* Allow bit/part select of vectors in continuous assignments.
|
||||
*
|
||||
* Revision 1.85 2007/04/12 05:21:54 steve
|
||||
* fix handling of unary reduction logic in certain nets.
|
||||
*
|
||||
* Revision 1.84 2007/04/04 02:31:57 steve
|
||||
* Remove useless assert
|
||||
*
|
||||
* Revision 1.83 2007/02/05 01:42:31 steve
|
||||
* Set some missing local flags.
|
||||
*
|
||||
* Revision 1.82 2007/01/20 02:10:45 steve
|
||||
* Get argument widths right for shift results.
|
||||
*
|
||||
* Revision 1.81 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.80 2006/08/08 05:11:37 steve
|
||||
* Handle 64bit delay constants.
|
||||
*
|
||||
|
||||
+11
-2
@@ -1,4 +1,7 @@
|
||||
|
||||
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
|
||||
|
||||
@@ -249,7 +252,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 then a
|
||||
is accepted. Further testing shows that any expression other than a
|
||||
simple unsized constant is accepted there, even if all the operands of
|
||||
all the operators that make up the expression are unsized integers.
|
||||
|
||||
@@ -498,8 +501,14 @@ of 4-value behavior in the dead zone, and appears more user friendly
|
||||
when viewed by reasonable viewers.
|
||||
|
||||
|
||||
$Id: ieee1364-notes.txt,v 1.17 2003/07/15 03:49:22 steve Exp $
|
||||
$Id: ieee1364-notes.txt,v 1.19 2007/04/18 02:36:13 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
-4
@@ -17,12 +17,12 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: iverilog-vpi.sh,v 1.16 2006/09/26 18:54:42 steve Exp $"
|
||||
#ident "$Id: iverilog-vpi.sh,v 1.17 2007/02/06 05:07:31 steve Exp $"
|
||||
|
||||
# These are the variables used for compiling files
|
||||
CC=gcc
|
||||
CXX=g++
|
||||
CFLAGS="@PIC@ -O -I@INCLUDEDIR@"
|
||||
CC=@IVCC@
|
||||
CXX=@IVCXX@
|
||||
CFLAGS="@PIC@ @IVCFLAGS@ -I@INCLUDEDIR@"
|
||||
|
||||
# These are used for linking...
|
||||
LD=gcc
|
||||
|
||||
@@ -29,7 +29,6 @@ ivl_expr_bits
|
||||
ivl_expr_def
|
||||
ivl_expr_dvalue
|
||||
ivl_expr_event
|
||||
ivl_expr_memory
|
||||
ivl_expr_name
|
||||
ivl_expr_opcode
|
||||
ivl_expr_oper1
|
||||
@@ -62,6 +61,7 @@ ivl_logic_type
|
||||
ivl_logic_udp
|
||||
ivl_logic_width
|
||||
|
||||
ivl_lpm_array
|
||||
ivl_lpm_aset_value
|
||||
ivl_lpm_async_clr
|
||||
ivl_lpm_async_set
|
||||
@@ -72,7 +72,6 @@ ivl_lpm_data
|
||||
ivl_lpm_datab
|
||||
ivl_lpm_define
|
||||
ivl_lpm_enable
|
||||
ivl_lpm_memory
|
||||
ivl_lpm_name
|
||||
ivl_lpm_q
|
||||
ivl_lpm_scope
|
||||
@@ -88,18 +87,11 @@ ivl_lpm_type
|
||||
ivl_lpm_width
|
||||
|
||||
ivl_lval_idx
|
||||
ivl_lval_mem
|
||||
ivl_lval_mux
|
||||
ivl_lval_part_off
|
||||
ivl_lval_sig
|
||||
ivl_lval_width
|
||||
|
||||
ivl_memory_basename
|
||||
ivl_memory_root
|
||||
ivl_memory_scope
|
||||
ivl_memory_size
|
||||
ivl_memory_width
|
||||
|
||||
ivl_nexus_get_private
|
||||
ivl_nexus_name
|
||||
ivl_nexus_ptrs
|
||||
@@ -117,6 +109,12 @@ 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
|
||||
@@ -128,8 +126,6 @@ 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
|
||||
@@ -142,11 +138,14 @@ ivl_scope_time_units
|
||||
ivl_scope_type
|
||||
ivl_scope_tname
|
||||
|
||||
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
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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
|
||||
+144
-252
@@ -19,10 +19,10 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: ivl_target.h,v 1.171 2006/09/23 04:57:19 steve Exp $"
|
||||
#ident "$Id: ivl_target.h,v 1.182 2007/04/02 01:12:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdint.h>
|
||||
# include <inttypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
#define _BEGIN_DECL extern "C" {
|
||||
@@ -59,6 +59,10 @@ _BEGIN_DECL
|
||||
* The following typedefs list the various cookies that may be passed
|
||||
* around.
|
||||
*
|
||||
* ivl_array_t
|
||||
* This object represent an array that can be a memory or a net
|
||||
* array. (They are the same from the perspective of ivl_target.h.)
|
||||
*
|
||||
* ivl_design_t
|
||||
* This object represents the entire elaborated design. Various
|
||||
* global properties and methods are available from this.
|
||||
@@ -137,6 +141,7 @@ _BEGIN_DECL
|
||||
* scope. These names are unique within a scope, but not necessarily
|
||||
* throughout the design.
|
||||
*/
|
||||
typedef struct ivl_array_s *ivl_array_t;
|
||||
typedef struct ivl_delaypath_s*ivl_delaypath_t;
|
||||
typedef struct ivl_design_s *ivl_design_t;
|
||||
typedef struct ivl_event_s *ivl_event_t;
|
||||
@@ -153,7 +158,7 @@ typedef struct ivl_parameter_s*ivl_parameter_t;
|
||||
typedef struct ivl_process_s *ivl_process_t;
|
||||
typedef struct ivl_scope_s *ivl_scope_t;
|
||||
typedef struct ivl_signal_s *ivl_signal_t;
|
||||
typedef struct ivl_memory_s *ivl_memory_t;
|
||||
typedef struct ivl_memory_s *ivl_memory_t; /* DEPRECATED */
|
||||
typedef struct ivl_statement_s*ivl_statement_t;
|
||||
|
||||
/*
|
||||
@@ -178,7 +183,7 @@ typedef enum ivl_drive_e {
|
||||
and incompatibilities to be introduced. */
|
||||
typedef enum ivl_expr_type_e {
|
||||
IVL_EX_NONE = 0,
|
||||
/* IVL_EX_BITSEL = 1, */
|
||||
IVL_EX_ARRAY = 18,
|
||||
IVL_EX_BINARY = 2,
|
||||
IVL_EX_CONCAT = 3,
|
||||
IVL_EX_EVENT = 17,
|
||||
@@ -225,6 +230,7 @@ typedef enum ivl_logic_e {
|
||||
/* This is the type of an LPM object. */
|
||||
typedef enum ivl_lpm_type_e {
|
||||
IVL_LPM_ADD = 0,
|
||||
IVL_LPM_ARRAY = 30,
|
||||
IVL_LPM_CONCAT = 16,
|
||||
IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */
|
||||
IVL_LPM_CMP_EQ = 10,
|
||||
@@ -252,7 +258,7 @@ typedef enum ivl_lpm_type_e {
|
||||
IVL_LPM_SHIFTR = 7,
|
||||
IVL_LPM_SIGN_EXT=27,
|
||||
IVL_LPM_SUB = 8,
|
||||
IVL_LPM_RAM = 9,
|
||||
/* IVL_LPM_RAM = 9, / obsolete */
|
||||
IVL_LPM_UFUNC = 14
|
||||
} ivl_lpm_type_t;
|
||||
|
||||
@@ -381,10 +387,21 @@ typedef const struct ivl_attribute_s*ivl_attribute_t;
|
||||
* This returns the nexus that is the source end of the delay
|
||||
* path. Transitions on the source are the start of the delay time
|
||||
* for this path.
|
||||
*
|
||||
* ivl_path_condit
|
||||
* This returns the nexus that tracks the condition for the
|
||||
* delay. If the delay path is unconditional, this returns nil.
|
||||
*
|
||||
* ivl_path_srouce_posedge
|
||||
* ivl_path_source_negedge
|
||||
* These functions return true if the source is edge sensitive.
|
||||
*/
|
||||
extern ivl_nexus_t ivl_path_source(ivl_delaypath_t obj);
|
||||
extern uint64_t ivl_path_delay(ivl_delaypath_t obj, ivl_path_edge_t pt);
|
||||
extern ivl_nexus_t ivl_path_condit(ivl_delaypath_t obj);
|
||||
|
||||
extern int ivl_path_source_posedge(ivl_delaypath_t obj);
|
||||
extern int ivl_path_source_negedge(ivl_delaypath_t obj);
|
||||
|
||||
/* DESIGN
|
||||
* When handed a design (ivl_design_t) there are a few things that you
|
||||
@@ -574,6 +591,14 @@ extern ivl_nexus_t ivl_event_pos(ivl_event_t net, unsigned idx);
|
||||
*
|
||||
* SEMANTIC NOTES
|
||||
*
|
||||
* - IVL_EX_ARRAY
|
||||
* This expression type is a special case of the IVL_EX_SIGNAL where
|
||||
* the target is an array (ivl_signal_t with an array_count) but there
|
||||
* is no index expression. This is used only in the special situation
|
||||
* where the array is passed to a system task/function. The function
|
||||
* ivl_expr_signal returns the ivl_signal_t of the array object, and
|
||||
* from that all the properties of the array can be determined.
|
||||
*
|
||||
* - IVL_EX_BINARY
|
||||
*
|
||||
* - IVL_EX_SELECT
|
||||
@@ -583,6 +608,33 @@ extern ivl_nexus_t ivl_event_pos(ivl_event_t net, unsigned idx);
|
||||
* is the base of a vector. The compiler has already figured out any
|
||||
* conversion from signal units to vector units, so the result of
|
||||
* ivl_expr_oper1 should range from 0 to ivl_expr_width().
|
||||
*
|
||||
* - IVL_EX_SIGNAL
|
||||
* This expression references a signal vector. The ivl_expr_signal
|
||||
* function gets a handle for the signal that is referenced. The
|
||||
* signal may be an array (see the ivl_signal_array_count function)
|
||||
* that is addressed by the expression returned by the ivl_expr_oper1
|
||||
* function. This expression returns a *canonical* address. The core
|
||||
* compiler already corrected the expression to account for index
|
||||
* bases.
|
||||
*
|
||||
* The ivl_expr_width function returns the vector width of the signal
|
||||
* word. The ivl_expr_value returns the data type of the word.
|
||||
*
|
||||
* Bit and part selects are not done here. The IVL_EX_SELECT
|
||||
* expression does bit/part selects on the word read from the signal.
|
||||
*
|
||||
* - IVL_EX_STRING
|
||||
* This expression refers to a string constant. The ivl_expr_string
|
||||
* function returns a pointer to the first byte of the string. The
|
||||
* compiler has translated it to a "vvp escaped string" which has
|
||||
* quoting and escapes eliminated. The string may contain octal
|
||||
* escapes (\<oct>) so that the string text returned by
|
||||
* ivl_expr_string will only contain graphical characters. It is up to
|
||||
* the target to change the escaped \NNN to the proper byte value when
|
||||
* using this string. No other escape sequences will appear in the
|
||||
* string. Quote (") and slash (\) characters will be delivered in
|
||||
* \NNN form.
|
||||
*/
|
||||
|
||||
extern ivl_expr_type_t ivl_expr_type(ivl_expr_t net);
|
||||
@@ -627,42 +679,7 @@ extern unsigned long ivl_expr_uvalue(ivl_expr_t net);
|
||||
/* any expression */
|
||||
extern unsigned ivl_expr_width(ivl_expr_t net);
|
||||
|
||||
/*
|
||||
* Memory.
|
||||
* Memories are declared in Verilog source as 2 dimensional arrays of
|
||||
* reg bits. This means that they are simple arrays of vectors. The
|
||||
* vectors in the array are called "words".
|
||||
*
|
||||
* ivl_memory_name (DEPRECATED)
|
||||
*
|
||||
* ivl_memory_basename
|
||||
* This returns the base name of the memory object. The base name
|
||||
* does not include the name of the scopes that contains the object.
|
||||
*
|
||||
* ivl_memory_root
|
||||
* The root of the memory is the value to add to a calculated
|
||||
* address to get to a canonical (0-based) address. This value is
|
||||
* used when external code wishes to access a word. All the
|
||||
* compiled references to the word within the compiled design are
|
||||
* converted to canonical form by the compiler.
|
||||
*
|
||||
* ivl_memory_size
|
||||
* ivl_memory_width
|
||||
* These functions return the dimensions of the memory. The size is
|
||||
* the number of words in the memory, and the width is the number
|
||||
* of bits in each word.
|
||||
*
|
||||
* ivl_memory_scope
|
||||
* This returns the scope that contains the memory.
|
||||
*/
|
||||
|
||||
extern const char*ivl_memory_basename(ivl_memory_t net);
|
||||
extern int ivl_memory_root(ivl_memory_t net);
|
||||
extern ivl_scope_t ivl_memory_scope(ivl_memory_t net);
|
||||
extern unsigned ivl_memory_size(ivl_memory_t net);
|
||||
extern unsigned ivl_memory_width(ivl_memory_t net);
|
||||
|
||||
extern ivl_memory_t ivl_expr_memory(ivl_expr_t net);
|
||||
|
||||
/* LOGIC
|
||||
* These types and functions support manipulation of logic gates. The
|
||||
@@ -750,7 +767,7 @@ extern ivl_memory_t ivl_expr_memory(ivl_expr_t net);
|
||||
* These devices are grouped as logic devices with zero inputs because
|
||||
* the outputs have the same characteristics as other logic
|
||||
* devices. They are special only in that they have zero inputs, and
|
||||
* their drivers typically have strength other then strong.
|
||||
* their drivers typically have strength other than strong.
|
||||
*
|
||||
* - IVL_LO_UDP
|
||||
* User defined primitives (UDPs) are like any other logic devices, in
|
||||
@@ -909,7 +926,7 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
||||
* inputs. In fact, the compiler doesn't assure that the widths of the
|
||||
* inputs add up to the width of the output, but the possibility
|
||||
* exists. It is *not* an error for the sum of the input widths to be
|
||||
* more then the width of the output, although the possibility of
|
||||
* more than the width of the output, although the possibility of
|
||||
* overflow exists at run time.
|
||||
*
|
||||
* Multiply may be signed. If so, the output should be sign extended
|
||||
@@ -975,7 +992,7 @@ extern const char* ivl_udp_name(ivl_udp_t net);
|
||||
* single ivl_lpm_data input are the same with, ivl_lpm_width. This
|
||||
* device carries a vector like other LPM devices.
|
||||
*
|
||||
* - Memory port (IVL_LPM_RAM)
|
||||
* - Memory port (IVL_LPM_RAM) (deprecated in favor of IVL_LPM_ARRAY)
|
||||
* These are structural ports into a memory device. They represent
|
||||
* address/data ports of a memory device that the context can hook to
|
||||
* for read or write. Read devices have an ivl_lpm_q output port that
|
||||
@@ -1069,34 +1086,33 @@ extern ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net);
|
||||
extern ivl_nexus_t ivl_lpm_sync_clr(ivl_lpm_t net);
|
||||
extern ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net);
|
||||
extern ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net);
|
||||
/* IVL_LPM_ARRAY */
|
||||
extern ivl_signal_t ivl_lpm_array(ivl_lpm_t net);
|
||||
/* IVL_LPM_PART */
|
||||
extern unsigned ivl_lpm_base(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF IVL_LPM_RAM */
|
||||
/* IVL_LPM_FF */
|
||||
extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net);
|
||||
/* IVL_LPM_UFUNC */
|
||||
extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net);
|
||||
/* IVL_LPM_FF IVL_LPM_RAM */
|
||||
/* IVL_LPM_FF */
|
||||
extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net);
|
||||
/* IVL_LPM_ADD IVL_LPM_CONCAT IVL_LPM_FF IVL_LPM_PART IVL_LPM_MULT
|
||||
IVL_LPM_MUX IVL_LPM_RAM IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB
|
||||
IVL_LPM_MUX IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB
|
||||
IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_SUB */
|
||||
extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_RAM
|
||||
/* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART
|
||||
IVL_LPM_SUB IVL_LPM_UFUNC */
|
||||
extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx);
|
||||
/* IVL_LPM_MUX IVL_LPM_RAM */
|
||||
/* IVL_LPM_MUX */
|
||||
extern unsigned ivl_lpm_selects(ivl_lpm_t net);
|
||||
/* IVL_LPM_MUX IVL_LPM_RAM */
|
||||
/* IVL_LPM_MUX */
|
||||
extern ivl_nexus_t ivl_lpm_select(ivl_lpm_t net);
|
||||
/* IVL_LPM_CONCAT IVL_LPM_MUX IVL_LPM_REPEAT IVL_LPM_UFUNC */
|
||||
extern unsigned ivl_lpm_size(ivl_lpm_t net);
|
||||
/* IVL_LPM_SFUNC */
|
||||
extern const char*ivl_lpm_string(ivl_lpm_t net);
|
||||
/* IVL_LPM_RAM */
|
||||
extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
||||
|
||||
|
||||
/* LVAL
|
||||
* The l-values of assignments are concatenation of ivl_lval_t
|
||||
@@ -1119,7 +1135,7 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
||||
*
|
||||
* (Should this be combined with ivl_lval_idx? -Ed)
|
||||
*
|
||||
* ivl_lval_mem
|
||||
* ivl_lval_mem (deprecated)
|
||||
* If the l-value is a memory, this method returns an
|
||||
* ivl_memory_t that represents that memory. Otherwise, it
|
||||
* returns 0.
|
||||
@@ -1149,18 +1165,26 @@ extern ivl_memory_t ivl_lpm_memory(ivl_lpm_t net);
|
||||
* The ivl_lval_part_off is the canonical base of a part or
|
||||
* bit select.
|
||||
*
|
||||
* - Memory words
|
||||
* - Memory words (Replace this with Array words below)
|
||||
* If the l-value is a memory word, the ivl_lval_mem function returns
|
||||
* a non-nil value. The ivl_lval_idx function will return an
|
||||
* expression that calculates an address for the memory. The compiler
|
||||
* will assure that the ivl_lval_width will exactly match the
|
||||
* ivl_memory_width of the memory word.
|
||||
*
|
||||
* - Array words
|
||||
* If the l-value is an array, then ivl_lval_idx function will return
|
||||
* an expression that calculates the address of the array word. If
|
||||
* the referenced signal has more than one word, this expression must
|
||||
* be present. If the signal has exactly one word (it is not an array)
|
||||
* then the ivl_lval_idx exression must *not* be present.
|
||||
*
|
||||
* For array words, the ivl_lval_width is the width of the word.
|
||||
*/
|
||||
|
||||
extern unsigned ivl_lval_width(ivl_lval_t net);
|
||||
extern ivl_expr_t ivl_lval_mux(ivl_lval_t net); // XXXX Obsolete?
|
||||
extern ivl_expr_t ivl_lval_idx(ivl_lval_t net);
|
||||
extern ivl_memory_t ivl_lval_mem(ivl_lval_t net);
|
||||
extern ivl_expr_t ivl_lval_part_off(ivl_lval_t net);
|
||||
extern ivl_signal_t ivl_lval_sig(ivl_lval_t net);
|
||||
|
||||
@@ -1320,7 +1344,7 @@ extern ivl_expr_t ivl_parameter_expr(ivl_parameter_t net);
|
||||
* ivl_scope_children
|
||||
* A scope may in turn contain other scopes. This method iterates
|
||||
* through all the child scopes of a given scope. If the function
|
||||
* returns any value other then 0, the iteration stops and the
|
||||
* returns any value other than 0, the iteration stops and the
|
||||
* method returns that value. Otherwise, iteration continues until
|
||||
* the children run out.
|
||||
*
|
||||
@@ -1329,7 +1353,9 @@ extern ivl_expr_t ivl_parameter_expr(ivl_parameter_t net);
|
||||
*
|
||||
* ivl_scope_def
|
||||
* Task definition scopes carry a task definition, in the form of
|
||||
* a statement. This method accesses that definition.
|
||||
* a statement. This method accesses that definition. The
|
||||
* ivl_scope_def function must return a statement for scopes that
|
||||
* are type FUNCTION or TASK, and must return nil otherwise.
|
||||
*
|
||||
* ivl_scope_event
|
||||
* ivl_scope_events
|
||||
@@ -1407,8 +1433,6 @@ extern unsigned ivl_scope_logs(ivl_scope_t net);
|
||||
extern ivl_net_logic_t ivl_scope_log(ivl_scope_t net, unsigned idx);
|
||||
extern unsigned ivl_scope_lpms(ivl_scope_t net);
|
||||
extern ivl_lpm_t ivl_scope_lpm(ivl_scope_t, unsigned idx);
|
||||
extern unsigned ivl_scope_mems(ivl_scope_t net);
|
||||
extern ivl_memory_t ivl_scope_mem(ivl_scope_t net, unsigned idx);
|
||||
extern const char* ivl_scope_name(ivl_scope_t net);
|
||||
extern const char* ivl_scope_basename(ivl_scope_t net);
|
||||
extern unsigned ivl_scope_params(ivl_scope_t net);
|
||||
@@ -1432,17 +1456,26 @@ extern int ivl_scope_time_units(ivl_scope_t net);
|
||||
* Signals have a name (obviously) and types. A signal may also be
|
||||
* signed or unsigned.
|
||||
*
|
||||
* ivl_signal_pins (replace these with ivl_signal_nex)
|
||||
* ivl_signal_pin
|
||||
* The ivl_signal_pin function returns the nexus connected to the
|
||||
* signal. If the signal is a vector, the idx can be a non-zero
|
||||
* value, and the result is the nexus for the specified bit.
|
||||
*
|
||||
* ivl_signal_nex
|
||||
* This is the nexus of the signal. This is used for managing
|
||||
* connections to the rest of the net. There is exactly one pin for
|
||||
* a signal. If the signal represents a vector, then the entire
|
||||
* vector is carried through the single output.
|
||||
* each word of a signal. Each word may in turn be a vector. The
|
||||
* word address is the zero-based index for the word. It is up to
|
||||
* the context to translate different bases to the canonical address.
|
||||
*
|
||||
* ivl_signal_array_base
|
||||
* ivl_signal_array_count
|
||||
* The signal may be arrayed. If so, the array_count is >1. Each
|
||||
* word of the array has its own nexus. The array_base is the
|
||||
* address is the Verilg source for the canonical zero word. This
|
||||
* may be negative, positive or zero.
|
||||
*
|
||||
* Note that arraying of the signal into words is distinct from the
|
||||
* vectors. The width of a signal is the width of a WORD.
|
||||
*
|
||||
* ivl_signal_dimensions
|
||||
* The signal may be an array (of vectors) in which case this
|
||||
* function returns >0, the number of dimensions of the array.
|
||||
*
|
||||
* ivl_signal_msb
|
||||
* ivl_signal_lsb
|
||||
@@ -1503,7 +1536,10 @@ extern int ivl_scope_time_units(ivl_scope_t net);
|
||||
* key does not exist, the function returns 0.
|
||||
*/
|
||||
|
||||
extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net);
|
||||
extern ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word);
|
||||
extern int ivl_signal_array_base(ivl_signal_t net);
|
||||
extern unsigned ivl_signal_array_count(ivl_signal_t net);
|
||||
extern unsigned ivl_signal_dimensions(ivl_signal_t net);
|
||||
extern int ivl_signal_msb(ivl_signal_t net);
|
||||
extern int ivl_signal_lsb(ivl_signal_t net);
|
||||
extern unsigned ivl_signal_width(ivl_signal_t net);
|
||||
@@ -1568,7 +1604,7 @@ extern ivl_statement_type_t ivl_statement_type(ivl_statement_t net);
|
||||
/*
|
||||
* The following functions retrieve specific single values from the
|
||||
* statement. These values are the bits of data and parameters that
|
||||
* make up the statement. Many of these functions apply to more then
|
||||
* make up the statement. Many of these functions apply to more than
|
||||
* one type of statement, so the comment in front of them tells which
|
||||
* statement types can be passed to the function.
|
||||
*
|
||||
@@ -1587,7 +1623,7 @@ extern ivl_statement_type_t ivl_statement_type(ivl_statement_t net);
|
||||
* ivl_stmt_lval
|
||||
* ivl_stmt_lvals
|
||||
* Return the number of l-values for an assignment statement, or
|
||||
* the specific l-value. If there is more then 1 l-value, then the
|
||||
* the specific l-value. If there is more than 1 l-value, then the
|
||||
* l-values are presumed to be vector values concatenated together
|
||||
* from msb (idx==0) to lsb.
|
||||
*
|
||||
@@ -1634,8 +1670,8 @@ extern ivl_statement_type_t ivl_statement_type(ivl_statement_t net);
|
||||
* - IVL_ST_DELAY, IVL_ST_DELAYX
|
||||
* These statement types are delay statements. They are a way to
|
||||
* attach a delay to a statement. The ivl_stmt_sub_stmt() function
|
||||
* gets the statment to be executed after the delay. If this an
|
||||
* ivl_ST_DELAY, then the ivl_stmt_delay_val function gets the
|
||||
* gets the statement to be executed after the delay. If this is
|
||||
* IVL_ST_DELAY, then the ivl_stmt_delay_val function gets the
|
||||
* constant delay. If this is IVL_ST_DELAYX, then the
|
||||
* ivl_stmt_delay_expr gets the expression of the delay. In this case,
|
||||
* the expression is not necessarily constant.
|
||||
@@ -1706,10 +1742,6 @@ extern unsigned ivl_stmt_lvals(ivl_statement_t net);
|
||||
extern unsigned ivl_stmt_lwidth(ivl_statement_t net);
|
||||
/* IVL_ST_STASK */
|
||||
extern const char* ivl_stmt_name(ivl_statement_t net);
|
||||
#if 0
|
||||
extern ivl_nexus_t ivl_stmt_nexus(ivl_statement_t net, unsigned idx);
|
||||
extern unsigned ivl_stmt_nexus_count(ivl_statement_t net);
|
||||
#endif
|
||||
/* IVL_ST_STASK */
|
||||
extern ivl_expr_t ivl_stmt_parm(ivl_statement_t net, unsigned idx);
|
||||
/* IVL_ST_STASK */
|
||||
@@ -1752,6 +1784,42 @@ _END_DECL
|
||||
|
||||
/*
|
||||
* $Log: ivl_target.h,v $
|
||||
* Revision 1.182 2007/04/02 01:12:34 steve
|
||||
* Seperate arrayness from word count
|
||||
*
|
||||
* Revision 1.181 2007/03/22 16:08:16 steve
|
||||
* Spelling fixes from Larry
|
||||
*
|
||||
* Revision 1.180 2007/03/02 06:13:22 steve
|
||||
* Add support for edge sensitive spec paths.
|
||||
*
|
||||
* Revision 1.179 2007/03/01 06:19:38 steve
|
||||
* Add support for conditional specify delay paths.
|
||||
*
|
||||
* Revision 1.178 2007/02/26 19:49:49 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.177 2007/02/25 23:08:24 steve
|
||||
* Process Verilog escape sequences much earlier.
|
||||
*
|
||||
* Revision 1.176 2007/02/02 04:33:00 steve
|
||||
* Use inttypes.h instead of stdint.h for portability.
|
||||
*
|
||||
* Revision 1.175 2007/01/29 01:52:51 steve
|
||||
* Clarify the use of ivl_scope_def for not-functions.
|
||||
*
|
||||
* Revision 1.174 2007/01/17 05:00:12 steve
|
||||
* Dead code for memories in scopes.
|
||||
*
|
||||
* Revision 1.173 2007/01/17 04:39:18 steve
|
||||
* Remove dead code related to memories.
|
||||
*
|
||||
* Revision 1.172 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.171 2006/09/23 04:57:19 steve
|
||||
* Basic support for specify timing.
|
||||
*
|
||||
@@ -1781,181 +1849,5 @@ _END_DECL
|
||||
*
|
||||
* Revision 1.162 2005/11/20 15:58:25 steve
|
||||
* Document the IVL_ST_DELAY statements.
|
||||
*
|
||||
* Revision 1.161 2005/09/19 21:45:35 steve
|
||||
* Spelling patches from Larry.
|
||||
*
|
||||
* Revision 1.160 2005/09/01 04:11:37 steve
|
||||
* Generate code to handle real valued muxes.
|
||||
*
|
||||
* Revision 1.159 2005/08/06 17:58:16 steve
|
||||
* Implement bi-directional part selects.
|
||||
*
|
||||
* Revision 1.158 2005/07/11 16:56:50 steve
|
||||
* Remove NetVariable and ivl_variable_t structures.
|
||||
*
|
||||
* Revision 1.157 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.156 2005/06/13 22:25:37 steve
|
||||
* Document ivl_logic_delay function.
|
||||
*
|
||||
* Revision 1.155 2005/05/24 01:44:28 steve
|
||||
* Do sign extension of structuran nets.
|
||||
*
|
||||
* Revision 1.154 2005/05/08 23:44:08 steve
|
||||
* Add support for variable part select.
|
||||
*
|
||||
* Revision 1.153 2005/05/07 03:14:00 steve
|
||||
* Clarify internal delays for assignments.
|
||||
*
|
||||
* Revision 1.152 2005/04/24 23:44:02 steve
|
||||
* Update DFF support to new data flow.
|
||||
*
|
||||
* Revision 1.151 2005/04/13 06:35:11 steve
|
||||
* Make logic aware of strength.
|
||||
*
|
||||
* Revision 1.150 2005/04/08 04:52:31 steve
|
||||
* Make clear that memory addresses are cannonical.
|
||||
*
|
||||
* Revision 1.149 2005/04/06 05:29:08 steve
|
||||
* Rework NetRamDq and IVL_LPM_RAM nodes.
|
||||
*
|
||||
* Revision 1.148 2005/04/01 06:04:30 steve
|
||||
* Clean up handle of UDPs.
|
||||
*
|
||||
* Revision 1.147 2005/03/18 02:56:03 steve
|
||||
* Add support for LPM_UFUNC user defined functions.
|
||||
*
|
||||
* Revision 1.146 2005/03/09 04:53:40 steve
|
||||
* Generate code for new form of memory ports.
|
||||
*
|
||||
* Revision 1.145 2005/03/05 05:47:42 steve
|
||||
* Handle memory words in l-value concatenations.
|
||||
*
|
||||
* Revision 1.144 2005/03/03 04:34:42 steve
|
||||
* Rearrange how memories are supported as vvp_vector4 arrays.
|
||||
*
|
||||
* Revision 1.143 2005/02/19 02:43:38 steve
|
||||
* Support shifts and divide.
|
||||
*
|
||||
* Revision 1.142 2005/02/14 01:51:39 steve
|
||||
* Handle bit selects in l-values to assignments.
|
||||
*
|
||||
* Revision 1.141 2005/02/13 01:15:07 steve
|
||||
* Replace supply nets with wires connected to pullup/down supply devices.
|
||||
*
|
||||
* Revision 1.140 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.139 2005/02/08 00:12:36 steve
|
||||
* Add the NetRepeat node, and code generator support.
|
||||
*
|
||||
* Revision 1.138 2005/02/03 04:56:20 steve
|
||||
* laborate reduction gates into LPM_RED_ nodes.
|
||||
*
|
||||
* Revision 1.137 2005/01/29 18:46:18 steve
|
||||
* Netlist boolean expressions generate gate vectors.
|
||||
*
|
||||
* Revision 1.136 2005/01/29 16:47:20 steve
|
||||
* Clarify width of nexus.
|
||||
*
|
||||
* Revision 1.135 2005/01/28 05:39:33 steve
|
||||
* Simplified NetMult and IVL_LPM_MULT.
|
||||
*
|
||||
* Revision 1.134 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.133 2005/01/22 17:36:59 steve
|
||||
* stub dump signed flags of magnitude compare.
|
||||
*
|
||||
* Revision 1.132 2005/01/22 01:06:55 steve
|
||||
* Change case compare from logic to an LPM node.
|
||||
*
|
||||
* Revision 1.131 2005/01/09 20:16:01 steve
|
||||
* Use PartSelect/PV and VP to handle part selects through ports.
|
||||
*
|
||||
* Revision 1.130 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.129 2004/12/18 18:56:18 steve
|
||||
* Add ivl_event_scope, and better document ivl_event_X methods.
|
||||
*
|
||||
* Revision 1.128 2004/12/15 17:10:40 steve
|
||||
* Fixup force statement elaboration.
|
||||
*
|
||||
* Revision 1.127 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.126 2004/10/04 01:10:53 steve
|
||||
* Clean up spurious trailing white space.
|
||||
*
|
||||
* Revision 1.125 2004/09/25 01:58:12 steve
|
||||
* Some commentary on ivl_logic_pin.
|
||||
*
|
||||
* Revision 1.124 2003/12/03 02:46:24 steve
|
||||
* Add support for wait on list of named events.
|
||||
*
|
||||
* Revision 1.123 2003/11/08 20:06:21 steve
|
||||
* Spelling fixes in comments.
|
||||
*
|
||||
* Revision 1.122 2003/08/22 23:14:26 steve
|
||||
* Preserve variable ranges all the way to the vpi.
|
||||
*
|
||||
* Revision 1.121 2003/08/15 02:23:52 steve
|
||||
* Add synthesis support for synchronous reset.
|
||||
*
|
||||
* Revision 1.120 2003/07/30 01:13:28 steve
|
||||
* Add support for triand and trior.
|
||||
*
|
||||
* Revision 1.119 2003/06/23 01:25:44 steve
|
||||
* Module attributes make it al the way to ivl_target.
|
||||
*
|
||||
* Revision 1.118 2003/05/14 05:26:41 steve
|
||||
* Support real expressions in case statements.
|
||||
*
|
||||
* Revision 1.117 2003/04/22 04:48:29 steve
|
||||
* Support event names as expressions elements.
|
||||
*
|
||||
* Revision 1.116 2003/04/11 05:18:08 steve
|
||||
* Handle signed magnitude compare all the
|
||||
* way through to the vvp code generator.
|
||||
*
|
||||
* Revision 1.115 2003/03/10 23:40:53 steve
|
||||
* Keep parameter constants for the ivl_target API.
|
||||
*
|
||||
* Revision 1.114 2003/03/06 01:24:37 steve
|
||||
* Obsolete the ivl_event_name function.
|
||||
*
|
||||
* Revision 1.113 2003/03/06 00:28:41 steve
|
||||
* All NetObj objects have lex_string base names.
|
||||
*
|
||||
* Revision 1.112 2003/02/26 01:29:24 steve
|
||||
* LPM objects store only their base names.
|
||||
*
|
||||
* Revision 1.111 2003/01/30 16:23:07 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.110 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.109 2002/12/21 00:55:58 steve
|
||||
* The $time system task returns the integer time
|
||||
* scaled to the local units. Change the internal
|
||||
* implementation of vpiSystemTime the $time functions
|
||||
* to properly account for this. Also add $simtime
|
||||
* to get the simulation time.
|
||||
*/
|
||||
#endif
|
||||
|
||||
+74
-6
@@ -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.46 2004/09/10 00:15:45 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.48 2007/05/30 23:21:20 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -70,7 +70,14 @@ 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;
|
||||
|
||||
@@ -111,11 +118,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);
|
||||
istack->path, istack->lineno+1);
|
||||
|
||||
fprintf(stderr, "%s:%u: : "
|
||||
"This is the odd matched `ifdef.\n",
|
||||
cur->path, cur->lineno);
|
||||
cur->path, cur->lineno+1);
|
||||
}
|
||||
|
||||
free(cur->path);
|
||||
@@ -309,7 +316,24 @@ W [ \t\b\f]+
|
||||
yy_push_state(IFDEF_SUPR);
|
||||
}
|
||||
|
||||
<IFDEF_TRUE>`else { BEGIN(IFDEF_FALSE); }
|
||||
<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_FALSE>`else { BEGIN(IFDEF_TRUE); }
|
||||
<IFDEF_SUPR>`else { }
|
||||
|
||||
@@ -322,6 +346,42 @@ 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(); }
|
||||
|
||||
@@ -759,7 +819,7 @@ static void lexor_done()
|
||||
ifdef_stack = cur->next;
|
||||
|
||||
fprintf(stderr, "%s:%u: error: This `ifdef lacks an `endif.\n",
|
||||
cur->path, cur->lineno);
|
||||
cur->path, cur->lineno+1);
|
||||
|
||||
free(cur->path);
|
||||
free(cur);
|
||||
@@ -777,11 +837,14 @@ 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) {
|
||||
fclose(isp->file);
|
||||
/* Delay the close of this file, because the yyrestart
|
||||
below seems to have some memory of this file. */
|
||||
delayed_close = isp->file;
|
||||
free(isp->path);
|
||||
} else {
|
||||
/* If I am printing line directives and I just finished
|
||||
@@ -825,6 +888,7 @@ static int yywrap()
|
||||
}
|
||||
|
||||
yyrestart(istack->file);
|
||||
if (delayed_close) fclose(delayed_close);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -833,6 +897,7 @@ 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",
|
||||
@@ -854,6 +919,7 @@ void reset_lexor(FILE*out, char*paths[])
|
||||
isp->path = strdup(paths[0]);
|
||||
isp->file = fopen(paths[0], "r");
|
||||
isp->str = 0;
|
||||
isp->lineno = 0;
|
||||
if (isp->file == 0) {
|
||||
perror(paths[0]);
|
||||
exit(1);
|
||||
@@ -876,8 +942,10 @@ void reset_lexor(FILE*out, char*paths[])
|
||||
for (idx = 1 ; paths[idx] ; idx += 1) {
|
||||
isp = malloc(sizeof(struct include_stack_t));
|
||||
isp->path = strdup(paths[idx]);
|
||||
isp->file = 0;
|
||||
isp->str = 0;
|
||||
isp->next = 0;
|
||||
isp->lineno = 0;
|
||||
if (tail)
|
||||
tail->next = isp;
|
||||
else
|
||||
|
||||
@@ -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.92 2006/07/31 03:50:17 steve Exp $"
|
||||
#ident "$Id: lexor.lex,v 1.96 2007/06/14 03:50:00 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -53,6 +53,7 @@ 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;
|
||||
@@ -72,6 +73,13 @@ 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;
|
||||
}
|
||||
|
||||
@@ -101,6 +109,7 @@ static int comment_enter;
|
||||
%s UDPTABLE
|
||||
%x PPTIMESCALE
|
||||
%x PPDEFAULT_NETTYPE
|
||||
%s EDGES
|
||||
|
||||
W [ \t\b\f\r]+
|
||||
|
||||
@@ -159,11 +168,12 @@ W [ \t\b\f\r]+
|
||||
with "*" and return that. */
|
||||
"("{W}*"*"{W}*")" { return '*'; }
|
||||
|
||||
|
||||
<EDGES>"]" { BEGIN(0); return yytext[0]; }
|
||||
[}{;:\[\],()#=.@&!?<>%|^~+*/-] { return yytext[0]; }
|
||||
|
||||
\" { BEGIN(CSTRING); }
|
||||
<CSTRING>\\\" { yymore(); }
|
||||
<CSTRING>\\\\ { yymore(); /* Catch \\, which is a \ escaping itself */ }
|
||||
<CSTRING>\\\" { yymore(); /* Catch \", which is an escaped quote */ }
|
||||
<CSTRING>\n { BEGIN(0);
|
||||
yylval.text = strdup(yytext);
|
||||
VLerror(yylloc, "Missing close quote of string.");
|
||||
@@ -201,6 +211,17 @@ 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) {
|
||||
@@ -221,6 +242,10 @@ W [ \t\b\f\r]+
|
||||
}
|
||||
break;
|
||||
|
||||
case K_edge:
|
||||
BEGIN(EDGES);
|
||||
break;
|
||||
|
||||
default:
|
||||
yylval.text = 0;
|
||||
break;
|
||||
@@ -460,7 +485,7 @@ static verinum*make_unsized_binary(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
verinum*out = new verinum(bits, size);
|
||||
verinum*out = new verinum(bits, size, false);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
@@ -520,7 +545,7 @@ static verinum*make_unsized_octal(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
verinum*out = new verinum(bits, size);
|
||||
verinum*out = new verinum(bits, size, false);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
@@ -590,7 +615,7 @@ static verinum*make_unsized_hex(const char*txt)
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
verinum*out = new verinum(bits, size);
|
||||
verinum*out = new verinum(bits, size, false);
|
||||
out->has_sign(sign_flag);
|
||||
delete[]bits;
|
||||
return out;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
# 59 Temple Place - Suite 330
|
||||
# Boston, MA 02111-1307, USA
|
||||
#
|
||||
#ident "$Id: Makefile.in,v 1.35 2006/10/30 22:45:37 steve Exp $"
|
||||
#ident "$Id: Makefile.in,v 1.36 2007/02/06 05:07:32 steve Exp $"
|
||||
#
|
||||
#
|
||||
SHELL = /bin/sh
|
||||
@@ -41,7 +41,6 @@ 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 \
|
||||
|
||||
@@ -23,7 +23,7 @@ AC_CHECK_SIZEOF(unsigned)
|
||||
# may modify CPPFLAGS and CFLAGS
|
||||
AX_CPP_PRECOMP
|
||||
|
||||
# Compiler option for position independent code, needed whan making shared objects.
|
||||
# Compiler option for position independent code, needed when making shared objects.
|
||||
AX_C_PICFLAG
|
||||
|
||||
AC_SUBST(EXEEXT)
|
||||
|
||||
@@ -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.16 2006/10/30 22:45:37 steve Exp $"
|
||||
#ident "$Id: veriusertfs.c,v 1.17 2007/05/08 22:01:26 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -58,7 +58,7 @@ void veriusertfs_register_table(p_tfcell vtable)
|
||||
p_tfcell tf;
|
||||
s_vpi_systf_data tf_data;
|
||||
p_pli_data data;
|
||||
char trace_buf[1024];
|
||||
static 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++) {
|
||||
@@ -389,6 +389,9 @@ 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)
|
||||
*
|
||||
|
||||
+16
-1
@@ -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.17 2004/10/04 01:10:53 steve Exp $"
|
||||
#ident "$Id: link_const.cc,v 1.18 2007/04/14 03:10:51 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -132,6 +132,8 @@ 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;
|
||||
@@ -140,6 +142,16 @@ 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,6 +176,9 @@ 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.
|
||||
*
|
||||
|
||||
@@ -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.93 2006/09/28 04:35:18 steve Exp $"
|
||||
#ident "$Id: main.cc,v 1.95 2007/04/19 02:52:53 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -94,6 +94,7 @@ 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;
|
||||
|
||||
@@ -125,6 +126,8 @@ bool debug_synth2 = false;
|
||||
*/
|
||||
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.
|
||||
@@ -277,6 +280,15 @@ static void parm_to_flagmap(const string&flag)
|
||||
* 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.
|
||||
*
|
||||
@@ -367,6 +379,13 @@ 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);
|
||||
@@ -634,11 +653,20 @@ int main(int argc, char*argv[])
|
||||
for (mod = pform_modules.begin()
|
||||
; mod != pform_modules.end()
|
||||
; mod++) {
|
||||
if (mentioned_p[(*mod).second->mod_name()] == false) {
|
||||
if (verbose_flag)
|
||||
cout << " " << (*mod).second->mod_name();
|
||||
roots.push_back((*mod).second->mod_name());
|
||||
}
|
||||
|
||||
/* 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 (verbose_flag)
|
||||
cout << endl;
|
||||
@@ -787,6 +815,12 @@ 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.94 2007/03/07 04:24:59 steve
|
||||
* Make integer width controllable.
|
||||
*
|
||||
* Revision 1.93 2006/09/28 04:35:18 steve
|
||||
* Support selective control of specify and xtypes features.
|
||||
*
|
||||
|
||||
@@ -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 then the compiler.
|
||||
developer tools other than 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
|
||||
|
||||
+17
-27
@@ -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.21 2006/02/02 02:43:58 steve Exp $"
|
||||
#ident "$Id: net_assign.cc,v 1.22 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -39,20 +39,13 @@ unsigned count_lval_width(const NetAssign_*idx)
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetNet*s)
|
||||
: sig_(s), mem_(0), bmux_(0), base_(0)
|
||||
: sig_(s), word_(0), base_(0)
|
||||
{
|
||||
lwid_ = sig_->vector_width();
|
||||
sig_->incr_lref();
|
||||
more = 0;
|
||||
}
|
||||
|
||||
NetAssign_::NetAssign_(NetMemory*s)
|
||||
: sig_(0), mem_(s), bmux_(0), base_(0)
|
||||
{
|
||||
lwid_ = mem_->width();
|
||||
more = 0;
|
||||
}
|
||||
|
||||
NetAssign_::~NetAssign_()
|
||||
{
|
||||
if (sig_) {
|
||||
@@ -62,23 +55,23 @@ NetAssign_::~NetAssign_()
|
||||
}
|
||||
|
||||
assert( more == 0 );
|
||||
if (bmux_) delete bmux_;
|
||||
if (word_) delete word_;
|
||||
}
|
||||
|
||||
void NetAssign_::set_bmux(NetExpr*r)
|
||||
void NetAssign_::set_word(NetExpr*r)
|
||||
{
|
||||
assert(bmux_ == 0);
|
||||
bmux_ = r;
|
||||
assert(word_ == 0);
|
||||
word_ = r;
|
||||
}
|
||||
|
||||
NetExpr* NetAssign_::bmux()
|
||||
NetExpr* NetAssign_::word()
|
||||
{
|
||||
return bmux_;
|
||||
return word_;
|
||||
}
|
||||
|
||||
const NetExpr* NetAssign_::bmux() const
|
||||
const NetExpr* NetAssign_::word() const
|
||||
{
|
||||
return bmux_;
|
||||
return word_;
|
||||
}
|
||||
|
||||
const NetExpr* NetAssign_::get_base() const
|
||||
@@ -88,17 +81,13 @@ const NetExpr* NetAssign_::get_base() const
|
||||
|
||||
unsigned NetAssign_::lwidth() const
|
||||
{
|
||||
if (mem_) return lwid_;
|
||||
else if (bmux_) return 1;
|
||||
else return lwid_;
|
||||
return lwid_;
|
||||
}
|
||||
|
||||
perm_string NetAssign_::name() const
|
||||
{
|
||||
if (sig_) {
|
||||
return sig_->name();
|
||||
} else if (mem_) {
|
||||
return mem_->name();
|
||||
} else {
|
||||
return perm_string::literal("");
|
||||
}
|
||||
@@ -109,11 +98,6 @@ NetNet* NetAssign_::sig() const
|
||||
return sig_;
|
||||
}
|
||||
|
||||
NetMemory* NetAssign_::mem() const
|
||||
{
|
||||
return mem_;
|
||||
}
|
||||
|
||||
void NetAssign_::set_part(NetExpr*base, unsigned wid)
|
||||
{
|
||||
base_ = base;
|
||||
@@ -275,6 +259,12 @@ NetRelease::~NetRelease()
|
||||
|
||||
/*
|
||||
* $Log: net_assign.cc,v $
|
||||
* Revision 1.22 2007/01/16 05:44:15 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.21 2006/02/02 02:43:58 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
||||
+70
-64
@@ -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.50 2006/08/08 05:11:37 steve Exp $"
|
||||
#ident "$Id: net_design.cc,v 1.54 2007/06/05 04:18:09 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -32,6 +32,7 @@
|
||||
# include "netlist.h"
|
||||
# include "util.h"
|
||||
# include "compiler.h"
|
||||
# include "netmisc.h"
|
||||
# include <sstream>
|
||||
|
||||
Design:: Design()
|
||||
@@ -84,7 +85,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, root, NetScope::MODULE);
|
||||
root_scope_ = new NetScope(0, hname_t(root), NetScope::MODULE);
|
||||
/* This relies on the fact that the basename return value is
|
||||
permallocated. */
|
||||
root_scope_->set_module_name(root_scope_->basename());
|
||||
@@ -114,26 +115,27 @@ 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 hname_t&path) const
|
||||
NetScope* Design::find_scope(const std::list<hname_t>&path) const
|
||||
{
|
||||
if (path.peek_name(0) == 0)
|
||||
if (path.empty())
|
||||
return 0;
|
||||
|
||||
for (list<NetScope*>::const_iterator scope = root_scopes_.begin()
|
||||
; scope != root_scopes_.end(); scope++) {
|
||||
|
||||
NetScope*cur = *scope;
|
||||
if (strcmp(path.peek_name(0), cur->basename()) != 0)
|
||||
if (path.front() != cur->fullname())
|
||||
continue;
|
||||
|
||||
unsigned hidx = 1;
|
||||
while (cur) {
|
||||
const char*name = path.peek_name(hidx);
|
||||
if (name == 0)
|
||||
return cur;
|
||||
std::list<hname_t> tmp = path;
|
||||
tmp.pop_front();
|
||||
|
||||
cur = cur->child(name);
|
||||
hidx += 1;
|
||||
while (cur) {
|
||||
if (tmp.empty()) return cur;
|
||||
|
||||
cur = cur->child( tmp.front() );
|
||||
|
||||
tmp.pop_front();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -143,28 +145,34 @@ NetScope* Design::find_scope(const hname_t&path) const
|
||||
|
||||
/*
|
||||
* This is a relative lookup of a scope by name. The starting point is
|
||||
* 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.
|
||||
* 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.
|
||||
*/
|
||||
NetScope* Design::find_scope(NetScope*scope, const hname_t&path) const
|
||||
NetScope* Design::find_scope(NetScope*scope, const std::list<hname_t>&path) const
|
||||
{
|
||||
assert(scope);
|
||||
if (path.peek_name(0) == 0)
|
||||
if (path.empty())
|
||||
return scope;
|
||||
|
||||
for ( ; scope ; scope = scope->parent()) {
|
||||
unsigned hidx = 0;
|
||||
const char*key = path.peek_name(hidx);
|
||||
|
||||
std::list<hname_t> tmp = path;
|
||||
|
||||
NetScope*cur = scope;
|
||||
do {
|
||||
cur = cur->child(key);
|
||||
if (cur == 0) break;
|
||||
hidx += 1;
|
||||
key = path.peek_name(hidx);
|
||||
} while (key);
|
||||
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());
|
||||
|
||||
if (cur) return cur;
|
||||
}
|
||||
@@ -196,18 +204,19 @@ void NetScope::run_defparams(Design*des)
|
||||
}
|
||||
}
|
||||
|
||||
map<hname_t,NetExpr*>::const_iterator pp;
|
||||
map<pform_name_t,NetExpr*>::const_iterator pp;
|
||||
for (pp = defparams.begin() ; pp != defparams.end() ; pp ++ ) {
|
||||
NetExpr*val = (*pp).second;
|
||||
hname_t path = (*pp).first;
|
||||
pform_name_t path = (*pp).first;
|
||||
|
||||
char*tmp = path.remove_tail_name();
|
||||
perm_string perm_name = lex_strings.make(tmp);
|
||||
delete[]tmp;
|
||||
perm_string perm_name = peek_tail_name(path);
|
||||
path.pop_back();
|
||||
|
||||
list<hname_t> eval_path = eval_scope_path(des, this, path);
|
||||
|
||||
/* If there is no path on the name, then the targ_scope
|
||||
is the current scope. */
|
||||
NetScope*targ_scope = des->find_scope(this, path);
|
||||
NetScope*targ_scope = des->find_scope(this, eval_path);
|
||||
if (targ_scope == 0) {
|
||||
cerr << val->get_line() << ": warning: scope of " <<
|
||||
path << "." << perm_name << " not found." << endl;
|
||||
@@ -218,7 +227,7 @@ void NetScope::run_defparams(Design*des)
|
||||
if (! flag) {
|
||||
cerr << val->get_line() << ": warning: parameter "
|
||||
<< perm_name << " not found in "
|
||||
<< targ_scope->name() << "." << endl;
|
||||
<< scope_path(targ_scope) << "." << endl;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -425,68 +434,52 @@ 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, hname_t path)
|
||||
NetNet* Design::find_signal(NetScope*scope, pform_name_t path)
|
||||
{
|
||||
assert(scope);
|
||||
|
||||
char*key = path.remove_tail_name();
|
||||
if (path.peek_name(0))
|
||||
scope = find_scope(scope, path);
|
||||
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);
|
||||
}
|
||||
|
||||
while (scope) {
|
||||
if (NetNet*net = scope->find_signal(key)) {
|
||||
delete key;
|
||||
if (NetNet*net = scope->find_signal(key))
|
||||
return net;
|
||||
}
|
||||
|
||||
if (scope->type() == NetScope::MODULE)
|
||||
break;
|
||||
|
||||
scope = scope->parent();
|
||||
}
|
||||
|
||||
delete key;
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetFuncDef* Design::find_function(NetScope*scope, const hname_t&name)
|
||||
NetFuncDef* Design::find_function(NetScope*scope, const pform_name_t&name)
|
||||
{
|
||||
assert(scope);
|
||||
NetScope*func = find_scope(scope, name);
|
||||
|
||||
std::list<hname_t> eval_path = eval_scope_path(this, scope, name);
|
||||
NetScope*func = find_scope(scope, eval_path);
|
||||
if (func && (func->type() == NetScope::FUNC))
|
||||
return func->func_def();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetFuncDef* Design::find_function(const hname_t&key)
|
||||
NetScope* Design::find_task(NetScope*scope, const pform_name_t&name)
|
||||
{
|
||||
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);
|
||||
std::list<hname_t> eval_path = eval_scope_path(this, scope, name);
|
||||
NetScope*task = find_scope(scope, eval_path);
|
||||
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);
|
||||
@@ -562,6 +555,19 @@ 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.
|
||||
*
|
||||
|
||||
+6
-3
@@ -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.26 2004/10/04 01:10:54 steve Exp $"
|
||||
#ident "$Id: net_event.cc,v 1.27 2007/06/02 03:42:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -56,10 +56,10 @@ perm_string NetEvent::name() const
|
||||
return name_;
|
||||
}
|
||||
|
||||
string NetEvent::full_name() const
|
||||
NetScope* NetEvent::scope()
|
||||
{
|
||||
assert(scope_);
|
||||
return scope_->name() + "." + string(name_);
|
||||
return scope_;
|
||||
}
|
||||
|
||||
const NetScope* NetEvent::scope() const
|
||||
@@ -449,6 +449,9 @@ 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.
|
||||
*
|
||||
|
||||
+10
-4
@@ -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.8 2006/06/18 04:15:50 steve Exp $"
|
||||
#ident "$Id: net_func.cc,v 1.10 2007/06/02 03:42:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -95,14 +95,14 @@ bool PECallFunction::check_call_matches_definition_(Design*des, NetScope*dscope)
|
||||
|
||||
if (dscope->type() != NetScope::FUNC) {
|
||||
cerr << get_line() << ": error: Attempt to call scope "
|
||||
<< dscope->name() << " as a function." << endl;
|
||||
<< scope_path(dscope) << " as a function." << endl;
|
||||
des->errors += 1;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (parms_count != dscope->func_def()->port_count()) {
|
||||
cerr << get_line() << ": error: Function " << dscope->name()
|
||||
<< " expects " << (dscope->func_def()->port_count()-1)
|
||||
cerr << get_line() << ": error: Function " << scope_path(dscope)
|
||||
<< " expects " << (dscope->func_def()->port_count())
|
||||
<< " arguments, you passed " << parms_count << "."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
@@ -149,6 +149,12 @@ unsigned NetSysFunc::vector_width() const
|
||||
|
||||
/*
|
||||
* $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.
|
||||
*
|
||||
|
||||
+11
-5
@@ -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.19 2006/02/02 02:43:58 steve Exp $"
|
||||
#ident "$Id: net_link.cc,v 1.21 2007/06/02 03:42:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -304,14 +304,14 @@ const Link* Nexus::first_nlink() const
|
||||
return list_;
|
||||
}
|
||||
|
||||
void* Nexus::t_cookie() const
|
||||
ivl_nexus_t Nexus::t_cookie() const
|
||||
{
|
||||
return t_cookie_;
|
||||
}
|
||||
|
||||
void* Nexus::t_cookie(void*val)const
|
||||
ivl_nexus_t Nexus::t_cookie(ivl_nexus_t val)const
|
||||
{
|
||||
void*tmp = t_cookie_;
|
||||
ivl_nexus_t tmp = t_cookie_;
|
||||
t_cookie_ = val;
|
||||
return tmp;
|
||||
}
|
||||
@@ -391,7 +391,7 @@ const char* Nexus::name() const
|
||||
}
|
||||
assert(sig);
|
||||
ostringstream tmp;
|
||||
tmp << sig->scope()->name() << "." << sig->name();
|
||||
tmp << scope_path(sig->scope()) << "." << sig->name();
|
||||
if (sig->pin_count() > 1)
|
||||
tmp << "<" << pin << ">";
|
||||
|
||||
@@ -525,6 +525,12 @@ 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.20 2007/03/26 18:17:50 steve
|
||||
* Remove pretense of general use for t_cookie.
|
||||
*
|
||||
* Revision 1.19 2006/02/02 02:43:58 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
||||
+9
-9
@@ -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.15 2006/04/16 00:15:43 steve Exp $"
|
||||
#ident "$Id: net_nex_input.cc,v 1.16 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -78,12 +78,6 @@ 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.
|
||||
@@ -171,8 +165,8 @@ NexusSet* NetEUnary::nex_input()
|
||||
NexusSet* NetAssign_::nex_input()
|
||||
{
|
||||
NexusSet*result = new NexusSet;
|
||||
if (bmux_) {
|
||||
NexusSet*tmp = bmux_->nex_input();
|
||||
if (word_) {
|
||||
NexusSet*tmp = word_->nex_input();
|
||||
result->add(*tmp);
|
||||
delete tmp;
|
||||
}
|
||||
@@ -393,6 +387,12 @@ 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.
|
||||
*
|
||||
|
||||
+20
-1
@@ -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.12 2005/02/14 04:58:50 steve Exp $"
|
||||
#ident "$Id: net_nex_output.cc,v 1.14 2007/04/17 04:34:23 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -77,6 +77,10 @@ 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);
|
||||
}
|
||||
@@ -111,6 +115,15 @@ 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)
|
||||
@@ -119,6 +132,12 @@ 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.13 2007/04/05 01:53:52 steve
|
||||
* Probe of case statement inputs can skip nul statements.
|
||||
*
|
||||
* Revision 1.12 2005/02/14 04:58:50 steve
|
||||
* l-value input may be a vector.
|
||||
*
|
||||
|
||||
+21
-83
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: net_scope.cc,v 1.35 2005/11/27 05:56:20 steve Exp $"
|
||||
#ident "$Id: net_scope.cc,v 1.38 2007/06/02 03:42:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -35,10 +35,9 @@
|
||||
* in question.
|
||||
*/
|
||||
|
||||
NetScope::NetScope(NetScope*up, perm_string n, NetScope::TYPE t)
|
||||
NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t)
|
||||
: type_(t), up_(up), sib_(0), sub_(0)
|
||||
{
|
||||
memories_ = 0;
|
||||
signals_ = 0;
|
||||
events_ = 0;
|
||||
lcounter_ = 0;
|
||||
@@ -242,15 +241,7 @@ NetNet::Type NetScope::default_nettype() const
|
||||
|
||||
perm_string NetScope::basename() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
string NetScope::name() const
|
||||
{
|
||||
if (up_)
|
||||
return up_->name() + "." + string(name_);
|
||||
else
|
||||
return string(name_);
|
||||
return name_.peek_name();
|
||||
}
|
||||
|
||||
void NetScope::add_event(NetEvent*ev)
|
||||
@@ -337,81 +328,16 @@ NetNet* NetScope::find_signal(const char*key)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method searches for the signal within this scope. If the path
|
||||
* has hierarchy, I follow the child scopes until I get the base name,
|
||||
* and look for the key in the deepest scope.
|
||||
*/
|
||||
NetNet* NetScope::find_signal_in_child(const hname_t&path)
|
||||
{
|
||||
NetScope*cur = this;
|
||||
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));
|
||||
}
|
||||
|
||||
void NetScope::add_memory(NetMemory*mem)
|
||||
{
|
||||
if (memories_ == 0) {
|
||||
mem->snext_ = mem;
|
||||
mem->sprev_ = mem;
|
||||
} else {
|
||||
mem->snext_ = memories_->snext_;
|
||||
mem->sprev_ = memories_;
|
||||
mem->snext_->sprev_ = mem;
|
||||
mem->sprev_->snext_ = mem;
|
||||
}
|
||||
memories_ = mem;
|
||||
mem->scope_ = this;
|
||||
}
|
||||
|
||||
void NetScope::rem_memory(NetMemory*mem)
|
||||
{
|
||||
assert(mem->scope_ == this);
|
||||
if (memories_ == mem)
|
||||
memories_ = mem->sprev_;
|
||||
|
||||
if (memories_ == mem) {
|
||||
memories_ = 0;
|
||||
} else {
|
||||
mem->sprev_->snext_ = mem->snext_;
|
||||
mem->snext_->sprev_ = mem->sprev_;
|
||||
}
|
||||
mem->scope_ = 0;
|
||||
}
|
||||
|
||||
NetMemory* NetScope::find_memory(const string&key)
|
||||
{
|
||||
if (memories_ == 0)
|
||||
return 0;
|
||||
|
||||
NetMemory*cur = memories_;
|
||||
do {
|
||||
if (cur->name() == key.c_str())
|
||||
return cur;
|
||||
cur = cur->sprev_;
|
||||
} while (cur != memories_);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This method locates a child scope by name. The name is the simple
|
||||
* name of the child, no hierarchy is searched.
|
||||
*/
|
||||
NetScope* NetScope::child(const char*name)
|
||||
NetScope* NetScope::child(const hname_t&name)
|
||||
{
|
||||
if (sub_ == 0) return 0;
|
||||
|
||||
NetScope*cur = sub_;
|
||||
while (strcmp(cur->name_, name) != 0) {
|
||||
while (cur->name_ != name) {
|
||||
if (cur->sib_ == 0) return 0;
|
||||
cur = cur->sib_;
|
||||
}
|
||||
@@ -419,12 +345,12 @@ NetScope* NetScope::child(const char*name)
|
||||
return cur;
|
||||
}
|
||||
|
||||
const NetScope* NetScope::child(const char*name) const
|
||||
const NetScope* NetScope::child(const hname_t&name) const
|
||||
{
|
||||
if (sub_ == 0) return 0;
|
||||
|
||||
NetScope*cur = sub_;
|
||||
while (strcmp(cur->name_, name) != 0) {
|
||||
while (cur->name_ != name) {
|
||||
if (cur->sib_ == 0) return 0;
|
||||
cur = cur->sib_;
|
||||
}
|
||||
@@ -448,15 +374,27 @@ perm_string NetScope::local_symbol()
|
||||
res << "_s" << (lcounter_++);
|
||||
return lex_strings.make(res.str());
|
||||
}
|
||||
|
||||
#if 0
|
||||
string NetScope::local_hsymbol()
|
||||
{
|
||||
return string(name()) + "." + string(local_symbol());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* $Log: net_scope.cc,v $
|
||||
* Revision 1.38 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.37 2007/04/26 03:06:22 steve
|
||||
* Rework hname_t to use perm_strings.
|
||||
*
|
||||
* Revision 1.36 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.35 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
|
||||
+297
-277
@@ -17,18 +17,18 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netlist.cc,v 1.250 2006/11/10 04:54:26 steve Exp $"
|
||||
#ident "$Id: netlist.cc,v 1.258 2007/06/02 03:42:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
|
||||
# include <iostream>
|
||||
|
||||
# include <cassert>
|
||||
# include <typeinfo>
|
||||
# include "compiler.h"
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
|
||||
ostream& operator<< (ostream&o, NetNet::Type t)
|
||||
@@ -237,13 +237,23 @@ NetBus::~NetBus()
|
||||
{
|
||||
}
|
||||
|
||||
NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n, unsigned npins)
|
||||
: NetObj(s, n, npins)
|
||||
NetDelaySrc::NetDelaySrc(NetScope*s, perm_string n,
|
||||
unsigned npins, bool condit_src)
|
||||
: NetObj(s, n, npins + (condit_src?1:0))
|
||||
{
|
||||
condit_flag_ = false;
|
||||
posedge_ = false;
|
||||
negedge_ = false;
|
||||
for (unsigned idx = 0 ; idx < npins ; idx += 1) {
|
||||
pin(idx).set_name(perm_string::literal("I"), idx);
|
||||
pin(idx).set_dir(Link::INPUT);
|
||||
}
|
||||
|
||||
if (condit_src) {
|
||||
condit_flag_ = true;
|
||||
pin(npins).set_name(perm_string::literal("COND"), 0);
|
||||
pin(npins).set_dir(Link::INPUT);
|
||||
}
|
||||
}
|
||||
|
||||
NetDelaySrc::~NetDelaySrc()
|
||||
@@ -330,10 +340,67 @@ uint64_t NetDelaySrc::get_delay(unsigned idx) const
|
||||
return transition_delays_[idx];
|
||||
}
|
||||
|
||||
void NetDelaySrc::set_posedge()
|
||||
{
|
||||
posedge_ = true;
|
||||
}
|
||||
|
||||
void NetDelaySrc::set_negedge()
|
||||
{
|
||||
negedge_ = true;
|
||||
}
|
||||
|
||||
bool NetDelaySrc::is_posedge() const
|
||||
{
|
||||
return posedge_;
|
||||
}
|
||||
|
||||
bool NetDelaySrc::is_negedge() const
|
||||
{
|
||||
return negedge_;
|
||||
}
|
||||
|
||||
unsigned NetDelaySrc::src_count() const
|
||||
{
|
||||
if (condit_flag_)
|
||||
return pin_count() - 1;
|
||||
else
|
||||
return pin_count();
|
||||
}
|
||||
|
||||
Link& NetDelaySrc::src_pin(unsigned idx)
|
||||
{
|
||||
ivl_assert(*this, idx < src_count());
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
const Link& NetDelaySrc::src_pin(unsigned idx) const
|
||||
{
|
||||
ivl_assert(*this, idx < src_count());
|
||||
return pin(idx);
|
||||
}
|
||||
|
||||
bool NetDelaySrc::is_condit() const
|
||||
{
|
||||
return condit_flag_;
|
||||
}
|
||||
|
||||
Link& NetDelaySrc::condit_pin()
|
||||
{
|
||||
ivl_assert(*this, condit_flag_);
|
||||
return pin(pin_count()-1);
|
||||
}
|
||||
|
||||
const Link& NetDelaySrc::condit_pin() const
|
||||
{
|
||||
ivl_assert(*this, condit_flag_);
|
||||
return pin(pin_count()-1);
|
||||
}
|
||||
|
||||
NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
||||
: NetObj(s, n, 1), sig_next_(0), sig_prev_(0),
|
||||
type_(t), port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE),
|
||||
signed_(false), msb_(npins-1), lsb_(0),
|
||||
signed_(false), msb_(npins-1), lsb_(0), dimensions_(0), s0_(0), e0_(0),
|
||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
{
|
||||
assert(s);
|
||||
@@ -367,11 +434,12 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, unsigned npins)
|
||||
s->add_signal(this);
|
||||
}
|
||||
|
||||
NetNet::NetNet(NetScope*s, perm_string n, Type t, long ms, long ls)
|
||||
NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||
long ms, long ls)
|
||||
: NetObj(s, n, 1),
|
||||
sig_next_(0), sig_prev_(0), type_(t),
|
||||
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
|
||||
msb_(ms), lsb_(ls),
|
||||
msb_(ms), lsb_(ls), dimensions_(0), s0_(0), e0_(0),
|
||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
{
|
||||
assert(s);
|
||||
@@ -397,9 +465,59 @@ NetNet::NetNet(NetScope*s, perm_string n, Type t, long ms, long ls)
|
||||
break;
|
||||
}
|
||||
|
||||
pin(0).set_name(perm_string::literal("P"), 0);
|
||||
pin(0).set_dir(dir);
|
||||
pin(0).set_init(init_value);
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
pin(idx).set_name(perm_string::literal("P"), idx);
|
||||
pin(idx).set_dir(dir);
|
||||
pin(idx).set_init(init_value);
|
||||
}
|
||||
|
||||
s->add_signal(this);
|
||||
}
|
||||
|
||||
static unsigned calculate_count(long s, long e)
|
||||
{
|
||||
if (s >= e)
|
||||
return s - e + 1;
|
||||
else
|
||||
return e - s + 1;
|
||||
}
|
||||
|
||||
NetNet::NetNet(NetScope*s, perm_string n, Type t,
|
||||
long ms, long ls, long array_s, long array_e)
|
||||
: NetObj(s, n, calculate_count(array_s, array_e)),
|
||||
sig_next_(0), sig_prev_(0), type_(t),
|
||||
port_type_(NOT_A_PORT), data_type_(IVL_VT_NO_TYPE), signed_(false),
|
||||
msb_(ms), lsb_(ls), dimensions_(1), s0_(array_s), e0_(array_e),
|
||||
local_flag_(false), eref_count_(0), lref_count_(0)
|
||||
{
|
||||
assert(s);
|
||||
|
||||
verinum::V init_value = verinum::Vz;
|
||||
Link::DIR dir = Link::PASSIVE;
|
||||
|
||||
switch (t) {
|
||||
case REG:
|
||||
case IMPLICIT_REG:
|
||||
init_value = verinum::Vx;
|
||||
dir = Link::OUTPUT;
|
||||
break;
|
||||
case SUPPLY0:
|
||||
init_value = verinum::V0;
|
||||
dir = Link::OUTPUT;
|
||||
break;
|
||||
case SUPPLY1:
|
||||
init_value = verinum::V1;
|
||||
dir = Link::OUTPUT;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < pin_count() ; idx += 1) {
|
||||
pin(idx).set_name(perm_string::literal("P"), idx);
|
||||
pin(idx).set_dir(dir);
|
||||
pin(idx).set_init(init_value);
|
||||
}
|
||||
|
||||
s->add_signal(this);
|
||||
}
|
||||
@@ -533,6 +651,41 @@ unsigned NetNet::sb_to_idx(long sb) const
|
||||
return lsb_ - sb;
|
||||
}
|
||||
|
||||
unsigned NetNet::array_dimensions() const
|
||||
{
|
||||
return dimensions_;
|
||||
}
|
||||
|
||||
long NetNet::array_first() const
|
||||
{
|
||||
if (s0_ < e0_)
|
||||
return s0_;
|
||||
else
|
||||
return e0_;
|
||||
}
|
||||
|
||||
unsigned NetNet::array_count() const
|
||||
{
|
||||
return calculate_count(s0_, e0_);
|
||||
}
|
||||
|
||||
bool NetNet::array_index_is_valid(long sb) const
|
||||
{
|
||||
if (sb < s0_ && sb < e0_)
|
||||
return false;
|
||||
if (sb > e0_ && sb > s0_)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned NetNet::array_index_to_address(long sb) const
|
||||
{
|
||||
if (s0_ <= e0_)
|
||||
return sb - s0_;
|
||||
else
|
||||
return sb - e0_;
|
||||
}
|
||||
|
||||
void NetNet::incr_eref()
|
||||
{
|
||||
eref_count_ += 1;
|
||||
@@ -973,6 +1126,55 @@ const Link& NetAddSub::pin_Result() const
|
||||
return pin(8);
|
||||
}
|
||||
|
||||
NetArrayDq::NetArrayDq(NetScope*s, perm_string n, NetNet*mem, unsigned awid)
|
||||
: NetNode(s, n, 2),
|
||||
mem_(mem), awidth_(awid)
|
||||
{
|
||||
pin(0).set_dir(Link::OUTPUT);
|
||||
pin(0).set_name(perm_string::literal("Result"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("Address"), 0);
|
||||
}
|
||||
|
||||
NetArrayDq::~NetArrayDq()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned NetArrayDq::width() const
|
||||
{
|
||||
return mem_->vector_width();
|
||||
}
|
||||
|
||||
unsigned NetArrayDq::awidth() const
|
||||
{
|
||||
return awidth_;
|
||||
}
|
||||
|
||||
const NetNet* NetArrayDq::mem() const
|
||||
{
|
||||
return mem_;
|
||||
}
|
||||
|
||||
Link& NetArrayDq::pin_Result()
|
||||
{
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
Link& NetArrayDq::pin_Address()
|
||||
{
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
const Link& NetArrayDq::pin_Result() const
|
||||
{
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
const Link& NetArrayDq::pin_Address() const
|
||||
{
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
/*
|
||||
* The pinout for the NetCLShift is:
|
||||
* 0 -- Result
|
||||
@@ -1428,190 +1630,6 @@ const Link& NetMux::pin_Data(unsigned s) const
|
||||
return pin(2+s);
|
||||
}
|
||||
|
||||
|
||||
NetRamDq::NetRamDq(NetScope*s, perm_string n, NetMemory*mem, unsigned awid)
|
||||
: NetNode(s, n, 6),
|
||||
mem_(mem), awidth_(awid)
|
||||
{
|
||||
pin(0).set_dir(Link::INPUT);
|
||||
pin(0).set_name(perm_string::literal("InClock"), 0);
|
||||
pin(1).set_dir(Link::INPUT);
|
||||
pin(1).set_name(perm_string::literal("OutClock"), 0);
|
||||
pin(2).set_dir(Link::INPUT);
|
||||
pin(2).set_name(perm_string::literal("WE"), 0);
|
||||
pin(3).set_dir(Link::INPUT);
|
||||
pin(3).set_name(perm_string::literal("Address"), 0);
|
||||
pin(4).set_dir(Link::INPUT);
|
||||
pin(4).set_name(perm_string::literal("Data"), 0);
|
||||
pin(5).set_dir(Link::OUTPUT);
|
||||
pin(5).set_name(perm_string::literal("Q"), 0);
|
||||
|
||||
next_ = mem_->ram_list_;
|
||||
mem_->ram_list_ = this;
|
||||
}
|
||||
|
||||
NetRamDq::~NetRamDq()
|
||||
{
|
||||
if (mem_->ram_list_ == this) {
|
||||
mem_->ram_list_ = next_;
|
||||
|
||||
} else {
|
||||
NetRamDq*cur = mem_->ram_list_;
|
||||
while (cur->next_ != this) {
|
||||
assert(cur->next_);
|
||||
cur = cur->next_;
|
||||
}
|
||||
assert(cur->next_ == this);
|
||||
cur->next_ = next_;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned NetRamDq::width() const
|
||||
{
|
||||
return mem_->width();
|
||||
}
|
||||
|
||||
unsigned NetRamDq::awidth() const
|
||||
{
|
||||
return awidth_;
|
||||
}
|
||||
|
||||
unsigned NetRamDq::size() const
|
||||
{
|
||||
return mem_->count();
|
||||
}
|
||||
|
||||
const NetMemory* NetRamDq::mem() const
|
||||
{
|
||||
return mem_;
|
||||
}
|
||||
|
||||
unsigned NetRamDq::count_partners() const
|
||||
{
|
||||
unsigned count = 0;
|
||||
for (NetRamDq*cur = mem_->ram_list_ ; cur ; cur = cur->next_)
|
||||
count += 1;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void NetRamDq::absorb_partners()
|
||||
{
|
||||
NetRamDq*cur, *tmp;
|
||||
for (cur = mem_->ram_list_, tmp = 0
|
||||
; cur||tmp ; cur = cur? cur->next_ : tmp) {
|
||||
tmp = 0;
|
||||
if (cur == this) continue;
|
||||
|
||||
bool ok_flag = true;
|
||||
ok_flag &= pin_Address().is_linked(cur->pin_Address());
|
||||
|
||||
if (!ok_flag) continue;
|
||||
|
||||
if (pin_InClock().is_linked()
|
||||
&& cur->pin_InClock().is_linked()
|
||||
&& ! pin_InClock().is_linked(cur->pin_InClock()))
|
||||
continue;
|
||||
|
||||
if (pin_OutClock().is_linked()
|
||||
&& cur->pin_OutClock().is_linked()
|
||||
&& ! pin_OutClock().is_linked(cur->pin_OutClock()))
|
||||
continue;
|
||||
|
||||
if (pin_WE().is_linked()
|
||||
&& cur->pin_WE().is_linked()
|
||||
&& ! pin_WE().is_linked(cur->pin_WE()))
|
||||
continue;
|
||||
|
||||
if (pin_Data().is_linked() && cur->pin_Data().is_linked()) {
|
||||
ok_flag &= pin_Data().is_linked(cur->pin_Data());
|
||||
}
|
||||
|
||||
if (! ok_flag) continue;
|
||||
|
||||
if (pin_Q().is_linked() && cur->pin_Q().is_linked()) {
|
||||
|
||||
ok_flag &= pin_Q().is_linked(cur->pin_Q());
|
||||
}
|
||||
|
||||
if (! ok_flag) continue;
|
||||
|
||||
// I see no other reason to reject cur, so link up all
|
||||
// my pins and delete it.
|
||||
connect(pin_InClock(), cur->pin_InClock());
|
||||
connect(pin_OutClock(), cur->pin_OutClock());
|
||||
connect(pin_WE(), cur->pin_WE());
|
||||
|
||||
connect(pin_Address(), cur->pin_Address());
|
||||
connect(pin_Data(), cur->pin_Data());
|
||||
connect(pin_Q(), cur->pin_Q());
|
||||
|
||||
tmp = cur->next_;
|
||||
delete cur;
|
||||
cur = 0;
|
||||
}
|
||||
}
|
||||
|
||||
Link& NetRamDq::pin_InClock()
|
||||
{
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
const Link& NetRamDq::pin_InClock() const
|
||||
{
|
||||
return pin(0);
|
||||
}
|
||||
|
||||
Link& NetRamDq::pin_OutClock()
|
||||
{
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
const Link& NetRamDq::pin_OutClock() const
|
||||
{
|
||||
return pin(1);
|
||||
}
|
||||
|
||||
Link& NetRamDq::pin_WE()
|
||||
{
|
||||
return pin(2);
|
||||
}
|
||||
|
||||
const Link& NetRamDq::pin_WE() const
|
||||
{
|
||||
return pin(2);
|
||||
}
|
||||
|
||||
Link& NetRamDq::pin_Address()
|
||||
{
|
||||
return pin(3);
|
||||
}
|
||||
|
||||
const Link& NetRamDq::pin_Address() const
|
||||
{
|
||||
return pin(3);
|
||||
}
|
||||
|
||||
Link& NetRamDq::pin_Data()
|
||||
{
|
||||
return pin(4);
|
||||
}
|
||||
|
||||
const Link& NetRamDq::pin_Data() const
|
||||
{
|
||||
return pin(4);
|
||||
}
|
||||
|
||||
Link& NetRamDq::pin_Q()
|
||||
{
|
||||
return pin(5);
|
||||
}
|
||||
|
||||
const Link& NetRamDq::pin_Q() const
|
||||
{
|
||||
return pin(5);
|
||||
}
|
||||
|
||||
NetSignExtend::NetSignExtend(NetScope*s, perm_string n, unsigned w)
|
||||
: NetNode(s, n, 2), width_(w)
|
||||
{
|
||||
@@ -1752,11 +1770,16 @@ NetFuncDef::NetFuncDef(NetScope*s, NetNet*result, const svector<NetNet*>&po)
|
||||
NetFuncDef::~NetFuncDef()
|
||||
{
|
||||
}
|
||||
|
||||
#if 0
|
||||
const string NetFuncDef::name() const
|
||||
{
|
||||
return scope_->name();
|
||||
}
|
||||
#endif
|
||||
const NetScope* NetFuncDef::scope() const
|
||||
{
|
||||
return scope_;
|
||||
}
|
||||
|
||||
void NetFuncDef::set_proc(NetProc*st)
|
||||
{
|
||||
@@ -1832,12 +1855,12 @@ NetEUFunc::~NetEUFunc()
|
||||
for (unsigned idx = 0 ; idx < parms_.count() ; idx += 1)
|
||||
delete parms_[idx];
|
||||
}
|
||||
|
||||
#if 0
|
||||
const string NetEUFunc::name() const
|
||||
{
|
||||
return func_->name();
|
||||
}
|
||||
|
||||
#endif
|
||||
const NetESignal*NetEUFunc::result_sig() const
|
||||
{
|
||||
return result_sig_;
|
||||
@@ -1875,12 +1898,12 @@ NetUTask::NetUTask(NetScope*def)
|
||||
NetUTask::~NetUTask()
|
||||
{
|
||||
}
|
||||
|
||||
#if 0
|
||||
const string NetUTask::name() const
|
||||
{
|
||||
return task_->name();
|
||||
}
|
||||
|
||||
#endif
|
||||
const NetScope* NetUTask::task() const
|
||||
{
|
||||
return task_;
|
||||
@@ -2027,68 +2050,6 @@ const NetScope* NetEConstParam::scope() const
|
||||
return scope_;
|
||||
}
|
||||
|
||||
|
||||
NetEMemory::NetEMemory(NetMemory*m, NetExpr*i)
|
||||
: NetExpr(m->width()), mem_(m), idx_(i)
|
||||
{
|
||||
}
|
||||
|
||||
NetEMemory::~NetEMemory()
|
||||
{
|
||||
}
|
||||
|
||||
perm_string NetEMemory::name() const
|
||||
{
|
||||
return mem_->name();
|
||||
}
|
||||
|
||||
const NetExpr* NetEMemory::index() const
|
||||
{
|
||||
return idx_;
|
||||
}
|
||||
|
||||
NetMemory::NetMemory(NetScope*sc, perm_string n, long w, long s, long e)
|
||||
: width_(w), idxh_(s), idxl_(e), ram_list_(0), scope_(sc)
|
||||
{
|
||||
name_ = n;
|
||||
scope_->add_memory(this);
|
||||
}
|
||||
|
||||
NetMemory::~NetMemory()
|
||||
{
|
||||
assert(scope_);
|
||||
scope_->rem_memory(this);
|
||||
}
|
||||
|
||||
unsigned NetMemory::count() const
|
||||
{
|
||||
if (idxh_ < idxl_)
|
||||
return idxl_ - idxh_ + 1;
|
||||
else
|
||||
return idxh_ - idxl_ + 1;
|
||||
}
|
||||
|
||||
perm_string NetMemory::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
|
||||
long NetMemory::index_to_address(long idx) const
|
||||
{
|
||||
if (idxh_ < idxl_)
|
||||
return idx - idxh_;
|
||||
else
|
||||
return idx - idxl_;
|
||||
}
|
||||
|
||||
|
||||
|
||||
NetEMemory* NetEMemory::dup_expr() const
|
||||
{
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
NetEEvent::NetEEvent(NetEvent*e)
|
||||
: event_(e)
|
||||
{
|
||||
@@ -2119,25 +2080,20 @@ const NetScope* NetEScope::scope() const
|
||||
}
|
||||
|
||||
NetESignal::NetESignal(NetNet*n)
|
||||
: NetExpr(n->vector_width()), net_(n)
|
||||
: NetExpr(n->vector_width()), net_(n), word_(0)
|
||||
{
|
||||
net_->incr_eref();
|
||||
set_line(*n);
|
||||
cast_signed(net_->get_signed());
|
||||
}
|
||||
|
||||
#if 0
|
||||
NetESignal::NetESignal(NetNet*n, unsigned m, unsigned l)
|
||||
: NetExpr(m - l + 1), net_(n)
|
||||
NetESignal::NetESignal(NetNet*n, NetExpr*w)
|
||||
: NetExpr(n->vector_width()), net_(n), word_(w)
|
||||
{
|
||||
assert(m >= l);
|
||||
msi_ = m;
|
||||
lsi_ = l;
|
||||
net_->incr_eref();
|
||||
set_line(*n);
|
||||
cast_signed(net_->get_signed());
|
||||
}
|
||||
#endif
|
||||
|
||||
NetESignal::~NetESignal()
|
||||
{
|
||||
@@ -2149,18 +2105,22 @@ perm_string NetESignal::name() const
|
||||
return net_->name();
|
||||
}
|
||||
|
||||
unsigned NetESignal::bit_count() const
|
||||
const NetExpr* NetESignal::word_index() const
|
||||
{
|
||||
return word_;
|
||||
}
|
||||
|
||||
unsigned NetESignal::vector_width() const
|
||||
{
|
||||
return net_->vector_width();
|
||||
}
|
||||
|
||||
Link& NetESignal::bit(unsigned idx)
|
||||
const NetNet* NetESignal::sig() const
|
||||
{
|
||||
assert(idx <= 0);
|
||||
return net_->pin(idx);
|
||||
return net_;
|
||||
}
|
||||
|
||||
const NetNet* NetESignal::sig() const
|
||||
NetNet* NetESignal::sig()
|
||||
{
|
||||
return net_;
|
||||
}
|
||||
@@ -2219,6 +2179,19 @@ const NetExpr* NetETernary::false_expr() const
|
||||
return false_val_;
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetETernary::expr_type() const
|
||||
{
|
||||
ivl_variable_type_t tru = true_val_->expr_type();
|
||||
ivl_variable_type_t fal = false_val_->expr_type();
|
||||
if (tru == IVL_VT_LOGIC && fal == IVL_VT_BOOL)
|
||||
return IVL_VT_LOGIC;
|
||||
if (tru == IVL_VT_BOOL && fal == IVL_VT_LOGIC)
|
||||
return IVL_VT_LOGIC;
|
||||
|
||||
ivl_assert(*this, tru == fal);
|
||||
return tru;
|
||||
}
|
||||
|
||||
NetEUnary::NetEUnary(char op, NetExpr*ex)
|
||||
: NetExpr(ex->expr_width()), op_(op), expr_(ex)
|
||||
{
|
||||
@@ -2242,6 +2215,11 @@ NetEUnary::~NetEUnary()
|
||||
delete expr_;
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetEUnary::expr_type() const
|
||||
{
|
||||
return expr_->expr_type();
|
||||
}
|
||||
|
||||
NetEUBits::NetEUBits(char op, NetExpr*ex)
|
||||
: NetEUnary(op, ex)
|
||||
{
|
||||
@@ -2251,6 +2229,11 @@ NetEUBits::~NetEUBits()
|
||||
{
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetEUBits::expr_type() const
|
||||
{
|
||||
return expr_->expr_type();
|
||||
}
|
||||
|
||||
NetEUReduce::NetEUReduce(char op, NetExpr*ex)
|
||||
: NetEUnary(op, ex)
|
||||
{
|
||||
@@ -2261,6 +2244,11 @@ NetEUReduce::~NetEUReduce()
|
||||
{
|
||||
}
|
||||
|
||||
ivl_variable_type_t NetEUReduce::expr_type() const
|
||||
{
|
||||
return expr_->expr_type();
|
||||
}
|
||||
|
||||
NetLogic::NetLogic(NetScope*s, perm_string n, unsigned pins,
|
||||
TYPE t, unsigned wid)
|
||||
: NetNode(s, n, pins), type_(t), width_(wid)
|
||||
@@ -2303,8 +2291,8 @@ unsigned NetUReduce::width() const
|
||||
return width_;
|
||||
}
|
||||
|
||||
NetTaskDef::NetTaskDef(const string&n, const svector<NetNet*>&po)
|
||||
: name_(n), proc_(0), ports_(po)
|
||||
NetTaskDef::NetTaskDef(NetScope*n, const svector<NetNet*>&po)
|
||||
: scope_(n), proc_(0), ports_(po)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -2329,11 +2317,16 @@ NetNet* NetTaskDef::port(unsigned idx)
|
||||
assert(idx < ports_.count());
|
||||
return ports_[idx];
|
||||
}
|
||||
|
||||
#if 0
|
||||
const string& NetTaskDef::name() const
|
||||
{
|
||||
return name_;
|
||||
}
|
||||
#endif
|
||||
const NetScope* NetTaskDef::scope() const
|
||||
{
|
||||
return scope_;
|
||||
}
|
||||
|
||||
const NetProc*NetTaskDef::proc() const
|
||||
{
|
||||
@@ -2342,6 +2335,33 @@ const NetProc*NetTaskDef::proc() const
|
||||
|
||||
/*
|
||||
* $Log: netlist.cc,v $
|
||||
* Revision 1.258 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.257 2007/04/02 01:12:34 steve
|
||||
* Seperate arrayness from word count
|
||||
*
|
||||
* Revision 1.256 2007/03/02 06:13:22 steve
|
||||
* Add support for edge sensitive spec paths.
|
||||
*
|
||||
* Revision 1.255 2007/03/01 06:19:38 steve
|
||||
* Add support for conditional specify delay paths.
|
||||
*
|
||||
* Revision 1.254 2007/02/20 05:58:36 steve
|
||||
* Handle unary minus of real valued expressions.
|
||||
*
|
||||
* Revision 1.253 2007/02/14 05:59:46 steve
|
||||
* Handle type of ternary expressions properly.
|
||||
*
|
||||
* Revision 1.252 2007/01/19 04:25:37 steve
|
||||
* Fix missing passive setting for array word pins.
|
||||
*
|
||||
* Revision 1.251 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.250 2006/11/10 04:54:26 steve
|
||||
* Add test_width methods for PETernary and PEString.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netlist.h,v 1.365 2006/11/04 06:19:25 steve Exp $"
|
||||
#ident "$Id: netlist.h,v 1.380 2007/06/02 03:42:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -32,8 +32,9 @@
|
||||
# include <map>
|
||||
# include <list>
|
||||
# include <vector>
|
||||
# include <stdint.h>
|
||||
# include "ivl_target.h"
|
||||
# include "pform_types.h"
|
||||
# include "config.h"
|
||||
# include "verinum.h"
|
||||
# include "verireal.h"
|
||||
# include "StringHeap.h"
|
||||
@@ -275,8 +276,8 @@ class Nexus {
|
||||
the value that has been driven. */
|
||||
verinum::V driven_value() const;
|
||||
|
||||
void* t_cookie() const;
|
||||
void* t_cookie(void*) const;
|
||||
ivl_nexus_t t_cookie() const;
|
||||
ivl_nexus_t t_cookie(ivl_nexus_t) const;
|
||||
|
||||
private:
|
||||
Link*list_;
|
||||
@@ -284,7 +285,7 @@ class Nexus {
|
||||
void relink(Link*);
|
||||
|
||||
mutable char* name_; /* Cache the calculated name for the Nexus. */
|
||||
mutable void* t_cookie_;
|
||||
mutable ivl_nexus_t t_cookie_;
|
||||
|
||||
enum VALUE { NO_GUESS, V0, V1, Vx, Vz, VAR };
|
||||
mutable VALUE driven_;
|
||||
@@ -379,7 +380,8 @@ class NetNode : public NetObj {
|
||||
class NetDelaySrc : public NetObj {
|
||||
|
||||
public:
|
||||
explicit NetDelaySrc(NetScope*s, perm_string n, unsigned npins);
|
||||
explicit NetDelaySrc(NetScope*s, perm_string n,
|
||||
unsigned nsrc, bool condit_src);
|
||||
~NetDelaySrc();
|
||||
|
||||
// These functions set the delays from the values in the
|
||||
@@ -401,10 +403,26 @@ class NetDelaySrc : public NetObj {
|
||||
|
||||
uint64_t get_delay(unsigned pe) const;
|
||||
|
||||
void set_posedge();
|
||||
void set_negedge();
|
||||
bool is_posedge() const;
|
||||
bool is_negedge() const;
|
||||
|
||||
unsigned src_count() const;
|
||||
Link&src_pin(unsigned);
|
||||
const Link&src_pin(unsigned) const;
|
||||
|
||||
bool is_condit() const;
|
||||
Link&condit_pin();
|
||||
const Link&condit_pin() const;
|
||||
|
||||
void dump(ostream&, unsigned ind) const;
|
||||
|
||||
private:
|
||||
uint64_t transition_delays_[12];
|
||||
bool condit_flag_;
|
||||
bool posedge_;
|
||||
bool negedge_;
|
||||
|
||||
private: // Not implemented
|
||||
NetDelaySrc(const NetDelaySrc&);
|
||||
@@ -447,7 +465,14 @@ class NetNet : public NetObj {
|
||||
// that passed through.
|
||||
explicit NetNet(NetScope*s, perm_string n, Type t, unsigned width =1);
|
||||
|
||||
explicit NetNet(NetScope*s, perm_string n, Type t, long ms, long ls);
|
||||
// This form supports an array of vectors. The [ms:ls] define
|
||||
// the base vector, and the [s0:e0] define the array
|
||||
// dimensions. If s0==e0, then this is not an array after
|
||||
// all.
|
||||
explicit NetNet(NetScope*s, perm_string n, Type t,
|
||||
long ms, long ls);
|
||||
explicit NetNet(NetScope*s, perm_string n, Type t,
|
||||
long ms, long ls, long s0, long e0);
|
||||
|
||||
virtual ~NetNet();
|
||||
|
||||
@@ -488,6 +513,21 @@ class NetNet : public NetObj {
|
||||
the pin# from the index. */
|
||||
bool sb_is_valid(long sb) const;
|
||||
|
||||
/* This method returns 0 for scalers and vectors, and greater
|
||||
for arrays. The value is the number of array
|
||||
indices. (Currently only one array index is supported.) */
|
||||
unsigned array_dimensions() const;
|
||||
long array_first() const;
|
||||
|
||||
// This is the number of array elements.
|
||||
unsigned array_count() const;
|
||||
|
||||
// This method returns a 0 based address of an array entry as
|
||||
// indexed by idx. The Verilog source may give index ranges
|
||||
// that are not zero based.
|
||||
bool array_index_is_valid(long idx) const;
|
||||
unsigned array_index_to_address(long idx) const;
|
||||
|
||||
bool local_flag() const { return local_flag_; }
|
||||
void local_flag(bool f) { local_flag_ = f; }
|
||||
|
||||
@@ -524,6 +564,8 @@ class NetNet : public NetObj {
|
||||
bool isint_; // original type of integer
|
||||
|
||||
long msb_, lsb_;
|
||||
const unsigned dimensions_;
|
||||
long s0_, e0_;
|
||||
|
||||
bool local_flag_;
|
||||
unsigned eref_count_;
|
||||
@@ -571,6 +613,37 @@ class NetAddSub : public NetNode {
|
||||
unsigned width_;
|
||||
};
|
||||
|
||||
/*
|
||||
* The NetArrayDq node represents an array dereference. The NetNet
|
||||
* that this object refers to is an array, and the Address pin selects
|
||||
* which word of the array to place on the Result.
|
||||
*/
|
||||
class NetArrayDq : public NetNode {
|
||||
|
||||
public:
|
||||
NetArrayDq(NetScope*s, perm_string name, NetNet*mem, unsigned awid);
|
||||
~NetArrayDq();
|
||||
|
||||
unsigned width() const;
|
||||
unsigned awidth() const;
|
||||
unsigned size() const;
|
||||
const NetNet*mem() const;
|
||||
|
||||
Link& pin_Address();
|
||||
Link& pin_Result();
|
||||
|
||||
const Link& pin_Address() const;
|
||||
const Link& pin_Result() const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
private:
|
||||
NetNet*mem_;
|
||||
unsigned awidth_;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* This type represents the LPM_CLSHIFT device.
|
||||
*/
|
||||
@@ -819,62 +892,6 @@ class NetFF : public NetNode {
|
||||
verinum sset_value_;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This class represents the declared memory object. The parser
|
||||
* creates one of these for each declared memory in the elaborated
|
||||
* design. A reference to one of these is handled by the NetEMemory
|
||||
* object, which is derived from NetExpr. This is not a node because
|
||||
* memory objects can only be accessed by behavioral code.
|
||||
*/
|
||||
class NetMemory {
|
||||
|
||||
public:
|
||||
NetMemory(NetScope*sc, perm_string n, long w, long s, long e);
|
||||
~NetMemory();
|
||||
|
||||
// This is the BASE name of the memory object. It does not
|
||||
// include scope name, get that from the scope itself.
|
||||
perm_string name() const;
|
||||
|
||||
// This is the width (in bits) of a single memory position.
|
||||
unsigned width() const { return width_; }
|
||||
|
||||
// This is the number of dimensions for the memory. A baseline
|
||||
// verilog memory has always 1 dimension, but N-dimensional
|
||||
// arrays have N.
|
||||
unsigned dimensions() const { return 1; }
|
||||
|
||||
const NetScope*scope() const { return scope_; };
|
||||
|
||||
// This is the number of memory positions.
|
||||
unsigned count() const;
|
||||
|
||||
// This method returns a 0 based address of a memory entry as
|
||||
// indexed by idx. The Verilog source may give index ranges
|
||||
// that are not zero based.
|
||||
long index_to_address(long idx) const;
|
||||
|
||||
void dump(ostream&o, unsigned lm) const;
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
unsigned width_;
|
||||
long idxh_;
|
||||
long idxl_;
|
||||
|
||||
friend class NetRamDq;
|
||||
NetRamDq* ram_list_;
|
||||
|
||||
friend class NetScope;
|
||||
NetMemory*snext_, *sprev_;
|
||||
NetScope*scope_;
|
||||
|
||||
private: // not implemented
|
||||
NetMemory(const NetMemory&);
|
||||
NetMemory& operator= (const NetMemory&);
|
||||
};
|
||||
|
||||
/*
|
||||
* This class implements a basic LPM_MULT combinational multiplier. It
|
||||
* is used as a structural representation of the * operator. The
|
||||
@@ -965,57 +982,6 @@ class NetMux : public NetNode {
|
||||
unsigned swidth_;
|
||||
};
|
||||
|
||||
/*
|
||||
* This device represents an LPM_RAM_DQ device. The actual content is
|
||||
* represented by a NetMemory object allocated elsewhere, but that
|
||||
* object fixes the width and size of the device. The pin count of the
|
||||
* address input is given in the constructor.
|
||||
*/
|
||||
class NetRamDq : public NetNode {
|
||||
|
||||
public:
|
||||
NetRamDq(NetScope*s, perm_string name, NetMemory*mem, unsigned awid);
|
||||
~NetRamDq();
|
||||
|
||||
unsigned width() const;
|
||||
unsigned awidth() const;
|
||||
unsigned size() const;
|
||||
const NetMemory*mem() const;
|
||||
|
||||
Link& pin_InClock();
|
||||
Link& pin_OutClock();
|
||||
Link& pin_WE();
|
||||
|
||||
Link& pin_Address();
|
||||
Link& pin_Data();
|
||||
Link& pin_Q();
|
||||
|
||||
const Link& pin_InClock() const;
|
||||
const Link& pin_OutClock() const;
|
||||
const Link& pin_WE() const;
|
||||
|
||||
const Link& pin_Address() const;
|
||||
const Link& pin_Data() const;
|
||||
const Link& pin_Q() const;
|
||||
|
||||
virtual void dump_node(ostream&, unsigned ind) const;
|
||||
virtual bool emit_node(struct target_t*) const;
|
||||
|
||||
// Use this method to absorb other NetRamDq objects that are
|
||||
// connected to the same memory, and have compatible pin
|
||||
// connections.
|
||||
void absorb_partners();
|
||||
|
||||
// Use this method to count the partners (including myself)
|
||||
// that are ports to the attached memory.
|
||||
unsigned count_partners() const;
|
||||
|
||||
private:
|
||||
NetMemory*mem_;
|
||||
NetRamDq*next_;
|
||||
unsigned awidth_;
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* The NetReplicate node takes a vector input and makes it into a larger
|
||||
@@ -1154,7 +1120,10 @@ class NetExpr : public LineInfo {
|
||||
// equivalent expression that is reduced as far as compile
|
||||
// time knows how. Essentially, this is designed to fold
|
||||
// constants.
|
||||
virtual NetExpr*eval_tree();
|
||||
//
|
||||
// The prune_to_width is the maximum width that the result
|
||||
// should be. If it is -1, then do not prune the result.
|
||||
virtual NetExpr*eval_tree(int prune_to_width = -1);
|
||||
|
||||
// Make a duplicate of myself, and subexpressions if I have
|
||||
// any. This is a deep copy operation.
|
||||
@@ -1565,7 +1534,7 @@ class NetUReduce : public NetNode {
|
||||
* N -- (1x)
|
||||
*
|
||||
* It also takes one of the following glob letters to represent more
|
||||
* then one item.
|
||||
* than one item.
|
||||
*
|
||||
* p -- 01, 0x or x1 // check this with the lexer
|
||||
* n -- 10, 1x or x0 // check this with the lexer
|
||||
@@ -1578,7 +1547,7 @@ class NetUReduce : public NetNode {
|
||||
* SEQUENTIAL
|
||||
* These objects have a single bit of memory. The logic table includes
|
||||
* an entry for the current value, and allows edges on the inputs. In
|
||||
* canonical form, inly then entries that generate 0, 1 or - (no change)
|
||||
* canonical form, only the entries that generate 0, 1 or - (no change)
|
||||
* are listed.
|
||||
*
|
||||
* COMBINATIONAL
|
||||
@@ -1710,20 +1679,18 @@ class NetAssign_ {
|
||||
|
||||
public:
|
||||
NetAssign_(NetNet*sig);
|
||||
NetAssign_(NetMemory*mem);
|
||||
~NetAssign_();
|
||||
|
||||
// If this expression exists, then only a single bit is to be
|
||||
// set from the rval, and the value of this expression selects
|
||||
// the pin that gets the value.
|
||||
NetExpr*bmux();
|
||||
const NetExpr*bmux() const;
|
||||
// If this expression exists, then it is used to select a word
|
||||
// from an array/memory.
|
||||
NetExpr*word();
|
||||
const NetExpr*word() const;
|
||||
|
||||
// Get the base index of the part select, or 0 if there is no
|
||||
// part select.
|
||||
const NetExpr* get_base() const;
|
||||
|
||||
void set_bmux(NetExpr*);
|
||||
void set_word(NetExpr*);
|
||||
void set_part(NetExpr* loff, unsigned wid);
|
||||
|
||||
// Get the width of the r-value that this node expects. This
|
||||
@@ -1735,7 +1702,6 @@ class NetAssign_ {
|
||||
perm_string name() const;
|
||||
|
||||
NetNet* sig() const;
|
||||
NetMemory*mem() const;
|
||||
|
||||
// Mark that the synthesizer has worked with this l-value, so
|
||||
// when it is released, the l-value signal should be turned
|
||||
@@ -1755,9 +1721,8 @@ class NetAssign_ {
|
||||
|
||||
private:
|
||||
NetNet *sig_;
|
||||
NetMemory*mem_;
|
||||
// Memory word index
|
||||
NetExpr*bmux_;
|
||||
NetExpr*word_;
|
||||
|
||||
bool turn_sig_to_wire_on_release_;
|
||||
// indexed part select base
|
||||
@@ -2095,7 +2060,6 @@ class NetEvent : public LineInfo {
|
||||
~NetEvent();
|
||||
|
||||
perm_string name() const;
|
||||
string full_name() const;
|
||||
|
||||
// Get information about probes connected to me.
|
||||
unsigned nprobe() const;
|
||||
@@ -2302,8 +2266,9 @@ class NetFuncDef {
|
||||
|
||||
void set_proc(NetProc*st);
|
||||
|
||||
const string name() const;
|
||||
//const string name() const;
|
||||
const NetProc*proc() const;
|
||||
const NetScope*scope() const;
|
||||
NetScope*scope();
|
||||
|
||||
unsigned port_count() const;
|
||||
@@ -2441,12 +2406,13 @@ class NetSTask : public NetProc {
|
||||
class NetTaskDef {
|
||||
|
||||
public:
|
||||
NetTaskDef(const string&n, const svector<NetNet*>&po);
|
||||
NetTaskDef(NetScope*n, const svector<NetNet*>&po);
|
||||
~NetTaskDef();
|
||||
|
||||
void set_proc(NetProc*p);
|
||||
|
||||
const string& name() const;
|
||||
//const string& name() const;
|
||||
const NetScope* scope() const;
|
||||
const NetProc*proc() const;
|
||||
|
||||
unsigned port_count() const;
|
||||
@@ -2455,7 +2421,7 @@ class NetTaskDef {
|
||||
void dump(ostream&, unsigned) const;
|
||||
|
||||
private:
|
||||
string name_;
|
||||
NetScope*scope_;
|
||||
NetProc*proc_;
|
||||
svector<NetNet*>ports_;
|
||||
|
||||
@@ -2472,11 +2438,9 @@ class NetTaskDef {
|
||||
class NetEUFunc : public NetExpr {
|
||||
|
||||
public:
|
||||
NetEUFunc(NetScope*, NetESignal*, svector<NetExpr*>&);
|
||||
NetEUFunc(NetScope*, NetESignal*, svector<NetExpr*>&);
|
||||
~NetEUFunc();
|
||||
|
||||
const string name() const;
|
||||
|
||||
const NetESignal*result_sig() const;
|
||||
|
||||
unsigned parm_count() const;
|
||||
@@ -2518,6 +2482,7 @@ class NetUTask : public NetProc {
|
||||
const NetScope* task() const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual void nex_output(NexusSet&);
|
||||
virtual bool emit_proc(struct target_t*) const;
|
||||
virtual void dump(ostream&, unsigned ind) const;
|
||||
|
||||
@@ -2658,6 +2623,7 @@ class NetEBinary : public NetExpr {
|
||||
NetExpr* right_;
|
||||
|
||||
void eval_sub_tree_();
|
||||
bool get_real_arguments_(verireal&lv, verireal&rv);
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -2677,8 +2643,11 @@ class NetEBAdd : public NetEBinary {
|
||||
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetEBAdd* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*);
|
||||
|
||||
private:
|
||||
NetECReal* eval_tree_real_();
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -2696,7 +2665,7 @@ class NetEBDiv : public NetEBinary {
|
||||
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetEBDiv* dup_expr() const;
|
||||
virtual NetExpr* eval_tree();
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*);
|
||||
};
|
||||
|
||||
@@ -2722,7 +2691,7 @@ class NetEBBits : public NetEBinary {
|
||||
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetEBBits* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
|
||||
virtual NetNet* synthesize(Design*);
|
||||
};
|
||||
@@ -2753,7 +2722,7 @@ class NetEBComp : public NetEBinary {
|
||||
virtual bool has_width() const;
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
virtual NetEBComp* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
|
||||
virtual NetNet* synthesize(Design*);
|
||||
|
||||
@@ -2783,7 +2752,7 @@ class NetEBLogic : public NetEBinary {
|
||||
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetEBLogic* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*);
|
||||
|
||||
private:
|
||||
@@ -2803,7 +2772,7 @@ class NetEBMult : public NetEBinary {
|
||||
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetEBMult* dup_expr() const;
|
||||
virtual NetExpr* eval_tree();
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*);
|
||||
|
||||
private:
|
||||
@@ -2825,7 +2794,7 @@ class NetEBPow : public NetEBinary {
|
||||
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetEBPow* dup_expr() const;
|
||||
virtual NetExpr* eval_tree();
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet* synthesize(Design*);
|
||||
|
||||
private:
|
||||
@@ -2856,7 +2825,7 @@ class NetEBShift : public NetEBinary {
|
||||
virtual bool has_width() const;
|
||||
|
||||
virtual NetEBShift* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
|
||||
virtual NetNet* synthesize(Design*);
|
||||
|
||||
@@ -2891,7 +2860,7 @@ class NetEConcat : public NetExpr {
|
||||
virtual bool has_width() const;
|
||||
virtual bool set_width(unsigned w, bool last_chance =false);
|
||||
virtual NetEConcat* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
virtual NetNet*synthesize(Design*);
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
@@ -2923,7 +2892,7 @@ class NetEParam : public NetExpr {
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual bool has_width() const;
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetExpr* eval_tree();
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
virtual NetEParam* dup_expr() const;
|
||||
|
||||
virtual void dump(ostream&) const;
|
||||
@@ -2962,7 +2931,7 @@ class NetESelect : public NetExpr {
|
||||
virtual bool set_width(unsigned w, bool last_chance =false);
|
||||
virtual bool has_width() const;
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual NetEConst* eval_tree();
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
virtual NetESelect* dup_expr() const;
|
||||
virtual NetNet*synthesize(Design*des);
|
||||
virtual void dump(ostream&) const;
|
||||
@@ -3072,8 +3041,9 @@ class NetETernary : public NetExpr {
|
||||
const NetExpr*false_expr() const;
|
||||
|
||||
virtual NetETernary* dup_expr() const;
|
||||
virtual NetExpr* eval_tree();
|
||||
virtual NetExpr* eval_tree(int prune_to_width = -1);
|
||||
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
virtual NexusSet* nex_input();
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
@@ -3112,8 +3082,9 @@ class NetEUnary : public NetExpr {
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
|
||||
virtual NetEUnary* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
virtual NexusSet* nex_input();
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
@@ -3133,7 +3104,8 @@ class NetEUBits : public NetEUnary {
|
||||
|
||||
virtual NetNet* synthesize(Design*);
|
||||
|
||||
virtual NetEConst* eval_tree();
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
};
|
||||
|
||||
class NetEUReduce : public NetEUnary {
|
||||
@@ -3145,56 +3117,25 @@ class NetEUReduce : public NetEUnary {
|
||||
virtual bool set_width(unsigned w, bool last_chance);
|
||||
virtual NetNet* synthesize(Design*);
|
||||
virtual NetEUReduce* dup_expr() const;
|
||||
virtual NetEConst* eval_tree();
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* A reference to a memory is represented by this expression. If the
|
||||
* index is not supplied, then the node is only valid in certain
|
||||
* specific contexts.
|
||||
*/
|
||||
class NetEMemory : public NetExpr {
|
||||
|
||||
public:
|
||||
NetEMemory(NetMemory*mem, NetExpr*idx =0);
|
||||
virtual ~NetEMemory();
|
||||
|
||||
perm_string name () const;
|
||||
const NetExpr* index() const;
|
||||
|
||||
virtual bool set_width(unsigned, bool last_chance);
|
||||
virtual NetNet* synthesize(Design*des);
|
||||
|
||||
NetExpr* eval_tree();
|
||||
virtual NetEMemory*dup_expr() const;
|
||||
|
||||
virtual NexusSet* nex_input();
|
||||
virtual void expr_scan(struct expr_scan_t*) const;
|
||||
virtual void dump(ostream&) const;
|
||||
|
||||
const NetMemory*memory() const { return mem_; };
|
||||
|
||||
private:
|
||||
NetMemory*mem_;
|
||||
NetExpr* idx_;
|
||||
virtual NetEConst* eval_tree(int prune_to_width = -1);
|
||||
virtual ivl_variable_type_t expr_type() const;
|
||||
};
|
||||
|
||||
/*
|
||||
* When a signal shows up in an expression, this type represents
|
||||
* it. From this the expression can get any kind of access to the
|
||||
* structural signal.
|
||||
* structural signal, including arrays.
|
||||
*
|
||||
* A signal shows up as a node in the netlist so that structural
|
||||
* activity can invoke the expression. This node also supports part
|
||||
* select by indexing a range of the NetNet that is associated with
|
||||
* it. The msi() is the more significant index, and lsi() the least
|
||||
* significant index.
|
||||
* The NetESignal may refer to an array, if the word_index is
|
||||
* included. This expression calculates the index of the word in the
|
||||
* array. It may only be nil if the expression refers to the whole
|
||||
* array, and that is legal only in limited situation.
|
||||
*/
|
||||
class NetESignal : public NetExpr {
|
||||
|
||||
public:
|
||||
NetESignal(NetNet*n);
|
||||
NetESignal(NetNet*n, NetExpr*word_index);
|
||||
~NetESignal();
|
||||
|
||||
perm_string name() const;
|
||||
@@ -3204,12 +3145,16 @@ class NetESignal : public NetExpr {
|
||||
NetNet* synthesize(Design*des);
|
||||
NexusSet* nex_input();
|
||||
|
||||
// These methods actually reference the properties of the
|
||||
// NetNet object that I point to.
|
||||
unsigned bit_count() const;
|
||||
Link& bit(unsigned idx);
|
||||
// This is the expression for selecting an array word, if this
|
||||
// signal refers to an array.
|
||||
const NetExpr* word_index() const;
|
||||
|
||||
// This is the width of the vector that this signal refers to.
|
||||
unsigned vector_width() const;
|
||||
// Point back to the signal that this expression node references.
|
||||
const NetNet* sig() const;
|
||||
NetNet* sig();
|
||||
// Declared vector dimensions for the signal.
|
||||
unsigned msi() const;
|
||||
unsigned lsi() const;
|
||||
|
||||
@@ -3220,6 +3165,8 @@ class NetESignal : public NetExpr {
|
||||
|
||||
private:
|
||||
NetNet*net_;
|
||||
// Expression to select a word from the net.
|
||||
NetExpr*word_;
|
||||
};
|
||||
|
||||
|
||||
@@ -3235,7 +3182,7 @@ class NetScope : public Attrib {
|
||||
|
||||
/* Create a new scope, and attach it to the given parent. The
|
||||
name is expected to have been permallocated. */
|
||||
NetScope(NetScope*up, perm_string name, TYPE t);
|
||||
NetScope(NetScope*up, const hname_t&name, TYPE t);
|
||||
~NetScope();
|
||||
|
||||
/* Parameters exist within a scope, and these methods allow
|
||||
@@ -3273,26 +3220,14 @@ class NetScope : public Attrib {
|
||||
|
||||
void add_signal(NetNet*);
|
||||
void rem_signal(NetNet*);
|
||||
|
||||
NetNet* find_signal(const char*name);
|
||||
NetNet* find_signal_in_child(const hname_t&name);
|
||||
|
||||
|
||||
/* ... and these methods manage memory the same way as signals
|
||||
are managed above. */
|
||||
|
||||
void add_memory(NetMemory*);
|
||||
void rem_memory(NetMemory*);
|
||||
|
||||
NetMemory* find_memory(const string&name);
|
||||
|
||||
|
||||
/* The parent and child() methods allow users of NetScope
|
||||
objects to locate nearby scopes. */
|
||||
NetScope* parent();
|
||||
NetScope* child(const char*name);
|
||||
NetScope* child(const hname_t&name);
|
||||
const NetScope* parent() const;
|
||||
const NetScope* child(const char*name) const;
|
||||
const NetScope* child(const hname_t&name) const;
|
||||
|
||||
TYPE type() const;
|
||||
|
||||
@@ -3331,7 +3266,7 @@ class NetScope : public Attrib {
|
||||
name, whereas the basename is just my name within my parent
|
||||
scope. */
|
||||
perm_string basename() const;
|
||||
string name() const;
|
||||
const hname_t& fullname() const { return name_; }
|
||||
|
||||
void run_defparams(class Design*);
|
||||
void evaluate_parameters(class Design*);
|
||||
@@ -3339,9 +3274,6 @@ class NetScope : public Attrib {
|
||||
/* This method generates a non-hierarchical name that is
|
||||
guaranteed to be unique within this scope. */
|
||||
perm_string local_symbol();
|
||||
/* This method generates a hierarchical name that is
|
||||
guaranteed to be unique globally. */
|
||||
string local_hsymbol();
|
||||
|
||||
void dump(ostream&) const;
|
||||
void emit_scope(struct target_t*tgt) const;
|
||||
@@ -3356,7 +3288,7 @@ class NetScope : public Attrib {
|
||||
assignments from the scope pass to the parameter evaluation
|
||||
step. After that, it is not used. */
|
||||
|
||||
map<hname_t,NetExpr*>defparams;
|
||||
map<pform_name_t,NetExpr*>defparams;
|
||||
|
||||
public:
|
||||
/* After everything is all set up, the code generators like
|
||||
@@ -3392,15 +3324,13 @@ class NetScope : public Attrib {
|
||||
|
||||
private:
|
||||
TYPE type_;
|
||||
perm_string name_;
|
||||
hname_t name_;
|
||||
|
||||
signed char time_unit_, time_prec_;
|
||||
NetNet::Type default_nettype_;
|
||||
|
||||
NetEvent *events_;
|
||||
NetNet *signals_;
|
||||
NetMemory*memories_;
|
||||
|
||||
perm_string module_name_;
|
||||
union {
|
||||
NetTaskDef*task_;
|
||||
@@ -3458,8 +3388,8 @@ class Design {
|
||||
path is taken as an absolute scope name. Otherwise, the
|
||||
scope is located starting at the passed scope and working
|
||||
up if needed. */
|
||||
NetScope* find_scope(const hname_t&path) const;
|
||||
NetScope* find_scope(NetScope*, const hname_t&path) const;
|
||||
NetScope* find_scope(const std::list<hname_t>&path) const;
|
||||
NetScope* find_scope(NetScope*, const std::list<hname_t>&path) const;
|
||||
|
||||
// PARAMETERS
|
||||
|
||||
@@ -3471,15 +3401,13 @@ class Design {
|
||||
this method, unlike the NetScope::find_signal method,
|
||||
handles global name binding. */
|
||||
|
||||
NetNet*find_signal(NetScope*scope, hname_t path);
|
||||
NetNet*find_signal(NetScope*scope, pform_name_t path);
|
||||
|
||||
// Functions
|
||||
NetFuncDef* find_function(NetScope*scope, const hname_t&key);
|
||||
NetFuncDef* find_function(const hname_t&path);
|
||||
NetFuncDef* find_function(NetScope*scope, const pform_name_t&key);
|
||||
|
||||
// Tasks
|
||||
NetScope* find_task(NetScope*scope, const hname_t&name);
|
||||
NetScope* find_task(const hname_t&key);
|
||||
NetScope* find_task(NetScope*scope, const pform_name_t&name);
|
||||
|
||||
// NODES
|
||||
void add_node(NetNode*);
|
||||
@@ -3565,8 +3493,70 @@ inline ostream& operator << (ostream&o, const NetExpr&exp)
|
||||
|
||||
extern ostream& operator << (ostream&, NetNet::Type);
|
||||
|
||||
/*
|
||||
* Manipulator to dump a scope complete path to the output. The
|
||||
* manipulator is "scope_path" and works like this:
|
||||
*
|
||||
* out << .... << scope_path(sc) << ... ;
|
||||
*/
|
||||
struct __ScopePathManip { const NetScope*scope; };
|
||||
inline __ScopePathManip scope_path(const NetScope*scope)
|
||||
{ __ScopePathManip tmp; tmp.scope = scope; return tmp; }
|
||||
|
||||
extern ostream& operator << (ostream&o, __ScopePathManip);
|
||||
|
||||
|
||||
/*
|
||||
* $Log: netlist.h,v $
|
||||
* Revision 1.380 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.379 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.378 2007/04/26 03:06:22 steve
|
||||
* Rework hname_t to use perm_strings.
|
||||
*
|
||||
* Revision 1.377 2007/04/17 04:34:23 steve
|
||||
* Fix handling calls to tasks in combinational always block
|
||||
*
|
||||
* Revision 1.376 2007/04/07 04:46:18 steve
|
||||
* Handle evaluate of addition of real valued constants.
|
||||
*
|
||||
* Revision 1.375 2007/04/02 01:12:34 steve
|
||||
* Seperate arrayness from word count
|
||||
*
|
||||
* Revision 1.374 2007/03/26 18:17:50 steve
|
||||
* Remove pretense of general use for t_cookie.
|
||||
*
|
||||
* Revision 1.373 2007/03/22 16:08:16 steve
|
||||
* Spelling fixes from Larry
|
||||
*
|
||||
* Revision 1.372 2007/03/08 05:30:03 steve
|
||||
* Limit the calculated widths of constants.
|
||||
*
|
||||
* Revision 1.371 2007/03/02 06:13:22 steve
|
||||
* Add support for edge sensitive spec paths.
|
||||
*
|
||||
* Revision 1.370 2007/03/01 06:19:38 steve
|
||||
* Add support for conditional specify delay paths.
|
||||
*
|
||||
* Revision 1.369 2007/02/20 05:58:36 steve
|
||||
* Handle unary minus of real valued expressions.
|
||||
*
|
||||
* Revision 1.368 2007/02/14 05:59:46 steve
|
||||
* Handle type of ternary expressions properly.
|
||||
*
|
||||
* Revision 1.367 2007/02/02 04:33:00 steve
|
||||
* Use inttypes.h instead of stdint.h for portability.
|
||||
*
|
||||
* Revision 1.366 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.365 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
|
||||
|
||||
+43
-34
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netmisc.cc,v 1.12 2006/06/02 04:48:50 steve Exp $"
|
||||
#ident "$Id: netmisc.cc,v 1.14 2007/06/02 03:42:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -25,6 +25,8 @@
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include "PExpr.h"
|
||||
# include "pform_types.h"
|
||||
# include "ivl_assert.h"
|
||||
|
||||
NetNet* add_to_net(Design*des, NetNet*sig, long val)
|
||||
{
|
||||
@@ -124,13 +126,13 @@ NetExpr* make_sub_expr(long val, NetExpr*expr)
|
||||
}
|
||||
|
||||
NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||
const PExpr*pe, int expr_wid)
|
||||
const PExpr*pe, int expr_wid, int prune_width)
|
||||
{
|
||||
NetExpr*tmp = pe->elaborate_expr(des, scope, expr_wid, false);
|
||||
if (tmp == 0)
|
||||
return 0;
|
||||
|
||||
if (NetExpr*tmp2 = tmp->eval_tree()) {
|
||||
if (NetExpr*tmp2 = tmp->eval_tree(prune_width)) {
|
||||
delete tmp;
|
||||
tmp = tmp2;
|
||||
}
|
||||
@@ -138,9 +140,47 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||
return tmp;
|
||||
}
|
||||
|
||||
std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
|
||||
const pform_name_t&path)
|
||||
{
|
||||
list<hname_t> res;
|
||||
|
||||
typedef pform_name_t::const_iterator pform_path_it;
|
||||
|
||||
for (pform_path_it cur = path.begin() ; cur != path.end(); cur++) {
|
||||
const name_component_t&comp = *cur;
|
||||
if (comp.index.empty()) {
|
||||
res.push_back(hname_t(comp.name));
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(comp.index.size() == 1);
|
||||
const index_component_t&index = comp.index.front();
|
||||
assert(index.sel == index_component_t::SEL_BIT);
|
||||
|
||||
NetExpr*tmp = elab_and_eval(des, scope, index.msb, -1);
|
||||
ivl_assert(*index.msb, tmp);
|
||||
|
||||
if (NetEConst*ctmp = dynamic_cast<NetEConst*>(tmp)) {
|
||||
res.push_back(hname_t(comp.name, ctmp->value().as_long()));
|
||||
delete ctmp;
|
||||
continue;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: netmisc.cc,v $
|
||||
* Revision 1.14 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.13 2007/03/08 05:30:03 steve
|
||||
* Limit the calculated widths of constants.
|
||||
*
|
||||
* Revision 1.12 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
|
||||
@@ -153,36 +193,5 @@ NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||
* Remove the NetEBitSel and combine all bit/part select
|
||||
* behavior into the NetESelect node and IVL_EX_SELECT
|
||||
* ivl_target expression type.
|
||||
*
|
||||
* Revision 1.9 2004/12/11 02:31:27 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.8 2004/02/20 18:53:35 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
* Revision 1.7 2004/02/18 17:11:57 steve
|
||||
* Use perm_strings for named langiage items.
|
||||
*
|
||||
* Revision 1.6 2003/03/06 00:28:42 steve
|
||||
* All NetObj objects have lex_string base names.
|
||||
*
|
||||
* Revision 1.5 2003/02/26 01:29:24 steve
|
||||
* LPM objects store only their base names.
|
||||
*
|
||||
* Revision 1.4 2002/08/31 03:48:50 steve
|
||||
* Fix reverse bit ordered bit select in continuous assignment.
|
||||
*
|
||||
* Revision 1.3 2002/08/12 01:35:00 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.2 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.1 2001/02/11 02:15:52 steve
|
||||
* Add the netmisc.cc source file.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: netmisc.h,v 1.26 2006/09/28 00:29:49 steve Exp $"
|
||||
#ident "$Id: netmisc.h,v 1.31 2007/06/02 03:42:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -39,23 +39,21 @@
|
||||
* ex2 is the lsb expression for the range. If there is no range, then
|
||||
* these values are set to 0.
|
||||
*/
|
||||
extern NetScope* symbol_search(const Design*des,
|
||||
NetScope*start, hname_t path,
|
||||
extern NetScope* symbol_search(Design*des,
|
||||
NetScope*start, pform_name_t path,
|
||||
NetNet*&net, /* net/reg */
|
||||
NetMemory*&mem, /* memory */
|
||||
const NetExpr*&par,/* parameter */
|
||||
NetEvent*&eve, /* named event */
|
||||
const NetExpr*&ex1, const NetExpr*&ex2);
|
||||
|
||||
inline NetScope* symbol_search(const Design*des,
|
||||
NetScope*start, const hname_t&path,
|
||||
inline NetScope* symbol_search(Design*des,
|
||||
NetScope*start, const pform_name_t&path,
|
||||
NetNet*&net, /* net/reg */
|
||||
NetMemory*&mem, /* memory */
|
||||
const NetExpr*&par,/* parameter */
|
||||
NetEvent*&eve /* named event */)
|
||||
{
|
||||
const NetExpr*ex1, *ex2;
|
||||
return symbol_search(des, start, path, net, mem, par, eve, ex1, ex2);
|
||||
return symbol_search(des, start, path, net, par, eve, ex1, ex2);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -89,7 +87,7 @@ extern NetNet*add_to_net(Design*des, NetNet*sig, long val);
|
||||
* where order matters.
|
||||
*
|
||||
* make_add_expr
|
||||
* Make a NetEBAdd expresion with <expr> the first argument and
|
||||
* Make a NetEBAdd expression with <expr> the first argument and
|
||||
* <val> the second. This may get turned into a subtract if <val> is
|
||||
* less then zero. If val is exactly zero, then return <expr> as is.
|
||||
*
|
||||
@@ -114,14 +112,41 @@ extern unsigned count_lval_width(const class NetAssign_*first);
|
||||
* it can. If the expression cannot be elaborated, return 0.
|
||||
*
|
||||
* The expr_width is the width of the context where the expression is
|
||||
* being elaborated, or -1 if the expression is self-determinted width.
|
||||
* being elaborated, or -1 if the expression is self-determined width.
|
||||
*
|
||||
* Also, the prune_width is the maximum width of the result, and it
|
||||
* passed to the eval_tree method of the expression to limit constant
|
||||
* results if possible.
|
||||
*/
|
||||
class PExpr;
|
||||
extern NetExpr* elab_and_eval(Design*des, NetScope*scope,
|
||||
const PExpr*pe, int expr_wid);
|
||||
const PExpr*pe, int expr_wid,
|
||||
int prune_width =-1);
|
||||
|
||||
extern std::list<hname_t> eval_scope_path(Design*des, NetScope*scope,
|
||||
const pform_name_t&path);
|
||||
|
||||
/*
|
||||
* $Log: netmisc.h,v $
|
||||
* Revision 1.31 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.30 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.29 2007/03/08 05:30:03 steve
|
||||
* Limit the calculated widths of constants.
|
||||
*
|
||||
* Revision 1.28 2007/02/26 19:49:49 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.27 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.26 2006/09/28 00:29:49 steve
|
||||
* Allow specparams as constants in expressions.
|
||||
*
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1998-2004 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 1998-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
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: pform.cc,v 1.137 2006/09/23 04:57:19 steve Exp $"
|
||||
#ident "$Id: pform.cc,v 1.148 2007/06/12 04:05:45 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -33,6 +33,7 @@
|
||||
# include <list>
|
||||
# include <map>
|
||||
# include <assert.h>
|
||||
# include <stack>
|
||||
# include <typeinfo>
|
||||
# include <sstream>
|
||||
|
||||
@@ -50,6 +51,9 @@ extern int VLparse();
|
||||
exactly one module currently being parsed, since verilog does not
|
||||
allow nested module definitions. */
|
||||
static Module*pform_cur_module = 0;
|
||||
|
||||
bool pform_library_flag = false;
|
||||
|
||||
/* increment this for generate schemes within a module, and set it
|
||||
to zero when a new module starts. */
|
||||
static unsigned scope_generate_counter = 1;
|
||||
@@ -77,35 +81,34 @@ static unsigned pform_timescale_line = 0;
|
||||
* and named blocks causes scope to be pushed and popped. The module
|
||||
* name is not included in this scope stack.
|
||||
*
|
||||
* The hier_name function, therefore, converts the name to the scope
|
||||
* of the module currently in progress.
|
||||
* The hier_name function, therefore, converts the name to the scoped
|
||||
* name within the module currently in progress. It never includes an
|
||||
* instance name.
|
||||
*
|
||||
* The scope stack does not include any scope created by a generate
|
||||
* scheme.
|
||||
*/
|
||||
|
||||
static hname_t scope_stack;
|
||||
static pform_name_t scope_stack;
|
||||
|
||||
void pform_push_scope(char*name)
|
||||
{
|
||||
scope_stack.append(name);
|
||||
scope_stack.push_back(name_component_t(lex_strings.make(name)));
|
||||
}
|
||||
|
||||
void pform_pop_scope()
|
||||
{
|
||||
char*tmp = scope_stack.remove_tail_name();
|
||||
assert(tmp);
|
||||
free(tmp);
|
||||
scope_stack.pop_back();
|
||||
}
|
||||
|
||||
static hname_t hier_name(const char*tail)
|
||||
static pform_name_t hier_name(const char*tail)
|
||||
{
|
||||
hname_t name = scope_stack;
|
||||
name.append(tail);
|
||||
pform_name_t name = scope_stack;
|
||||
name.push_back(name_component_t(lex_strings.make(tail)));
|
||||
return name;
|
||||
}
|
||||
|
||||
static PWire*get_wire_in_module(const hname_t&name)
|
||||
static PWire*get_wire_in_module(const pform_name_t&name)
|
||||
{
|
||||
/* Note that if we are processing a generate, then the
|
||||
scope depth will be empty because generate schemes
|
||||
@@ -199,7 +202,7 @@ verinum* pform_verinum_with_size(verinum*siz, verinum*val,
|
||||
break;
|
||||
}
|
||||
|
||||
verinum*res = new verinum(pad, size);
|
||||
verinum*res = new verinum(pad, size, true);
|
||||
|
||||
unsigned copy = val->len();
|
||||
if (res->len() < copy)
|
||||
@@ -242,6 +245,7 @@ void pform_startmodule(const char*name, const char*file, unsigned lineno,
|
||||
|
||||
pform_cur_module->set_file(file);
|
||||
pform_cur_module->set_lineno(lineno);
|
||||
pform_cur_module->library_flag = pform_library_flag;
|
||||
|
||||
/* The generate scheme numbering starts with *1*, not
|
||||
zero. That's just the way it is, thanks to the standard. */
|
||||
@@ -274,7 +278,7 @@ Module::port_t* pform_module_port_reference(char*name,
|
||||
unsigned lineno)
|
||||
{
|
||||
Module::port_t*ptmp = new Module::port_t;
|
||||
PEIdent*tmp = new PEIdent(hname_t(name));
|
||||
PEIdent*tmp = new PEIdent(lex_strings.make(name));
|
||||
tmp->set_file(file);
|
||||
tmp->set_lineno(lineno);
|
||||
ptmp->name = lex_strings.make(name);
|
||||
@@ -344,7 +348,7 @@ void pform_start_generate_for(const struct vlltype&li,
|
||||
gen->set_lineno(li.first_line);
|
||||
|
||||
// For now, assume that generates do not nest.
|
||||
assert(pform_cur_generate == 0);
|
||||
gen->parent = pform_cur_generate;
|
||||
pform_cur_generate = gen;
|
||||
|
||||
pform_cur_generate->scheme_type = PGenerate::GS_LOOP;
|
||||
@@ -371,8 +375,13 @@ void pform_endgenerate()
|
||||
assert(pform_cur_generate != 0);
|
||||
assert(pform_cur_module);
|
||||
|
||||
pform_cur_module->generate_schemes.push_back(pform_cur_generate);
|
||||
pform_cur_generate = 0;
|
||||
PGenerate*cur = pform_cur_generate;
|
||||
pform_cur_generate = cur->parent;
|
||||
|
||||
if (pform_cur_generate != 0)
|
||||
pform_cur_generate->generates.push_back(cur);
|
||||
else
|
||||
pform_cur_module->generate_schemes.push_back(cur);
|
||||
}
|
||||
|
||||
bool pform_expression_is_constant(const PExpr*ex)
|
||||
@@ -508,9 +517,10 @@ void pform_make_udp(perm_string name, list<string>*parms,
|
||||
map<string,PWire*> defs;
|
||||
for (unsigned idx = 0 ; idx < decl->count() ; idx += 1) {
|
||||
|
||||
hname_t pname = (*decl)[idx]->path();
|
||||
pform_name_t pname = (*decl)[idx]->path();
|
||||
string port_name = peek_tail_name(pname).str();
|
||||
|
||||
if (PWire*cur = defs[pname.peek_name(0)]) {
|
||||
if (PWire*cur = defs[port_name]) {
|
||||
bool rc = true;
|
||||
assert((*decl)[idx]);
|
||||
if ((*decl)[idx]->get_port_type() != NetNet::PIMPLICIT) {
|
||||
@@ -523,7 +533,7 @@ void pform_make_udp(perm_string name, list<string>*parms,
|
||||
}
|
||||
|
||||
} else {
|
||||
defs[pname.peek_name(0)] = (*decl)[idx];
|
||||
defs[port_name] = (*decl)[idx];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -669,7 +679,7 @@ void pform_make_udp(perm_string name, list<string>*parms,
|
||||
|
||||
// Make the port list for the UDP
|
||||
for (unsigned idx = 0 ; idx < pins.count() ; idx += 1)
|
||||
udp->ports[idx] = pins[idx]->path().peek_name(0);
|
||||
udp->ports[idx] = peek_tail_name(pins[idx]->path());
|
||||
|
||||
process_udp_table(udp, table, file, lineno);
|
||||
udp->initial = init;
|
||||
@@ -753,7 +763,7 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
|
||||
|
||||
// Make the port list for the UDP
|
||||
for (unsigned idx = 0 ; idx < pins.count() ; idx += 1)
|
||||
udp->ports[idx] = pins[idx]->path().peek_name(0);
|
||||
udp->ports[idx] = peek_tail_name(pins[idx]->path());
|
||||
|
||||
assert(udp);
|
||||
assert(table);
|
||||
@@ -910,6 +920,14 @@ void pform_makegates(PGBuiltin::Type type,
|
||||
* constraints, and sometimes different syntax. The X_modgate
|
||||
* functions handle the instantiations of modules (and UDP objects) by
|
||||
* making PGModule objects.
|
||||
*
|
||||
* The first pform_make_modgate handles the case of a module
|
||||
* instantiated with ports passed by position. The "wires" is an
|
||||
* ordered array of port expressions.
|
||||
*
|
||||
* The second pform_make_modgate handles the case of a module
|
||||
* instantiated with ports passed by name. The "bind" argument is the
|
||||
* ports matched with names.
|
||||
*/
|
||||
static void pform_make_modgate(perm_string type,
|
||||
perm_string name,
|
||||
@@ -982,7 +1000,11 @@ static void pform_make_modgate(perm_string type,
|
||||
cur->set_parameters(overrides->by_order);
|
||||
}
|
||||
|
||||
pform_cur_module->add_gate(cur);
|
||||
|
||||
if (pform_cur_generate)
|
||||
pform_cur_generate->add_gate(cur);
|
||||
else
|
||||
pform_cur_module->add_gate(cur);
|
||||
}
|
||||
|
||||
void pform_make_modgates(perm_string type,
|
||||
@@ -1087,7 +1109,7 @@ void pform_make_pgassign_list(svector<PExpr*>*alist,
|
||||
void pform_make_reginit(const struct vlltype&li,
|
||||
const char*name, PExpr*expr)
|
||||
{
|
||||
const hname_t sname = hier_name(name);
|
||||
const pform_name_t sname = hier_name(name);
|
||||
PWire*cur = pform_cur_module->get_wire(sname);
|
||||
if (cur == 0) {
|
||||
VLerror(li, "internal error: reginit to non-register?");
|
||||
@@ -1126,11 +1148,11 @@ void pform_module_define_port(const struct vlltype&li,
|
||||
svector<PExpr*>*range,
|
||||
svector<named_pexpr_t*>*attr)
|
||||
{
|
||||
hname_t name = hier_name(nm);
|
||||
pform_name_t name = hier_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
if (cur) {
|
||||
ostringstream msg;
|
||||
msg << name << " definition conflicts with "
|
||||
msg << nm << " definition conflicts with "
|
||||
<< "definition at " << cur->get_line()
|
||||
<< ".";
|
||||
VLerror(msg.str().c_str());
|
||||
@@ -1193,28 +1215,25 @@ void pform_makewire(const vlltype&li, const char*nm,
|
||||
ivl_variable_type_t dt,
|
||||
svector<named_pexpr_t*>*attr)
|
||||
{
|
||||
hname_t name = hier_name(nm);
|
||||
pform_name_t name = hier_name(nm);
|
||||
|
||||
PWire*cur = get_wire_in_module(name);
|
||||
|
||||
if (cur) {
|
||||
if ((cur->get_wire_type() != NetNet::IMPLICIT)
|
||||
&& (cur->get_wire_type() != NetNet::IMPLICIT_REG)) {
|
||||
// If this is not implicit ("implicit" meaning we don't know
|
||||
// what the type is yet) then set thay type now.
|
||||
if (cur && type != NetNet::IMPLICIT) {
|
||||
bool rc = cur->set_wire_type(type);
|
||||
if (rc == false) {
|
||||
ostringstream msg;
|
||||
msg << name << " previously defined at " <<
|
||||
cur->get_line() << ".";
|
||||
msg << nm << " definition conflicts with "
|
||||
<< "definition at " << cur->get_line()
|
||||
<< ".";
|
||||
VLerror(msg.str().c_str());
|
||||
} else {
|
||||
bool rc = cur->set_wire_type(type);
|
||||
if (rc == false) {
|
||||
ostringstream msg;
|
||||
msg << name << " definition conflicts with "
|
||||
<< "definition at " << cur->get_line()
|
||||
<< ".";
|
||||
VLerror(msg.str().c_str());
|
||||
}
|
||||
cerr << "XXXX type=" << type <<", curtype=" << cur->get_wire_type() << endl;
|
||||
}
|
||||
|
||||
}
|
||||
if (cur) {
|
||||
cur->set_file(li.text);
|
||||
cur->set_lineno(li.first_line);
|
||||
return;
|
||||
@@ -1285,10 +1304,11 @@ void pform_makewire(const vlltype&li,
|
||||
pform_makewire(li, first->name, type, NetNet::NOT_A_PORT, dt, 0);
|
||||
pform_set_net_range(first->name, range, signed_flag, dt);
|
||||
|
||||
hname_t name = hier_name(first->name);
|
||||
perm_string first_name = lex_strings.make(first->name);
|
||||
pform_name_t name = hier_name(first_name);
|
||||
PWire*cur = get_wire_in_module(name);
|
||||
if (cur != 0) {
|
||||
PEIdent*lval = new PEIdent(hname_t(first->name));
|
||||
PEIdent*lval = new PEIdent(first_name);
|
||||
lval->set_file(li.text);
|
||||
lval->set_lineno(li.first_line);
|
||||
PGAssign*ass = pform_make_pgassign(lval, first->expr,
|
||||
@@ -1306,7 +1326,7 @@ void pform_makewire(const vlltype&li,
|
||||
void pform_set_port_type(perm_string nm, NetNet::PortType pt,
|
||||
const char*file, unsigned lineno)
|
||||
{
|
||||
hname_t name = hier_name(nm);
|
||||
pform_name_t name = hier_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_LOGIC);
|
||||
@@ -1323,14 +1343,14 @@ void pform_set_port_type(perm_string nm, NetNet::PortType pt,
|
||||
|
||||
case NetNet::NOT_A_PORT:
|
||||
cerr << file << ":" << lineno << ": error: "
|
||||
<< "port " << name << " is not in the port list."
|
||||
<< "port " << nm << " is not in the port list."
|
||||
<< endl;
|
||||
error_count += 1;
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << file << ":" << lineno << ": error: "
|
||||
<< "port " << name << " already has a port declaration."
|
||||
<< "port " << nm << " already has a port declaration."
|
||||
<< endl;
|
||||
error_count += 1;
|
||||
break;
|
||||
@@ -1391,7 +1411,7 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
||||
; cur != names->end() ; cur ++ ) {
|
||||
|
||||
perm_string txt = *cur;
|
||||
hname_t name = hier_name(txt);
|
||||
pform_name_t name = hier_name(txt);
|
||||
|
||||
/* Look for a preexisting wire. If it exists, set the
|
||||
port direction. If not, create it. */
|
||||
@@ -1436,7 +1456,7 @@ void pform_set_function(perm_string name, PFunction*func)
|
||||
|
||||
void pform_set_attrib(perm_string name, perm_string key, char*value)
|
||||
{
|
||||
hname_t path (name);
|
||||
pform_name_t path = hier_name(name);
|
||||
|
||||
if (PWire*cur = pform_cur_module->get_wire(path)) {
|
||||
cur->attributes[key] = new PEString(value);
|
||||
@@ -1529,7 +1549,7 @@ void pform_set_specparam(perm_string name, PExpr*expr)
|
||||
pform_cur_module->specparams[name] = expr;
|
||||
}
|
||||
|
||||
void pform_set_defparam(const hname_t&name, PExpr*expr)
|
||||
void pform_set_defparam(const pform_name_t&name, PExpr*expr)
|
||||
{
|
||||
assert(expr);
|
||||
pform_cur_module->defparms[name] = expr;
|
||||
@@ -1565,8 +1585,23 @@ extern PSpecPath* pform_make_specify_path(const struct vlltype&li,
|
||||
return path;
|
||||
}
|
||||
|
||||
extern PSpecPath*pform_make_specify_edge_path(const struct vlltype&li,
|
||||
int edge_flag, /*posedge==true */
|
||||
list<perm_string>*src, char pol,
|
||||
bool full_flag, list<perm_string>*dst,
|
||||
PExpr*data_source_expression)
|
||||
{
|
||||
PSpecPath*tmp = pform_make_specify_path(li, src, pol, full_flag, dst);
|
||||
tmp->edge = edge_flag;
|
||||
tmp->data_source_expression = data_source_expression;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
extern PSpecPath* pform_assign_path_delay(PSpecPath*path, svector<PExpr*>*del)
|
||||
{
|
||||
if (path == 0)
|
||||
return 0;
|
||||
|
||||
assert(path->delays.size() == 0);
|
||||
|
||||
path->delays.resize(del->count());
|
||||
@@ -1581,6 +1616,8 @@ extern PSpecPath* pform_assign_path_delay(PSpecPath*path, svector<PExpr*>*del)
|
||||
|
||||
extern void pform_module_specify_path(PSpecPath*obj)
|
||||
{
|
||||
if (obj == 0)
|
||||
return;
|
||||
pform_cur_module->specify_paths.push_back(obj);
|
||||
}
|
||||
|
||||
@@ -1606,7 +1643,7 @@ void pform_set_port_type(const struct vlltype&li,
|
||||
|
||||
static void pform_set_reg_integer(const char*nm)
|
||||
{
|
||||
hname_t name = hier_name(nm);
|
||||
pform_name_t name = hier_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::INTEGER,
|
||||
@@ -1622,8 +1659,8 @@ static void pform_set_reg_integer(const char*nm)
|
||||
}
|
||||
assert(cur);
|
||||
|
||||
cur->set_range(new PENumber(new verinum(INTEGER_WIDTH-1, INTEGER_WIDTH)),
|
||||
new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH)));
|
||||
cur->set_range(new PENumber(new verinum(integer_width-1, integer_width)),
|
||||
new PENumber(new verinum((uint64_t)0, integer_width)));
|
||||
cur->set_signed(true);
|
||||
}
|
||||
|
||||
@@ -1640,7 +1677,7 @@ void pform_set_reg_integer(list<perm_string>*names)
|
||||
|
||||
static void pform_set_reg_time(const char*nm)
|
||||
{
|
||||
hname_t name = hier_name(nm);
|
||||
pform_name_t name = hier_name(nm);
|
||||
PWire*cur = pform_cur_module->get_wire(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
|
||||
@@ -1653,8 +1690,8 @@ static void pform_set_reg_time(const char*nm)
|
||||
}
|
||||
assert(cur);
|
||||
|
||||
cur->set_range(new PENumber(new verinum(TIME_WIDTH-1, INTEGER_WIDTH)),
|
||||
new PENumber(new verinum((uint64_t)0, INTEGER_WIDTH)));
|
||||
cur->set_range(new PENumber(new verinum(TIME_WIDTH-1, integer_width)),
|
||||
new PENumber(new verinum((uint64_t)0, integer_width)));
|
||||
}
|
||||
|
||||
void pform_set_reg_time(list<perm_string>*names)
|
||||
@@ -1677,7 +1714,9 @@ svector<PWire*>* pform_make_udp_input_ports(list<perm_string>*names)
|
||||
; cur != names->end()
|
||||
; cur ++ ) {
|
||||
perm_string txt = *cur;
|
||||
PWire*pp = new PWire(hname_t(txt),
|
||||
pform_name_t tmp;
|
||||
tmp.push_back(name_component_t(txt));
|
||||
PWire*pp = new PWire(tmp,
|
||||
NetNet::IMPLICIT,
|
||||
NetNet::PINPUT,
|
||||
IVL_VT_LOGIC);
|
||||
@@ -1702,7 +1741,11 @@ PProcess* pform_make_behavior(PProcess::Type type, Statement*st,
|
||||
delete attr;
|
||||
}
|
||||
|
||||
pform_cur_module->add_behavior(pp);
|
||||
if (pform_cur_generate)
|
||||
pform_cur_generate->add_behavior(pp);
|
||||
else
|
||||
pform_cur_module->add_behavior(pp);
|
||||
|
||||
return pp;
|
||||
}
|
||||
|
||||
@@ -1747,6 +1790,43 @@ int pform_parse(const char*path, FILE*file)
|
||||
|
||||
/*
|
||||
* $Log: pform.cc,v $
|
||||
* Revision 1.148 2007/06/12 04:05:45 steve
|
||||
* Put instantiated modules in the proper generated scope.
|
||||
*
|
||||
* Revision 1.147 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.146 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.145 2007/04/26 03:06:22 steve
|
||||
* Rework hname_t to use perm_strings.
|
||||
*
|
||||
* Revision 1.144 2007/04/19 02:52:53 steve
|
||||
* Add support for -v flag in command file.
|
||||
*
|
||||
* Revision 1.143 2007/04/13 02:34:35 steve
|
||||
* Parse edge sensitive paths without edge specifier.
|
||||
*
|
||||
* Revision 1.142 2007/03/07 04:24:59 steve
|
||||
* Make integer width controllable.
|
||||
*
|
||||
* Revision 1.141 2007/03/05 05:59:10 steve
|
||||
* Handle processes within generate loops.
|
||||
*
|
||||
* Revision 1.140 2007/02/12 01:52:21 steve
|
||||
* Parse all specify paths to pform.
|
||||
*
|
||||
* Revision 1.139 2007/01/27 05:36:11 steve
|
||||
* Fix padding of x when literal is sized and unsigned.
|
||||
*
|
||||
* Revision 1.138 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.137 2006/09/23 04:57:19 steve
|
||||
* Basic support for specify timing.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: pform.h,v 1.87 2006/09/23 04:57:19 steve Exp $"
|
||||
#ident "$Id: pform.h,v 1.91 2007/05/24 04:07:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -69,6 +69,12 @@ extern enum MIN_TYP_MAX { MIN, TYP, MAX } min_typ_max_flag;
|
||||
extern unsigned min_typ_max_warn;
|
||||
PExpr* pform_select_mtm_expr(PExpr*min, PExpr*typ, PExpr*max);
|
||||
|
||||
/*
|
||||
* This flag is true if the lexor thinks we are in a library source
|
||||
* file.
|
||||
*/
|
||||
extern bool pform_library_flag;
|
||||
|
||||
/*
|
||||
* These type are lexical types -- that is, types that are used as
|
||||
* lexical values to decorate the parse tree during parsing. They are
|
||||
@@ -255,7 +261,7 @@ extern void pform_set_localparam(perm_string name,
|
||||
bool signed_flag,
|
||||
svector<PExpr*>*range,
|
||||
PExpr*expr);
|
||||
extern void pform_set_defparam(const hname_t&name, PExpr*expr);
|
||||
extern void pform_set_defparam(const pform_name_t&name, PExpr*expr);
|
||||
|
||||
/*
|
||||
* Functions related to specify blocks.
|
||||
@@ -265,7 +271,13 @@ extern void pform_set_specparam(perm_string name, PExpr*expr);
|
||||
extern PSpecPath*pform_make_specify_path(const struct vlltype&li,
|
||||
list<perm_string>*src, char pol,
|
||||
bool full_flag, list<perm_string>*dst);
|
||||
extern PSpecPath*pform_make_specify_edge_path(const struct vlltype&li,
|
||||
int edge_flag, /*posedge==true */
|
||||
list<perm_string>*src, char pol,
|
||||
bool full_flag, list<perm_string>*dst,
|
||||
PExpr*data_source_expression);
|
||||
extern PSpecPath*pform_assign_path_delay(PSpecPath*obj, svector<PExpr*>*delays);
|
||||
|
||||
extern void pform_module_specify_path(PSpecPath*obj);
|
||||
|
||||
/*
|
||||
@@ -328,6 +340,19 @@ extern void pform_dump(ostream&out, Module*mod);
|
||||
|
||||
/*
|
||||
* $Log: pform.h,v $
|
||||
* Revision 1.91 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.90 2007/04/19 02:52:53 steve
|
||||
* Add support for -v flag in command file.
|
||||
*
|
||||
* Revision 1.89 2007/04/13 02:34:35 steve
|
||||
* Parse edge sensitive paths without edge specifier.
|
||||
*
|
||||
* Revision 1.88 2007/02/12 01:52:21 steve
|
||||
* Parse all specify paths to pform.
|
||||
*
|
||||
* Revision 1.87 2006/09/23 04:57:19 steve
|
||||
* Basic support for specify timing.
|
||||
*
|
||||
|
||||
+121
-33
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: pform_dump.cc,v 1.94 2006/09/23 04:57:19 steve Exp $"
|
||||
#ident "$Id: pform_dump.cc,v 1.101 2007/06/04 02:19:07 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -72,6 +72,65 @@ ostream& operator<< (ostream&o, PGate::strength_t str)
|
||||
return o;
|
||||
}
|
||||
|
||||
ostream& operator<< (ostream&out, perm_string that)
|
||||
{
|
||||
out << that.str();
|
||||
return out;
|
||||
}
|
||||
|
||||
ostream& operator<< (ostream&out, const index_component_t&that)
|
||||
{
|
||||
out << "[";
|
||||
switch (that.sel) {
|
||||
case index_component_t::SEL_BIT:
|
||||
out << *that.msb;
|
||||
break;
|
||||
case index_component_t::SEL_PART:
|
||||
out << *that.msb << ":" << *that.lsb;
|
||||
break;
|
||||
case index_component_t::SEL_IDX_UP:
|
||||
out << *that.msb << "+:" << *that.lsb;
|
||||
break;
|
||||
case index_component_t::SEL_IDX_DO:
|
||||
out << *that.msb << "-:" << *that.lsb;
|
||||
break;
|
||||
default:
|
||||
out << "???";
|
||||
break;
|
||||
}
|
||||
out << "]";
|
||||
return out;
|
||||
}
|
||||
|
||||
ostream& operator<< (ostream&out, const name_component_t&that)
|
||||
{
|
||||
out << that.name.str();
|
||||
|
||||
typedef std::list<index_component_t>::const_iterator index_it_t;
|
||||
for (index_it_t idx = that.index.begin()
|
||||
; idx != that.index.end() ; idx++) {
|
||||
|
||||
out << *idx;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
ostream& operator<< (ostream&o, const pform_name_t&that)
|
||||
{
|
||||
pform_name_t::const_iterator cur;
|
||||
|
||||
cur = that.begin();
|
||||
o << *cur;
|
||||
|
||||
cur++;
|
||||
while (cur != that.end()) {
|
||||
o << "." << *cur;
|
||||
cur++;
|
||||
}
|
||||
|
||||
return o;
|
||||
}
|
||||
|
||||
void PExpr::dump(ostream&out) const
|
||||
{
|
||||
out << typeid(*this).name();
|
||||
@@ -145,29 +204,6 @@ void PENumber::dump(ostream&out) const
|
||||
void PEIdent::dump(ostream&out) const
|
||||
{
|
||||
out << path_;
|
||||
if (msb_) {
|
||||
out << "[" << *msb_;
|
||||
if (lsb_) switch (sel_) {
|
||||
case SEL_IDX_UP:
|
||||
out << "+:" << *lsb_;
|
||||
break;
|
||||
case SEL_IDX_DO:
|
||||
out << "-:" << *lsb_;
|
||||
break;
|
||||
case SEL_PART:
|
||||
out << ":" << *lsb_;
|
||||
break;
|
||||
default:
|
||||
out << ":?:" << *lsb_;
|
||||
break;
|
||||
}
|
||||
out << "]";
|
||||
}
|
||||
|
||||
typedef std::vector<PExpr*>::const_iterator vector_it_t;
|
||||
for (vector_it_t cur = idx_.begin() ; cur != idx_.end() ; cur++) {
|
||||
out << "[" << *(*cur) << "]";
|
||||
}
|
||||
}
|
||||
|
||||
void PEString::dump(ostream&out) const
|
||||
@@ -629,6 +665,9 @@ void PFunction::dump(ostream&out, unsigned ind) const
|
||||
case PTF_REG:
|
||||
out << "reg ";
|
||||
break;
|
||||
case PTF_REG_S:
|
||||
out << "reg_s ";
|
||||
break;
|
||||
case PTF_INTEGER:
|
||||
out << "integer ";
|
||||
break;
|
||||
@@ -742,7 +781,18 @@ void PProcess::dump(ostream&out, unsigned ind) const
|
||||
|
||||
void PSpecPath::dump(std::ostream&out, unsigned ind) const
|
||||
{
|
||||
out << setw(ind) << "" << "specify path (";
|
||||
out << setw(ind) << "" << "specify path ";
|
||||
|
||||
if (condition)
|
||||
out << "if (" << *condition << ") ";
|
||||
|
||||
out << "(";
|
||||
if (edge) {
|
||||
if (edge > 0)
|
||||
out << "posedge ";
|
||||
else
|
||||
out << "negedge ";
|
||||
}
|
||||
|
||||
for (unsigned idx = 0 ; idx < src.size() ; idx += 1) {
|
||||
if (idx > 0) out << ", ";
|
||||
@@ -752,12 +802,18 @@ void PSpecPath::dump(std::ostream&out, unsigned ind) const
|
||||
|
||||
out << " => ";
|
||||
|
||||
if (data_source_expression)
|
||||
out << "(";
|
||||
|
||||
for (unsigned idx = 0 ; idx < dst.size() ; idx += 1) {
|
||||
if (idx > 0) out << ", ";
|
||||
assert(dst[idx]);
|
||||
out << dst[idx];
|
||||
}
|
||||
|
||||
if (data_source_expression)
|
||||
out << " : " << *data_source_expression << ")";
|
||||
|
||||
out << ") = (";
|
||||
for (unsigned idx = 0 ; idx < delays.size() ; idx += 1) {
|
||||
if (idx > 0) out << ", ";
|
||||
@@ -767,9 +823,9 @@ void PSpecPath::dump(std::ostream&out, unsigned ind) const
|
||||
out << ");" << endl;
|
||||
}
|
||||
|
||||
void PGenerate::dump(ostream&out) const
|
||||
void PGenerate::dump(ostream&out, unsigned indent) const
|
||||
{
|
||||
out << " generate(" << id_number << ")";
|
||||
out << setw(indent) << "" << "generate(" << id_number << ")";
|
||||
|
||||
switch (scheme_type) {
|
||||
case GS_NONE:
|
||||
@@ -791,15 +847,25 @@ void PGenerate::dump(ostream&out) const
|
||||
|
||||
out << endl;
|
||||
|
||||
for (map<hname_t,PWire*>::const_iterator idx = wires.begin()
|
||||
for (map<pform_name_t,PWire*>::const_iterator idx = wires.begin()
|
||||
; idx != wires.end() ; idx++) {
|
||||
|
||||
(*idx).second->dump(out, 6);
|
||||
(*idx).second->dump(out, indent+2);
|
||||
}
|
||||
|
||||
for (list<PGate*>::const_iterator idx = gates.begin()
|
||||
; idx != gates.end() ; idx++) {
|
||||
(*idx)->dump(out, 6);
|
||||
(*idx)->dump(out, indent+2);
|
||||
}
|
||||
|
||||
for (list<PProcess*>::const_iterator idx = behaviors.begin()
|
||||
; idx != behaviors.end() ; idx++) {
|
||||
(*idx)->dump(out, indent+2);
|
||||
}
|
||||
|
||||
for (list<PGenerate*>::const_iterator idx = generates.begin()
|
||||
; idx != generates.end() ; idx++) {
|
||||
(*idx)->dump(out, indent+2);
|
||||
}
|
||||
|
||||
out << " endgenerate" << endl;
|
||||
@@ -841,7 +907,7 @@ void Module::dump(ostream&out) const
|
||||
}
|
||||
|
||||
typedef map<perm_string,param_expr_t>::const_iterator parm_iter_t;
|
||||
typedef map<hname_t,PExpr*>::const_iterator parm_hiter_t;
|
||||
typedef map<pform_name_t,PExpr*>::const_iterator parm_hiter_t;
|
||||
for (parm_iter_t cur = parameters.begin()
|
||||
; cur != parameters.end() ; cur ++) {
|
||||
out << " parameter ";
|
||||
@@ -879,7 +945,7 @@ void Module::dump(ostream&out) const
|
||||
typedef list<PGenerate*>::const_iterator genscheme_iter_t;
|
||||
for (genscheme_iter_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; cur++) {
|
||||
(*cur)->dump(out);
|
||||
(*cur)->dump(out, 4);
|
||||
}
|
||||
|
||||
typedef map<perm_string,PExpr*>::const_iterator specparm_iter_t;
|
||||
@@ -906,7 +972,7 @@ void Module::dump(ostream&out) const
|
||||
}
|
||||
|
||||
// Iterate through and display all the wires.
|
||||
for (map<hname_t,PWire*>::const_iterator wire = wires_.begin()
|
||||
for (map<pform_name_t,PWire*>::const_iterator wire = wires_.begin()
|
||||
; wire != wires_.end()
|
||||
; wire ++ ) {
|
||||
|
||||
@@ -1007,6 +1073,28 @@ void PUdp::dump(ostream&out) const
|
||||
|
||||
/*
|
||||
* $Log: pform_dump.cc,v $
|
||||
* Revision 1.101 2007/06/04 02:19:07 steve
|
||||
* Handle bit/part select of array words in nets.
|
||||
*
|
||||
* Revision 1.100 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.99 2007/05/31 18:35:50 steve
|
||||
* Missing return value to perm_string dump
|
||||
*
|
||||
* Revision 1.98 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.97 2007/03/07 00:38:15 steve
|
||||
* Lint fixes.
|
||||
*
|
||||
* Revision 1.96 2007/03/05 05:59:10 steve
|
||||
* Handle processes within generate loops.
|
||||
*
|
||||
* Revision 1.95 2007/02/12 01:52:21 steve
|
||||
* Parse all specify paths to pform.
|
||||
*
|
||||
* Revision 1.94 2006/09/23 04:57:19 steve
|
||||
* Basic support for specify timing.
|
||||
*
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* 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: pform_types.cc,v 1.1 2007/05/24 04:07:12 steve Exp $"
|
||||
#endif
|
||||
|
||||
|
||||
# include "pform_types.h"
|
||||
|
||||
bool operator < (const name_component_t&lef, const name_component_t&rig)
|
||||
{
|
||||
if (lef.name < rig.name)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
#ifndef __pform_types_H
|
||||
#define __pform_types_H
|
||||
/*
|
||||
* 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: pform_types.h,v 1.2 2007/06/04 02:19:07 steve Exp $"
|
||||
#endif
|
||||
|
||||
// This for the perm_string type.
|
||||
# include "StringHeap.h"
|
||||
# include <iostream>
|
||||
# include <list>
|
||||
|
||||
/*
|
||||
* parse-form types.
|
||||
*/
|
||||
|
||||
struct index_component_t {
|
||||
enum ctype_t { SEL_NONE, SEL_BIT, SEL_PART, SEL_IDX_UP, SEL_IDX_DO };
|
||||
|
||||
index_component_t() : sel(SEL_NONE), msb(0), lsb(0) { };
|
||||
~index_component_t() { }
|
||||
|
||||
ctype_t sel;
|
||||
class PExpr*msb;
|
||||
class PExpr*lsb;
|
||||
};
|
||||
|
||||
struct name_component_t {
|
||||
explicit name_component_t(perm_string n) : name(n) { }
|
||||
~name_component_t() { }
|
||||
|
||||
perm_string name;
|
||||
std::list<index_component_t>index;
|
||||
};
|
||||
|
||||
extern bool operator < (const name_component_t&lef, const name_component_t&rig);
|
||||
|
||||
/*
|
||||
* The pform_name_t is the general form for a heirarchical identifier.
|
||||
*/
|
||||
typedef std::list<name_component_t> pform_name_t;
|
||||
|
||||
inline perm_string peek_head_name(const pform_name_t&that)
|
||||
{
|
||||
return that.front().name;
|
||||
}
|
||||
|
||||
inline perm_string peek_tail_name(const pform_name_t&that)
|
||||
{
|
||||
return that.back().name;
|
||||
}
|
||||
|
||||
extern std::ostream& operator<< (std::ostream&out, const pform_name_t&);
|
||||
extern std::ostream& operator<< (std::ostream&out, const name_component_t&that);
|
||||
extern std::ostream& operator<< (std::ostream&out, const index_component_t&that);
|
||||
|
||||
#endif
|
||||
+10
-4
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: set_width.cc,v 1.41 2006/11/04 06:19:25 steve Exp $"
|
||||
#ident "$Id: set_width.cc,v 1.42 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -340,7 +340,7 @@ bool NetECReal::set_width(unsigned w, bool)
|
||||
expr_width(w);
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0
|
||||
bool NetEMemory::set_width(unsigned w, bool)
|
||||
{
|
||||
if (w != mem_->width())
|
||||
@@ -349,7 +349,7 @@ bool NetEMemory::set_width(unsigned w, bool)
|
||||
expr_width(w);
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
bool NetEParam::set_width(unsigned, bool)
|
||||
{
|
||||
return false;
|
||||
@@ -374,7 +374,7 @@ bool NetESFunc::set_width(unsigned w, bool)
|
||||
*/
|
||||
bool NetESignal::set_width(unsigned w, bool)
|
||||
{
|
||||
if (w != bit_count())
|
||||
if (w != vector_width())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -441,6 +441,12 @@ bool NetEUReduce::set_width(unsigned w, bool)
|
||||
|
||||
/*
|
||||
* $Log: set_width.cc,v $
|
||||
* Revision 1.42 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.41 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
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# $Id: README-solaris_pkg.txt,v 1.2 2004/10/04 01:10:56 steve Exp $
|
||||
# $Id: README-solaris_pkg.txt,v 1.3 2007/02/26 19:49:49 steve Exp $
|
||||
|
||||
Notes about the solaris package.
|
||||
|
||||
I. Installing a prebuild solaris package
|
||||
I. Installing a prebuilt solaris package
|
||||
-----------------------------------------
|
||||
|
||||
To install the solaris package do the following as root on your machine:
|
||||
@@ -24,10 +24,10 @@ To install the solaris package do the following as root on your machine:
|
||||
this will install the package. The package will be registered under the
|
||||
name "IVLver"
|
||||
|
||||
II. Deinstalling the solaris package
|
||||
II. Uninstalling the solaris package
|
||||
-------------------------------------
|
||||
|
||||
To deinstall an installed solaris package do the following as root on your machine:
|
||||
To uninstall an installed solaris package do the following as root on your machine:
|
||||
|
||||
pkgrm IVLver
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: svector.h,v 1.10 2005/06/14 19:13:43 steve Exp $"
|
||||
#ident "$Id: svector.h,v 1.11 2007/03/22 16:08:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -31,7 +31,7 @@
|
||||
/*
|
||||
* This is a way simplified vector class that cannot grow or shrink,
|
||||
* and is really only able to handle values. It is intended to be
|
||||
* lighter weight then the STL list class.
|
||||
* lighter weight than the STL list class.
|
||||
*/
|
||||
|
||||
template <class TYPE> class svector {
|
||||
@@ -109,6 +109,9 @@ template <> inline svector<std::string>::svector(unsigned size)
|
||||
|
||||
/*
|
||||
* $Log: svector.h,v $
|
||||
* Revision 1.11 2007/03/22 16:08:17 steve
|
||||
* Spelling fixes from Larry
|
||||
*
|
||||
* Revision 1.10 2005/06/14 19:13:43 steve
|
||||
* gcc3/4 compile errors.
|
||||
*
|
||||
|
||||
+30
-22
@@ -17,19 +17,19 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: symbol_search.cc,v 1.3 2005/11/27 05:56:20 steve Exp $"
|
||||
#ident "$Id: symbol_search.cc,v 1.7 2007/06/02 03:42:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
# include "netmisc.h"
|
||||
# include <assert.h>
|
||||
|
||||
|
||||
/*
|
||||
* Search for the hierarchical name.
|
||||
*/
|
||||
NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
|
||||
NetScope*symbol_search(Design*des, NetScope*scope, pform_name_t path,
|
||||
NetNet*&net,
|
||||
NetMemory*&mem,
|
||||
const NetExpr*&par,
|
||||
NetEvent*&eve,
|
||||
const NetExpr*&ex1, const NetExpr*&ex2)
|
||||
@@ -37,39 +37,31 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
|
||||
assert(scope);
|
||||
|
||||
/* Get the tail name of the object we are looking for. */
|
||||
char*key = path.remove_tail_name();
|
||||
perm_string key = peek_tail_name(path);
|
||||
path.pop_back();
|
||||
|
||||
/* Initialize output argument to cleared. */
|
||||
net = 0;
|
||||
mem = 0;
|
||||
par = 0;
|
||||
eve = 0;
|
||||
|
||||
/* If the path has a scope part, then search for the specified
|
||||
scope that we are supposed to search. */
|
||||
if (path.peek_name(0))
|
||||
scope = des->find_scope(scope, path);
|
||||
if (! path.empty()) {
|
||||
list<hname_t> path_list = eval_scope_path(des, scope, path);
|
||||
assert(path_list.size() == path.size());
|
||||
scope = des->find_scope(scope, path_list);
|
||||
}
|
||||
|
||||
while (scope) {
|
||||
if ( (net = scope->find_signal(key)) ) {
|
||||
delete key;
|
||||
if ( (net = scope->find_signal(key)) )
|
||||
return scope;
|
||||
}
|
||||
|
||||
if ( (mem = scope->find_memory(key)) ) {
|
||||
delete key;
|
||||
if ( (eve = scope->find_event(key)) )
|
||||
return scope;
|
||||
}
|
||||
|
||||
if ( (eve = scope->find_event(key)) ) {
|
||||
delete key;
|
||||
if ( (par = scope->get_parameter(key, ex1, ex2)) )
|
||||
return scope;
|
||||
}
|
||||
|
||||
if ( (par = scope->get_parameter(key, ex1, ex2)) ) {
|
||||
delete key;
|
||||
return scope;
|
||||
}
|
||||
|
||||
if (scope->type() == NetScope::MODULE)
|
||||
scope = 0;
|
||||
@@ -77,12 +69,28 @@ NetScope*symbol_search(const Design*des, NetScope*scope, hname_t path,
|
||||
scope = scope->parent();
|
||||
}
|
||||
|
||||
delete key;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* $Log: symbol_search.cc,v $
|
||||
* Revision 1.7 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.6 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.5 2007/04/26 03:06:22 steve
|
||||
* Rework hname_t to use perm_strings.
|
||||
*
|
||||
* Revision 1.4 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.3 2005/11/27 05:56:20 steve
|
||||
* Handle bit select of parameter with ranges.
|
||||
*
|
||||
|
||||
+3
-45
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: syn-rules.y,v 1.33 2005/04/24 23:44:02 steve Exp $"
|
||||
#ident "$Id: syn-rules.y,v 1.34 2007/01/16 05:44:15 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -118,7 +118,7 @@ static void hookup_DFF_CE(NetFF*ff, NetESignal*d, NetEvProbe*pclk,
|
||||
// where lval is really a "reg [7:0]". In other words, part
|
||||
// selects in the l-value are handled by loff and the lwidth().
|
||||
|
||||
connect(ff->pin_Data(), d->bit(0));
|
||||
connect(ff->pin_Data(), d->sig()->pin(0));
|
||||
connect(ff->pin_Q(), a->sig()->pin(0));
|
||||
|
||||
connect(ff->pin_Clock(), pclk->pin(0));
|
||||
@@ -137,41 +137,6 @@ static void hookup_DFF_CE(NetFF*ff, NetESignal*d, NetEvProbe*pclk,
|
||||
a->turn_sig_to_wire_on_release();
|
||||
}
|
||||
|
||||
static void hookup_RAMDQ(NetRamDq*ram, NetESignal*d, NetNet*adr,
|
||||
NetEvProbe*pclk, NetNet*ce,
|
||||
NetAssign_*a, unsigned rval_pinoffset)
|
||||
{
|
||||
assert(d);
|
||||
assert(a);
|
||||
|
||||
/* Connect the input Data bits of the RAM, from the r-value of
|
||||
the assignment. */
|
||||
connect(ram->pin_Data(), d->bit(rval_pinoffset));
|
||||
|
||||
/* Connect the Address pins from the addr net discovered by the
|
||||
caller. */
|
||||
connect(ram->pin_Address(), adr->pin(0));
|
||||
|
||||
/* Connect the input clock and the WE of the RAM. */
|
||||
assert(pclk);
|
||||
connect(ram->pin_InClock(), pclk->pin(0));
|
||||
if (ce) {
|
||||
connect(ram->pin_WE(), ce->pin(0));
|
||||
} /* XXX does ram CE default to true if not connected? */
|
||||
|
||||
/* This notices any other NetRamDq objects connected to the
|
||||
same NetMemory, that have the same address pins and are
|
||||
otherwise compatible. This absorbs them into this object. */
|
||||
ram->absorb_partners();
|
||||
|
||||
/* This lval_ represents a reg that is a WIRE in the
|
||||
synthesized results. This function signals the destructor
|
||||
to change the REG that this l-value refers to into a
|
||||
WIRE. It is done then, at the last minute, so that pending
|
||||
synthesis can continue to work with it as a WIRE. */
|
||||
a->turn_sig_to_wire_on_release();
|
||||
}
|
||||
|
||||
static void make_DFF_CE(Design*des, NetProcTop*top, NetEvWait*wclk,
|
||||
NetEvent*eclk, NetExpr*cexp, NetAssignBase*asn)
|
||||
{
|
||||
@@ -207,13 +172,6 @@ static void make_DFF_CE(Design*des, NetProcTop*top, NetEvWait*wclk,
|
||||
a->sig()->vector_width());
|
||||
hookup_DFF_CE(ff, d, pclk, ce, a, rval_pinoffset);
|
||||
des->add_node(ff);
|
||||
} else if (a->mem()) {
|
||||
NetMemory *m=a->mem();
|
||||
NetNet *adr = a->bmux()->synthesize(des);
|
||||
NetRamDq*ram = new NetRamDq(top->scope(), m->name(),
|
||||
m, adr->pin_count());
|
||||
hookup_RAMDQ(ram, d, adr, pclk, ce, a, rval_pinoffset);
|
||||
des->add_node(ram);
|
||||
}
|
||||
rval_pinoffset += a->lwidth();
|
||||
}
|
||||
@@ -233,7 +191,7 @@ static void make_initializer(Design*des, NetProcTop*top, NetAssignBase*asn)
|
||||
|
||||
for (unsigned idx = 0 ; idx < asn->l_val(0)->lwidth() ; idx += 1) {
|
||||
|
||||
verinum::V bit = rsig->bit(idx).nexus()->driven_value();
|
||||
verinum::V bit = rsig->sig()->pin(idx).nexus()->driven_value();
|
||||
|
||||
Nexus*nex = asn->l_val(0)->sig()->pin(idx).nexus();
|
||||
for (Link*cur = nex->first_nlink()
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: synth2.cc,v 1.45 2005/08/27 04:32:08 steve Exp $"
|
||||
#ident "$Id: synth2.cc,v 1.46 2007/03/22 16:08:17 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -766,7 +766,7 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetFF*ff,
|
||||
|
||||
assert(events_in.count() == 0);
|
||||
|
||||
/* This can't be other then one unless there are named events,
|
||||
/* This can't be other than one unless there are named events,
|
||||
which I cannot synthesize. */
|
||||
assert(nevents_ == 1);
|
||||
NetEvent*ev = events_[0];
|
||||
@@ -1000,6 +1000,9 @@ void synth2(Design*des)
|
||||
|
||||
/*
|
||||
* $Log: synth2.cc,v $
|
||||
* Revision 1.46 2007/03/22 16:08:17 steve
|
||||
* Spelling fixes from Larry
|
||||
*
|
||||
* Revision 1.45 2005/08/27 04:32:08 steve
|
||||
* Handle synthesis of fully packed case statements.
|
||||
*
|
||||
|
||||
+103
-90
@@ -17,10 +17,11 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-api.cc,v 1.137 2006/09/23 04:57:19 steve Exp $"
|
||||
#ident "$Id: t-dll-api.cc,v 1.144 2007/04/02 01:12:34 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
# include "StringHeap.h"
|
||||
# include "t-dll.h"
|
||||
# include <stdlib.h>
|
||||
# include <string.h>
|
||||
@@ -28,6 +29,8 @@
|
||||
# include <malloc.h>
|
||||
#endif
|
||||
|
||||
static StringHeap api_strings;
|
||||
|
||||
/* THE FOLLOWING ARE FUNCTIONS THAT ARE CALLED FROM THE TARGET. */
|
||||
|
||||
extern "C" const char*ivl_design_flag(ivl_design_t des, const char*key)
|
||||
@@ -96,33 +99,6 @@ inline static const char *basename(ivl_scope_t scope, const char *inst)
|
||||
return inst+1;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_memory_basename(ivl_memory_t net)
|
||||
{
|
||||
return net->basename_;
|
||||
}
|
||||
|
||||
extern "C" ivl_scope_t ivl_memory_scope(ivl_memory_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->scope_;
|
||||
}
|
||||
|
||||
extern "C" int ivl_memory_root(ivl_memory_t net)
|
||||
{
|
||||
return net->root_;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_memory_size(ivl_memory_t net)
|
||||
{
|
||||
return net->size_;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_memory_width(ivl_memory_t net)
|
||||
{
|
||||
return net->width_;
|
||||
}
|
||||
|
||||
|
||||
extern "C" ivl_variable_type_t ivl_const_type(ivl_net_const_t net)
|
||||
{
|
||||
assert(net);
|
||||
@@ -317,6 +293,9 @@ extern "C" ivl_expr_t ivl_expr_oper1(ivl_expr_t net)
|
||||
case IVL_EX_MEMORY:
|
||||
return net->u_.memory_.idx_;
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
return net->u_.signal_.word;
|
||||
|
||||
case IVL_EX_TERNARY:
|
||||
return net->u_.ternary_.cond;
|
||||
|
||||
@@ -443,6 +422,7 @@ extern "C" ivl_signal_t ivl_expr_signal(ivl_expr_t net)
|
||||
switch (net->type_) {
|
||||
|
||||
case IVL_EX_SIGNAL:
|
||||
case IVL_EX_ARRAY:
|
||||
return net->u_.signal_.sig;
|
||||
|
||||
default:
|
||||
@@ -498,12 +478,6 @@ extern "C" unsigned ivl_expr_width(ivl_expr_t net)
|
||||
return net->width_;
|
||||
}
|
||||
|
||||
extern "C" ivl_memory_t ivl_expr_memory(ivl_expr_t net)
|
||||
{
|
||||
assert(net->type_ == IVL_EX_MEMORY);
|
||||
return net->u_.memory_.mem_;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_logic_attr(ivl_net_logic_t net, const char*key)
|
||||
{
|
||||
assert(net);
|
||||
@@ -707,6 +681,18 @@ extern "C" ivl_nexus_t ivl_lpm_sync_set(ivl_lpm_t net)
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_signal_t ivl_lpm_array(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_ARRAY:
|
||||
return net->u_.array.sig;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_lpm_base(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
@@ -726,7 +712,6 @@ extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net)
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.clk;
|
||||
default:
|
||||
assert(0);
|
||||
@@ -739,7 +724,6 @@ extern "C" ivl_expr_t ivl_lpm_aset_value(ivl_lpm_t net)
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.aset_value;
|
||||
default:
|
||||
assert(0);
|
||||
@@ -751,7 +735,6 @@ extern "C" ivl_expr_t ivl_lpm_sset_value(ivl_lpm_t net)
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.sset_value;
|
||||
default:
|
||||
assert(0);
|
||||
@@ -775,7 +758,6 @@ extern "C" ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_RAM:
|
||||
case IVL_LPM_FF:
|
||||
return net->u_.ff.we;
|
||||
default:
|
||||
@@ -827,10 +809,6 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx)
|
||||
else
|
||||
return net->u_.shift.s;
|
||||
|
||||
case IVL_LPM_RAM:
|
||||
assert(idx == 0);
|
||||
return net->u_.ff.d.pin;
|
||||
|
||||
case IVL_LPM_FF:
|
||||
assert(idx == 0);
|
||||
return net->u_.ff.d.pin;
|
||||
@@ -945,10 +923,6 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
|
||||
assert(idx == 0);
|
||||
return net->u_.arith.q;
|
||||
|
||||
case IVL_LPM_RAM:
|
||||
assert(idx == 0);
|
||||
return net->u_.ff.q.pin;
|
||||
|
||||
case IVL_LPM_FF:
|
||||
assert(idx == 0);
|
||||
return net->u_.ff.q.pin;
|
||||
@@ -993,6 +967,10 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net, unsigned idx)
|
||||
assert(idx == 0);
|
||||
return net->u_.repeat.q;
|
||||
|
||||
case IVL_LPM_ARRAY:
|
||||
assert(idx == 0);
|
||||
return net->u_.array.q;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
@@ -1008,12 +986,13 @@ extern "C" ivl_scope_t ivl_lpm_scope(ivl_lpm_t net)
|
||||
extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net)
|
||||
{
|
||||
switch (net->type) {
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.s.pin;
|
||||
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.s;
|
||||
|
||||
case IVL_LPM_ARRAY:
|
||||
return net->u_.array.a;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
@@ -1023,10 +1002,10 @@ extern "C" ivl_nexus_t ivl_lpm_select(ivl_lpm_t net)
|
||||
extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net)
|
||||
{
|
||||
switch (net->type) {
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.swid;
|
||||
case IVL_LPM_MUX:
|
||||
return net->u_.mux.swid;
|
||||
case IVL_LPM_ARRAY:
|
||||
return net->u_.array.swid;
|
||||
case IVL_LPM_CONCAT:
|
||||
return net->u_.concat.inputs;
|
||||
default:
|
||||
@@ -1040,7 +1019,6 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_FF:
|
||||
case IVL_LPM_RAM:
|
||||
case IVL_LPM_MUX:
|
||||
return 0;
|
||||
case IVL_LPM_ADD:
|
||||
@@ -1079,6 +1057,8 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net)
|
||||
return net->u_.part.signed_flag;
|
||||
case IVL_LPM_REPEAT:
|
||||
return 0;
|
||||
case IVL_LPM_ARRAY: // Array ports take the signedness of the array.
|
||||
return net->u_.array.sig->signed_;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
@@ -1119,18 +1099,6 @@ extern "C" unsigned ivl_lpm_width(ivl_lpm_t net)
|
||||
return net->width;
|
||||
}
|
||||
|
||||
extern "C" ivl_memory_t ivl_lpm_memory(ivl_lpm_t net)
|
||||
{
|
||||
assert(net);
|
||||
switch (net->type) {
|
||||
case IVL_LPM_RAM:
|
||||
return net->u_.ff.mem;
|
||||
default:
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" ivl_expr_t ivl_lval_mux(ivl_lval_t net)
|
||||
{
|
||||
assert(net);
|
||||
@@ -1142,16 +1110,9 @@ extern "C" ivl_expr_t ivl_lval_mux(ivl_lval_t net)
|
||||
extern "C" ivl_expr_t ivl_lval_idx(ivl_lval_t net)
|
||||
{
|
||||
assert(net);
|
||||
if (net->type_ == IVL_LVAL_MEM)
|
||||
return net->idx;
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
extern "C" ivl_memory_t ivl_lval_mem(ivl_lval_t net)
|
||||
{
|
||||
assert(net);
|
||||
if (net->type_ == IVL_LVAL_MEM)
|
||||
return net->n.mem;
|
||||
if (net->type_ == IVL_LVAL_ARR)
|
||||
return net->idx;
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
@@ -1174,15 +1135,23 @@ extern "C" ivl_signal_t ivl_lval_sig(ivl_lval_t net)
|
||||
case IVL_LVAL_REG:
|
||||
case IVL_LVAL_NET:
|
||||
case IVL_LVAL_MUX:
|
||||
case IVL_LVAL_ARR:
|
||||
return net->n.sig;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The nexus name is rarely needed. (Shouldn't be needed at all!) This
|
||||
* function will calculate the name if it is not already calculated.
|
||||
*/
|
||||
extern "C" const char* ivl_nexus_name(ivl_nexus_t net)
|
||||
{
|
||||
assert(net);
|
||||
if (net->name_ == 0) {
|
||||
net->name_ = api_strings.add(net->nexus_->name());
|
||||
}
|
||||
return net->name_;
|
||||
}
|
||||
|
||||
@@ -1283,6 +1252,12 @@ extern "C" ivl_scope_t ivl_parameter_scope(ivl_parameter_t net)
|
||||
return net->scope;
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_path_condit(ivl_delaypath_t obj)
|
||||
{
|
||||
assert(obj);
|
||||
return obj->condit;
|
||||
}
|
||||
|
||||
extern uint64_t ivl_path_delay(ivl_delaypath_t obj, ivl_path_edge_t edg)
|
||||
{
|
||||
assert(obj);
|
||||
@@ -1294,6 +1269,16 @@ extern ivl_nexus_t ivl_path_source(ivl_delaypath_t net)
|
||||
return net->src;
|
||||
}
|
||||
|
||||
extern int ivl_path_source_posedge(ivl_delaypath_t net)
|
||||
{
|
||||
return net->posedge ? 1 : 0;
|
||||
}
|
||||
|
||||
extern int ivl_path_source_negedge(ivl_delaypath_t net)
|
||||
{
|
||||
return net->negedge ? 1 : 0;
|
||||
}
|
||||
|
||||
extern "C" ivl_process_type_t ivl_process_type(ivl_process_t net)
|
||||
{
|
||||
return net->type_;
|
||||
@@ -1399,19 +1384,6 @@ extern "C" ivl_lpm_t ivl_scope_lpm(ivl_scope_t net, unsigned idx)
|
||||
return net->lpm_[idx];
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_scope_mems(ivl_scope_t net)
|
||||
{
|
||||
assert(net);
|
||||
return net->nmem_;
|
||||
}
|
||||
|
||||
extern "C" ivl_memory_t ivl_scope_mem(ivl_scope_t net, unsigned idx)
|
||||
{
|
||||
assert(net);
|
||||
assert(idx < net->nmem_);
|
||||
return net->mem_[idx];
|
||||
}
|
||||
|
||||
static unsigned scope_name_len(ivl_scope_t net)
|
||||
{
|
||||
unsigned len = 0;
|
||||
@@ -1520,6 +1492,21 @@ extern "C" const char* ivl_scope_tname(ivl_scope_t net)
|
||||
return net->tname_;
|
||||
}
|
||||
|
||||
extern "C" int ivl_signal_array_base(ivl_signal_t net)
|
||||
{
|
||||
return net->array_base;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_signal_array_count(ivl_signal_t net)
|
||||
{
|
||||
return net->array_words;
|
||||
}
|
||||
|
||||
extern "C" unsigned ivl_signal_dimensions(ivl_signal_t net)
|
||||
{
|
||||
return net->array_dimensions_;
|
||||
}
|
||||
|
||||
extern "C" const char* ivl_signal_attr(ivl_signal_t net, const char*key)
|
||||
{
|
||||
if (net->nattr == 0)
|
||||
@@ -1571,9 +1558,13 @@ extern "C" const char* ivl_signal_name(ivl_signal_t net)
|
||||
return name_buffer;
|
||||
}
|
||||
|
||||
extern "C" ivl_nexus_t ivl_signal_nex(ivl_signal_t net)
|
||||
extern "C" ivl_nexus_t ivl_signal_nex(ivl_signal_t net, unsigned word)
|
||||
{
|
||||
return net->pin_;
|
||||
assert(word < net->array_words);
|
||||
if (net->array_words > 1)
|
||||
return net->pins[word];
|
||||
else
|
||||
return net->pin;
|
||||
}
|
||||
|
||||
extern "C" int ivl_signal_msb(ivl_signal_t net)
|
||||
@@ -1889,11 +1880,9 @@ extern "C" unsigned ivl_stmt_lwidth(ivl_statement_t net)
|
||||
sum += 1;
|
||||
break;
|
||||
case IVL_LVAL_REG:
|
||||
case IVL_LVAL_ARR:
|
||||
sum += ivl_lval_width(cur);
|
||||
break;
|
||||
case IVL_LVAL_MEM:
|
||||
sum += ivl_memory_width(ivl_lval_mem(cur));
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
@@ -1976,6 +1965,30 @@ extern "C" ivl_statement_t ivl_stmt_sub_stmt(ivl_statement_t net)
|
||||
|
||||
/*
|
||||
* $Log: t-dll-api.cc,v $
|
||||
* Revision 1.144 2007/04/02 01:12:34 steve
|
||||
* Seperate arrayness from word count
|
||||
*
|
||||
* Revision 1.143 2007/03/26 16:51:48 steve
|
||||
* do not calculate nexus name unless needed.
|
||||
*
|
||||
* Revision 1.142 2007/03/02 06:13:22 steve
|
||||
* Add support for edge sensitive spec paths.
|
||||
*
|
||||
* Revision 1.141 2007/03/01 06:19:39 steve
|
||||
* Add support for conditional specify delay paths.
|
||||
*
|
||||
* Revision 1.140 2007/01/17 05:00:12 steve
|
||||
* Dead code for memories in scopes.
|
||||
*
|
||||
* Revision 1.139 2007/01/17 04:39:18 steve
|
||||
* Remove dead code related to memories.
|
||||
*
|
||||
* Revision 1.138 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.137 2006/09/23 04:57:19 steve
|
||||
* Basic support for specify timing.
|
||||
*
|
||||
|
||||
+41
-25
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-expr.cc,v 1.43 2005/09/14 02:53:15 steve Exp $"
|
||||
#ident "$Id: t-dll-expr.cc,v 1.47 2007/03/22 16:08:18 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -200,27 +200,6 @@ void dll_target::expr_concat(const NetEConcat*net)
|
||||
expr_ = cur;
|
||||
}
|
||||
|
||||
void dll_target::expr_memory(const NetEMemory*net)
|
||||
{
|
||||
assert(expr_ == 0);
|
||||
if (net->index()) {
|
||||
net->index()->expr_scan(this);
|
||||
assert(expr_);
|
||||
}
|
||||
|
||||
ivl_expr_t cur = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
assert(cur);
|
||||
|
||||
cur->type_ = IVL_EX_MEMORY;
|
||||
cur->value_ = IVL_VT_VECTOR;
|
||||
cur->width_= net->expr_width();
|
||||
cur->signed_ = net->has_sign()? 1 : 0;
|
||||
cur->u_.memory_.mem_ = find_memory(des_, net->memory());
|
||||
cur->u_.memory_.idx_ = expr_;
|
||||
|
||||
expr_ = cur;
|
||||
}
|
||||
|
||||
void dll_target::expr_const(const NetEConst*net)
|
||||
{
|
||||
assert(expr_ == 0);
|
||||
@@ -387,7 +366,7 @@ void dll_target::expr_ternary(const NetETernary*net)
|
||||
assert(expr);
|
||||
|
||||
expr->type_ = IVL_EX_TERNARY;
|
||||
expr->value_= IVL_VT_VECTOR;
|
||||
expr->value_= net->expr_type();
|
||||
expr->width_ = net->expr_width();
|
||||
expr->signed_ = net->has_sign()? 1 : 0;
|
||||
|
||||
@@ -410,8 +389,19 @@ void dll_target::expr_ternary(const NetETernary*net)
|
||||
|
||||
void dll_target::expr_signal(const NetESignal*net)
|
||||
{
|
||||
ivl_signal_t sig = find_signal(des_, net->sig());
|
||||
|
||||
assert(expr_ == 0);
|
||||
|
||||
/* If there is a word expression, generate it. */
|
||||
ivl_expr_t word_expr = 0;
|
||||
if (const NetExpr*word = net->word_index()) {
|
||||
word->expr_scan(this);
|
||||
assert(expr_);
|
||||
word_expr = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
|
||||
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
assert(expr_);
|
||||
|
||||
@@ -419,7 +409,18 @@ void dll_target::expr_signal(const NetESignal*net)
|
||||
expr_->value_= net->expr_type();
|
||||
expr_->width_= net->expr_width();
|
||||
expr_->signed_ = net->has_sign()? 1 : 0;
|
||||
expr_->u_.signal_.sig = find_signal(des_, net->sig());
|
||||
expr_->u_.signal_.word = word_expr;
|
||||
expr_->u_.signal_.sig = sig;
|
||||
|
||||
/* Make account for the special case that this is a reference
|
||||
to an array as a whole. We detect this case by noting that
|
||||
this is an array (more than 1 word) and there is no word
|
||||
select expression. In that case, this is an IVL_EX_ARRAY
|
||||
expression instead of a SIGNAL expression. */
|
||||
if (sig->array_words > 1 && word_expr == 0) {
|
||||
expr_->type_ = IVL_EX_ARRAY;
|
||||
expr_->width_ = 0; // Doesn't make much sense for arrays.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -464,7 +465,7 @@ void dll_target::expr_unary(const NetEUnary*net)
|
||||
|
||||
expr_ = (ivl_expr_t)calloc(1, sizeof(struct ivl_expr_s));
|
||||
expr_->type_ = IVL_EX_UNARY;
|
||||
expr_->value_= IVL_VT_VECTOR;
|
||||
expr_->value_= net->expr_type();
|
||||
expr_->width_ = net->expr_width();
|
||||
expr_->signed_ = net->has_sign()? 1 : 0;
|
||||
expr_->u_.unary_.op_ = net->op();
|
||||
@@ -473,6 +474,21 @@ void dll_target::expr_unary(const NetEUnary*net)
|
||||
|
||||
/*
|
||||
* $Log: t-dll-expr.cc,v $
|
||||
* Revision 1.47 2007/03/22 16:08:18 steve
|
||||
* Spelling fixes from Larry
|
||||
*
|
||||
* Revision 1.46 2007/02/20 05:58:36 steve
|
||||
* Handle unary minus of real valued expressions.
|
||||
*
|
||||
* Revision 1.45 2007/02/14 05:59:46 steve
|
||||
* Handle type of ternary expressions properly.
|
||||
*
|
||||
* 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 2005/09/14 02:53:15 steve
|
||||
* Support bool expressions and compares handle them optimally.
|
||||
*
|
||||
|
||||
+27
-19
@@ -18,7 +18,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll-proc.cc,v 1.68 2006/02/02 02:43:59 steve Exp $"
|
||||
#ident "$Id: t-dll-proc.cc,v 1.71 2007/06/02 03:42:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -131,7 +131,7 @@ bool dll_target::func_def(const NetScope*net)
|
||||
}
|
||||
|
||||
cerr << "?:0" << ": internal error: "
|
||||
<< "Function " << net->name() << " has a return type"
|
||||
<< "Function " << net->basename() << " has a return type"
|
||||
<< " that I do not understand." << endl;
|
||||
|
||||
return false;
|
||||
@@ -171,30 +171,24 @@ void dll_target::make_assign_lvals_(const NetAssignBase*net)
|
||||
cur->n.sig = find_signal(des_, asn->sig());
|
||||
|
||||
cur->idx = 0;
|
||||
if (asn->bmux()) {
|
||||
// If there is a word select expression, it is
|
||||
// really an array index. Note that the word index
|
||||
// expression is already converted to canonical
|
||||
// form by elaboration.
|
||||
if (asn->word()) {
|
||||
assert(expr_ == 0);
|
||||
asn->bmux()->expr_scan(this);
|
||||
|
||||
if (cur->n.sig->lsb_index != 0)
|
||||
sub_off_from_expr_(asn->sig()->lsb());
|
||||
asn->word()->expr_scan(this);
|
||||
// lsb_dist is the distance for this
|
||||
// index. If this is >1, then this may be an
|
||||
// array of arrays, so we need to multiply
|
||||
// to get the canonical index.
|
||||
if (cur->n.sig->lsb_dist != 1)
|
||||
mul_expr_by_const_(cur->n.sig->lsb_dist);
|
||||
|
||||
cur->type_ = IVL_LVAL_MUX;
|
||||
cur->type_ = IVL_LVAL_ARR;
|
||||
cur->idx = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
} else if (asn->mem()) {
|
||||
assert(asn->mem());
|
||||
cur->type_ = IVL_LVAL_MEM;
|
||||
cur->n.mem = find_memory(des_, asn->mem());
|
||||
assert(cur->n.mem);
|
||||
cur->width_ = ivl_memory_width(cur->n.mem);
|
||||
|
||||
assert(expr_ == 0);
|
||||
asn->bmux()->expr_scan(this);
|
||||
cur->idx = expr_;
|
||||
expr_ = 0;
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
@@ -647,6 +641,8 @@ bool dll_target::proc_wait(const NetEvWait*net)
|
||||
ivl_scope_t ev_scope = lookup_scope_(ev->scope());
|
||||
ivl_event_t ev_tmp=0;
|
||||
|
||||
assert(ev_scope);
|
||||
assert(ev_scope->nevent_ > 0);
|
||||
for (unsigned idx = 0 ; idx < ev_scope->nevent_ ; idx += 1) {
|
||||
const char*ename = ivl_event_basename(ev_scope->event_[idx]);
|
||||
if (strcmp(ev->name(), ename) == 0) {
|
||||
@@ -741,6 +737,18 @@ void dll_target::proc_while(const NetWhile*net)
|
||||
|
||||
/*
|
||||
* $Log: t-dll-proc.cc,v $
|
||||
* Revision 1.71 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.70 2007/04/04 01:50:38 steve
|
||||
* t-dll should not canonicalize word addresses, elaboration already does it.
|
||||
*
|
||||
* Revision 1.69 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.68 2006/02/02 02:43:59 steve
|
||||
* Allow part selects of memory words in l-values.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll.cc,v 1.161 2006/11/10 05:44:45 steve Exp $"
|
||||
#ident "$Id: t-dll.cc,v 1.171 2007/06/02 03:42:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -102,6 +102,31 @@ inline const char*dlerror(void)
|
||||
{ return strerror( errno ); }
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The custom new operator for the ivl_nexus_s type allows us to
|
||||
* allocate nexus objects in blocks. There are generally lots of them
|
||||
* permanently allocated, and allocating them in blocks reduces the
|
||||
* allocation overhead.
|
||||
*/
|
||||
static struct ivl_nexus_s * nexus_pool_ptr = 0;
|
||||
static int nexus_pool_remaining = 0;
|
||||
static const size_t NEXUS_POOL_SIZE = 4096;
|
||||
|
||||
void* ivl_nexus_s::operator new(size_t s)
|
||||
{
|
||||
assert(s == sizeof(struct ivl_nexus_s));
|
||||
if (nexus_pool_remaining <= 0) {
|
||||
nexus_pool_ptr = new struct ivl_nexus_s[NEXUS_POOL_SIZE];
|
||||
nexus_pool_remaining = NEXUS_POOL_SIZE;
|
||||
}
|
||||
|
||||
struct ivl_nexus_s*tmp = nexus_pool_ptr;
|
||||
nexus_pool_ptr += 1;
|
||||
nexus_pool_remaining -= 1;
|
||||
|
||||
return tmp;
|
||||
}
|
||||
|
||||
inline static const char *basename(ivl_scope_t scope, const char *inst)
|
||||
{
|
||||
inst += strlen(ivl_scope_name(scope));
|
||||
@@ -109,6 +134,17 @@ inline static const char *basename(ivl_scope_t scope, const char *inst)
|
||||
return inst+1;
|
||||
}
|
||||
|
||||
static perm_string make_scope_name(const hname_t&name)
|
||||
{
|
||||
if (! name.has_number())
|
||||
return name.peek_name();
|
||||
|
||||
char buf[1024];
|
||||
snprintf(buf, sizeof buf, "%s[%d]",
|
||||
name.peek_name().str(), name.peek_number());
|
||||
return lex_strings.make(buf);
|
||||
}
|
||||
|
||||
static struct dll_target dll_target_obj;
|
||||
|
||||
static void drive_from_link(const Link&lnk, ivl_drive_t&drv0, ivl_drive_t&drv1)
|
||||
@@ -187,6 +223,7 @@ ivl_attribute_s* dll_target::fill_in_attributes(const Attrib*net)
|
||||
static ivl_scope_t find_scope_from_root(ivl_scope_t root, const NetScope*cur)
|
||||
{
|
||||
ivl_scope_t parent, tmp;
|
||||
perm_string cur_name = make_scope_name(cur->fullname());
|
||||
|
||||
if (const NetScope*par = cur->parent()) {
|
||||
parent = find_scope_from_root(root, par);
|
||||
@@ -194,11 +231,11 @@ static ivl_scope_t find_scope_from_root(ivl_scope_t root, const NetScope*cur)
|
||||
return 0;
|
||||
|
||||
for (tmp = parent->child_ ; tmp ; tmp = tmp->sibling_)
|
||||
if (strcmp(tmp->name_, cur->basename()) == 0)
|
||||
if (strcmp(tmp->name_, cur_name) == 0)
|
||||
return tmp;
|
||||
|
||||
} else {
|
||||
if (strcmp(root->name_, cur->basename()) == 0)
|
||||
if (strcmp(root->name_, cur_name) == 0)
|
||||
return root;
|
||||
}
|
||||
|
||||
@@ -231,7 +268,7 @@ ivl_signal_t dll_target::find_signal(ivl_design_s &des, const NetNet*net)
|
||||
ivl_scope_t scope = find_scope(des, net->scope());
|
||||
assert(scope);
|
||||
|
||||
const char*nname = net->name();
|
||||
perm_string nname = net->name();
|
||||
|
||||
for (unsigned idx = 0 ; idx < scope->nsigs_ ; idx += 1) {
|
||||
if (strcmp(scope->sigs_[idx]->name_, nname) == 0)
|
||||
@@ -242,27 +279,6 @@ ivl_signal_t dll_target::find_signal(ivl_design_s &des, const NetNet*net)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function locates an ivl_memory_t object that matches the
|
||||
* NetMemory object. The search works by looking for the parent scope,
|
||||
* then scanning the parent scope for the NetMemory object.
|
||||
*/
|
||||
ivl_memory_t dll_target::find_memory(ivl_design_s &des, const NetMemory*net)
|
||||
{
|
||||
ivl_scope_t scope = find_scope(des, net->scope());
|
||||
assert(scope);
|
||||
|
||||
const char*nname = net->name();
|
||||
|
||||
for (unsigned idx = 0 ; idx < scope->nmem_ ; idx += 1) {
|
||||
if (strcmp(scope->mem_[idx]->basename_, nname) == 0)
|
||||
return scope->mem_[idx];
|
||||
}
|
||||
|
||||
assert(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ivl_nexus_t nexus_sig_make(ivl_signal_t net, unsigned pin)
|
||||
{
|
||||
ivl_nexus_t tmp = new struct ivl_nexus_s;
|
||||
@@ -417,14 +433,6 @@ static void scope_add_lpm(ivl_scope_t scope, ivl_lpm_t net)
|
||||
}
|
||||
}
|
||||
|
||||
static void scope_add_mem(ivl_scope_t scope, ivl_memory_t net)
|
||||
{
|
||||
scope->nmem_ += 1;
|
||||
scope->mem_ = (ivl_memory_t*)
|
||||
realloc(scope->mem_, scope->nmem_*sizeof(ivl_memory_t));
|
||||
scope->mem_[scope->nmem_-1] = net;
|
||||
}
|
||||
|
||||
ivl_parameter_t dll_target::scope_find_param(ivl_scope_t scope,
|
||||
const char*name)
|
||||
{
|
||||
@@ -446,7 +454,7 @@ ivl_parameter_t dll_target::scope_find_param(ivl_scope_t scope,
|
||||
*/
|
||||
void dll_target::make_scope_parameters(ivl_scope_t scope, const NetScope*net)
|
||||
{
|
||||
scope->nparam_ = net->parameters.size();
|
||||
scope->nparam_ = net->parameters.size() + net->localparams.size();
|
||||
if (scope->nparam_ == 0) {
|
||||
scope->param_ = 0;
|
||||
return;
|
||||
@@ -466,37 +474,52 @@ void dll_target::make_scope_parameters(ivl_scope_t scope, const NetScope*net)
|
||||
cur_par->scope = scope;
|
||||
|
||||
NetExpr*etmp = (*cur_pit).second.expr;
|
||||
|
||||
if (const NetEConst*e = dynamic_cast<const NetEConst*>(etmp)) {
|
||||
|
||||
expr_const(e);
|
||||
assert(expr_);
|
||||
|
||||
switch (expr_->type_) {
|
||||
case IVL_EX_STRING:
|
||||
expr_->u_.string_.parameter = cur_par;
|
||||
break;
|
||||
case IVL_EX_NUMBER:
|
||||
expr_->u_.number_.parameter = cur_par;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
} else if (const NetECReal*e = dynamic_cast<const NetECReal*>(etmp)) {
|
||||
|
||||
expr_creal(e);
|
||||
assert(expr_);
|
||||
assert(expr_->type_ == IVL_EX_REALNUM);
|
||||
expr_->u_.real_.parameter = cur_par;
|
||||
|
||||
}
|
||||
|
||||
cur_par->value = expr_;
|
||||
expr_ = 0;
|
||||
|
||||
make_scope_param_expr(cur_par, etmp);
|
||||
idx += 1;
|
||||
}
|
||||
for (pit_t cur_pit = net->localparams.begin()
|
||||
; cur_pit != net->localparams.end() ; cur_pit ++) {
|
||||
|
||||
assert(idx < scope->nparam_);
|
||||
ivl_parameter_t cur_par = scope->param_ + idx;
|
||||
cur_par->basename = (*cur_pit).first;
|
||||
cur_par->scope = scope;
|
||||
|
||||
NetExpr*etmp = (*cur_pit).second.expr;
|
||||
make_scope_param_expr(cur_par, etmp);
|
||||
idx += 1;
|
||||
}
|
||||
}
|
||||
|
||||
void dll_target::make_scope_param_expr(ivl_parameter_t cur_par, NetExpr*etmp)
|
||||
{
|
||||
if (const NetEConst*e = dynamic_cast<const NetEConst*>(etmp)) {
|
||||
|
||||
expr_const(e);
|
||||
assert(expr_);
|
||||
|
||||
switch (expr_->type_) {
|
||||
case IVL_EX_STRING:
|
||||
expr_->u_.string_.parameter = cur_par;
|
||||
break;
|
||||
case IVL_EX_NUMBER:
|
||||
expr_->u_.number_.parameter = cur_par;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
} else if (const NetECReal*e = dynamic_cast<const NetECReal*>(etmp)) {
|
||||
|
||||
expr_creal(e);
|
||||
assert(expr_);
|
||||
assert(expr_->type_ == IVL_EX_REALNUM);
|
||||
expr_->u_.real_.parameter = cur_par;
|
||||
|
||||
}
|
||||
|
||||
cur_par->value = expr_;
|
||||
expr_ = 0;
|
||||
}
|
||||
|
||||
void dll_target::add_root(ivl_design_s &des_, const NetScope *s)
|
||||
@@ -515,8 +538,7 @@ void dll_target::add_root(ivl_design_s &des_, const NetScope *s)
|
||||
root_->event_ = 0;
|
||||
root_->nlpm_ = 0;
|
||||
root_->lpm_ = 0;
|
||||
root_->nmem_ = 0;
|
||||
root_->mem_ = 0;
|
||||
root_->def = 0;
|
||||
make_scope_parameters(root_, s);
|
||||
root_->type_ = IVL_SCT_MODULE;
|
||||
root_->tname_ = root_->name_;
|
||||
@@ -665,7 +687,7 @@ bool dll_target::bufz(const NetBUFZ*net)
|
||||
me. This saves me the trouble of allocating them.) */
|
||||
|
||||
assert(net->pin(0).nexus()->t_cookie());
|
||||
obj->pins_[0] = (ivl_nexus_t) net->pin(0).nexus()->t_cookie();
|
||||
obj->pins_[0] = net->pin(0).nexus()->t_cookie();
|
||||
ivl_nexus_ptr_t out_ptr = nexus_log_add(obj->pins_[0], obj, 0);
|
||||
|
||||
|
||||
@@ -706,7 +728,7 @@ bool dll_target::bufz(const NetBUFZ*net)
|
||||
}
|
||||
|
||||
assert(net->pin(1).nexus()->t_cookie());
|
||||
obj->pins_[1] = (ivl_nexus_t) net->pin(1).nexus()->t_cookie();
|
||||
obj->pins_[1] = net->pin(1).nexus()->t_cookie();
|
||||
nexus_log_add(obj->pins_[1], obj, 1);
|
||||
|
||||
/* Attach the logic device to the scope that contains it. */
|
||||
@@ -844,7 +866,7 @@ void dll_target::logic(const NetLogic*net)
|
||||
for (unsigned idx = 0 ; idx < obj->npins_ ; idx += 1) {
|
||||
const Nexus*nex = net->pin(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->pins_[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->pins_[idx] = nex->t_cookie();
|
||||
ivl_nexus_ptr_t tmp = nexus_log_add(obj->pins_[idx], obj, idx);
|
||||
if (idx == 0)
|
||||
out_ptr = tmp;
|
||||
@@ -914,13 +936,13 @@ bool dll_target::sign_extend(const NetSignExtend*net)
|
||||
nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.reduce.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.reduce.q = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.reduce.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
nex = net->pin(1).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.reduce.a = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.reduce.a = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.reduce.a, obj, 1, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
@@ -966,13 +988,13 @@ bool dll_target::ureduce(const NetUReduce*net)
|
||||
nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.reduce.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.reduce.q = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.reduce.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
nex = net->pin(1).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.reduce.a = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.reduce.a = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.reduce.a, obj, 1, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
@@ -996,19 +1018,19 @@ void dll_target::net_case_cmp(const NetCaseCmp*net)
|
||||
nex = net->pin(1).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.a = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.a = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
nex = net->pin(2).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.b = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.b = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.b, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.q = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
@@ -1037,7 +1059,7 @@ bool dll_target::net_sysfunction(const NetSysFunc*net)
|
||||
nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.sfunc.pins[0] = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.sfunc.pins[0] = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.sfunc.pins[0], obj, 0,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
@@ -1045,7 +1067,7 @@ bool dll_target::net_sysfunction(const NetSysFunc*net)
|
||||
nex = net->pin(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.sfunc.pins[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.sfunc.pins[idx] = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.sfunc.pins[idx], obj, 0,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
@@ -1090,7 +1112,7 @@ bool dll_target::net_function(const NetUserFunc*net)
|
||||
for (unsigned idx = 0 ; idx < net->pin_count() ; idx += 1) {
|
||||
const Nexus*nex = net->pin(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
ivl_nexus_t nn = (ivl_nexus_t)nex->t_cookie();
|
||||
ivl_nexus_t nn = nex->t_cookie();
|
||||
assert(nn);
|
||||
|
||||
obj->u_.ufunc.pins[idx] = nn;
|
||||
@@ -1167,7 +1189,7 @@ void dll_target::udp(const NetUDP*net)
|
||||
}
|
||||
|
||||
assert(nex->t_cookie());
|
||||
obj->pins_[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->pins_[idx] = nex->t_cookie();
|
||||
nexus_log_add(obj->pins_[idx], obj, idx);
|
||||
}
|
||||
|
||||
@@ -1186,20 +1208,6 @@ void dll_target::udp(const NetUDP*net)
|
||||
scope_add_logic(scope, obj);
|
||||
}
|
||||
|
||||
void dll_target::memory(const NetMemory*net)
|
||||
{
|
||||
ivl_memory_t obj = new struct ivl_memory_s;
|
||||
|
||||
obj->scope_ = find_scope(des_, net->scope());
|
||||
obj->basename_ = net->name();
|
||||
obj->width_ = net->width();
|
||||
obj->signed_ = 0;
|
||||
obj->size_ = net->count();
|
||||
obj->root_ = -net->index_to_address(0);
|
||||
|
||||
scope_add_mem(obj->scope_, obj);
|
||||
}
|
||||
|
||||
void dll_target::lpm_add_sub(const NetAddSub*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
@@ -1228,19 +1236,19 @@ void dll_target::lpm_add_sub(const NetAddSub*net)
|
||||
nex = net->pin_Result().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.q = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
nex = net->pin_DataA().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.a = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.a = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
nex = net->pin_DataB().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.b = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.b = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.b, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
/* If the carry output is connected, then connect the extra Q
|
||||
@@ -1252,6 +1260,35 @@ void dll_target::lpm_add_sub(const NetAddSub*net)
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
}
|
||||
|
||||
bool dll_target::lpm_array_dq(const NetArrayDq*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_ARRAY;
|
||||
obj->name = net->name();
|
||||
obj->u_.array.sig = find_signal(des_, net->mem());
|
||||
assert(obj->u_.array.sig);
|
||||
obj->scope = find_scope(des_, net->scope());
|
||||
assert(obj->scope);
|
||||
obj->width = net->width();
|
||||
obj->u_.array.swid = net->awidth();
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
|
||||
const Nexus*nex;
|
||||
|
||||
nex = net->pin_Address().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.array.a = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.array.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
nex = net->pin_Result().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.array.q = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.array.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* The lpm_clshift device represents both left and right shifts,
|
||||
* depending on what is connected to the Direction pin. We convert
|
||||
@@ -1283,19 +1320,19 @@ void dll_target::lpm_clshift(const NetCLShift*net)
|
||||
nex = net->pin_Result().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.shift.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.shift.q = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.shift.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
nex = net->pin_Data().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.shift.d = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.shift.d = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.shift.d, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
nex = net->pin_Distance().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.shift.s = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.shift.s = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.shift.s, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
@@ -1324,12 +1361,12 @@ void dll_target::lpm_compare(const NetCompare*net)
|
||||
nex = net->pin_DataA().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.a = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.a = nex->t_cookie();
|
||||
|
||||
nex = net->pin_DataB().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.b = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.b = nex->t_cookie();
|
||||
|
||||
|
||||
if (net->pin_AGEB().is_linked()) {
|
||||
@@ -1337,7 +1374,7 @@ void dll_target::lpm_compare(const NetCompare*net)
|
||||
obj->type = IVL_LPM_CMP_GE;
|
||||
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.arith.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.q = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.q, obj, 0,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
@@ -1346,7 +1383,7 @@ void dll_target::lpm_compare(const NetCompare*net)
|
||||
obj->type = IVL_LPM_CMP_GT;
|
||||
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.arith.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.q = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.q, obj, 0,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
@@ -1355,7 +1392,7 @@ void dll_target::lpm_compare(const NetCompare*net)
|
||||
obj->type = IVL_LPM_CMP_GE;
|
||||
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.arith.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.q = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.q, obj, 0,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
@@ -1366,7 +1403,7 @@ void dll_target::lpm_compare(const NetCompare*net)
|
||||
obj->type = IVL_LPM_CMP_GT;
|
||||
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.arith.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.q = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.q, obj, 0,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
@@ -1377,7 +1414,7 @@ void dll_target::lpm_compare(const NetCompare*net)
|
||||
obj->type = IVL_LPM_CMP_EQ;
|
||||
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.arith.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.q = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.q, obj, 0,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
@@ -1386,7 +1423,7 @@ void dll_target::lpm_compare(const NetCompare*net)
|
||||
obj->type = IVL_LPM_CMP_NE;
|
||||
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.arith.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.q = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.q, obj, 0,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
@@ -1425,19 +1462,19 @@ void dll_target::lpm_divide(const NetDivide*net)
|
||||
nex = net->pin_Result().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.q = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
nex = net->pin_DataA().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.a = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.a = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
nex = net->pin_DataB().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.b = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.b = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.b, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
|
||||
@@ -1463,19 +1500,19 @@ void dll_target::lpm_modulo(const NetModulo*net)
|
||||
nex = net->pin_Result().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.q = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
nex = net->pin_DataA().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.a = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.a = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
nex = net->pin_DataB().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.b = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.b = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.b, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
@@ -1499,7 +1536,7 @@ void dll_target::lpm_ff(const NetFF*net)
|
||||
point back to this device. */
|
||||
nex = net->pin_Clock().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.clk = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.ff.clk = nex->t_cookie();
|
||||
assert(obj->u_.ff.clk);
|
||||
nexus_lpm_add(obj->u_.ff.clk, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
@@ -1508,7 +1545,7 @@ void dll_target::lpm_ff(const NetFF*net)
|
||||
if (net->pin_Enable().is_linked()) {
|
||||
nex = net->pin_Enable().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.we = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.ff.we = nex->t_cookie();
|
||||
assert(obj->u_.ff.we);
|
||||
nexus_lpm_add(obj->u_.ff.we, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
} else {
|
||||
@@ -1518,7 +1555,7 @@ void dll_target::lpm_ff(const NetFF*net)
|
||||
if (net->pin_Aclr().is_linked()) {
|
||||
nex = net->pin_Aclr().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.aclr = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.ff.aclr = nex->t_cookie();
|
||||
assert(obj->u_.ff.aclr);
|
||||
nexus_lpm_add(obj->u_.ff.aclr, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
} else {
|
||||
@@ -1528,7 +1565,7 @@ void dll_target::lpm_ff(const NetFF*net)
|
||||
if (net->pin_Aset().is_linked()) {
|
||||
nex = net->pin_Aset().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.aset = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.ff.aset = nex->t_cookie();
|
||||
assert(obj->u_.ff.aset);
|
||||
nexus_lpm_add(obj->u_.ff.aset, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
@@ -1543,7 +1580,7 @@ void dll_target::lpm_ff(const NetFF*net)
|
||||
if (net->pin_Sclr().is_linked()) {
|
||||
nex = net->pin_Sclr().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.sclr = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.ff.sclr = nex->t_cookie();
|
||||
assert(obj->u_.ff.sclr);
|
||||
nexus_lpm_add(obj->u_.ff.sclr, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
} else {
|
||||
@@ -1553,7 +1590,7 @@ void dll_target::lpm_ff(const NetFF*net)
|
||||
if (net->pin_Sset().is_linked()) {
|
||||
nex = net->pin_Sset().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.sset = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.ff.sset = nex->t_cookie();
|
||||
assert(obj->u_.ff.sset);
|
||||
nexus_lpm_add(obj->u_.ff.sset, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
@@ -1567,84 +1604,17 @@ void dll_target::lpm_ff(const NetFF*net)
|
||||
|
||||
nex = net->pin_Q().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.q.pin = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.ff.q.pin = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.ff.q.pin, obj, 0,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
nex = net->pin_Data().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.d.pin = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.ff.d.pin = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.ff.d.pin, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
}
|
||||
|
||||
void dll_target::lpm_ram_dq(const NetRamDq*net)
|
||||
{
|
||||
ivl_lpm_t obj = new struct ivl_lpm_s;
|
||||
obj->type = IVL_LPM_RAM;
|
||||
obj->name = net->name();
|
||||
obj->u_.ff.mem = find_memory(des_, net->mem());
|
||||
assert(obj->u_.ff.mem);
|
||||
obj->scope = find_scope(des_, net->mem()->scope());
|
||||
assert(obj->scope);
|
||||
|
||||
obj->width = net->width();
|
||||
obj->u_.ff.swid = net->awidth();
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
|
||||
const Nexus*nex;
|
||||
|
||||
// A write port is present only if something is connected to
|
||||
// the clock input.
|
||||
|
||||
bool has_write_port = net->pin_InClock().is_linked();
|
||||
|
||||
// Connect the write clock and write enable
|
||||
|
||||
if (has_write_port) {
|
||||
nex = net->pin_InClock().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.clk = (ivl_nexus_t) nex->t_cookie();
|
||||
assert(obj->u_.ff.clk);
|
||||
nexus_lpm_add(obj->u_.ff.clk, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
nex = net->pin_WE().nexus();
|
||||
if (nex && nex->t_cookie()) {
|
||||
obj->u_.ff.we = (ivl_nexus_t) nex->t_cookie();
|
||||
assert(obj->u_.ff.we);
|
||||
nexus_lpm_add(obj->u_.ff.we, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
else
|
||||
obj->u_.ff.we = 0x0;
|
||||
}
|
||||
else {
|
||||
obj->u_.ff.clk = 0x0;
|
||||
obj->u_.ff.we = 0x0;
|
||||
}
|
||||
|
||||
// Connect the address bus
|
||||
|
||||
nex = net->pin_Address().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.s.pin = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.ff.s.pin, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
// Connect the data busses
|
||||
|
||||
nex = net->pin_Q().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.q.pin = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.ff.q.pin, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
if (has_write_port) {
|
||||
nex = net->pin_Data().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.ff.d.pin = (ivl_nexus_t) nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.ff.d.pin, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Make the NetMult object into an IVL_LPM_MULT node.
|
||||
*/
|
||||
@@ -1666,19 +1636,19 @@ void dll_target::lpm_mult(const NetMult*net)
|
||||
nex = net->pin_Result().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.q = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.q, obj, 0, IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
nex = net->pin_DataA().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.a = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.a = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.a, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
nex = net->pin_DataB().nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.arith.b = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.arith.b = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.arith.b, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
|
||||
@@ -1708,14 +1678,14 @@ void dll_target::lpm_mux(const NetMux*net)
|
||||
/* Connect the output bits. */
|
||||
nex = net->pin_Result().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.mux.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.mux.q = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.mux.q, obj, 0,
|
||||
IVL_DR_STRONG, IVL_DR_STRONG);
|
||||
|
||||
/* Connect the select bits. */
|
||||
nex = net->pin_Sel().nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.mux.s = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.mux.s = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.mux.s, obj, 0,
|
||||
IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
|
||||
@@ -1725,7 +1695,7 @@ void dll_target::lpm_mux(const NetMux*net)
|
||||
|
||||
for (unsigned sdx = 0 ; sdx < selects ; sdx += 1) {
|
||||
nex = net->pin_Data(sdx).nexus();
|
||||
ivl_nexus_t tmp = (ivl_nexus_t) nex->t_cookie();
|
||||
ivl_nexus_t tmp = nex->t_cookie();
|
||||
obj->u_.mux.d[sdx] = tmp;
|
||||
nexus_lpm_add(tmp, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ);
|
||||
}
|
||||
@@ -1751,7 +1721,7 @@ bool dll_target::concat(const NetConcat*net)
|
||||
const Nexus*nex = net->pin(idx).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.concat.pins[idx] = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.concat.pins[idx] = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.concat.pins[idx], obj, 0, dr, dr);
|
||||
}
|
||||
|
||||
@@ -1795,20 +1765,20 @@ bool dll_target::part_select(const NetPartSelect*net)
|
||||
nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.part.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.part.q = nex->t_cookie();
|
||||
|
||||
/* NetPartSelect:pin(1) is the input pin. */
|
||||
nex = net->pin(1).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.part.a = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.part.a = nex->t_cookie();
|
||||
|
||||
/* If the part select has an additional pin, that pin is
|
||||
a variable select base. */
|
||||
if (net->pin_count() >= 3) {
|
||||
nex = net->pin(2).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->u_.part.s = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.part.s = nex->t_cookie();
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1817,13 +1787,13 @@ bool dll_target::part_select(const NetPartSelect*net)
|
||||
nex = net->pin(1).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.part.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.part.q = nex->t_cookie();
|
||||
|
||||
/* NetPartSelect:pin(0) is the input pin. */
|
||||
nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.part.a = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.part.a = nex->t_cookie();
|
||||
break;
|
||||
|
||||
case IVL_LPM_PART_BI:
|
||||
@@ -1833,13 +1803,13 @@ bool dll_target::part_select(const NetPartSelect*net)
|
||||
nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.part.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.part.q = nex->t_cookie();
|
||||
|
||||
/* NetPartSelect:pin(1) is the input pin. */
|
||||
nex = net->pin(1).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.part.a = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.part.a = nex->t_cookie();
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -1881,14 +1851,14 @@ bool dll_target::replicate(const NetReplicate*net)
|
||||
const Nexus*nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.repeat.q = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.repeat.q = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.repeat.q, obj, 0, dr, dr);
|
||||
|
||||
dr = IVL_DR_HiZ;
|
||||
nex = net->pin(1).nexus();
|
||||
assert(nex->t_cookie());
|
||||
|
||||
obj->u_.repeat.a = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->u_.repeat.a = nex->t_cookie();
|
||||
nexus_lpm_add(obj->u_.repeat.a, obj, 0, dr, dr);
|
||||
|
||||
scope_add_lpm(obj->scope, obj);
|
||||
@@ -1949,7 +1919,7 @@ bool dll_target::net_const(const NetConst*net)
|
||||
drive_from_link(net->pin(0), drv0, drv1);
|
||||
const Nexus*nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->pin_ = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->pin_ = nex->t_cookie();
|
||||
nexus_con_add(obj->pin_, obj, 0, drv0, drv1);
|
||||
|
||||
|
||||
@@ -1979,7 +1949,7 @@ bool dll_target::net_literal(const NetLiteral*net)
|
||||
drive_from_link(net->pin(0), drv0, drv1);
|
||||
const Nexus*nex = net->pin(0).nexus();
|
||||
assert(nex->t_cookie());
|
||||
obj->pin_ = (ivl_nexus_t) nex->t_cookie();
|
||||
obj->pin_ = nex->t_cookie();
|
||||
nexus_con_add(obj->pin_, obj, 0, drv0, drv1);
|
||||
|
||||
des_.nconsts += 1;
|
||||
@@ -2002,14 +1972,15 @@ void dll_target::scope(const NetScope*net)
|
||||
unsigned i;
|
||||
scope = NULL;
|
||||
for (i = 0; i < des_.nroots_ && scope == NULL; i++) {
|
||||
if (strcmp(des_.roots_[i]->name_, net->name().c_str()) == 0)
|
||||
if (strcmp(des_.roots_[i]->name_, net->basename()) == 0)
|
||||
scope = des_.roots_[i];
|
||||
}
|
||||
assert(scope);
|
||||
|
||||
} else {
|
||||
perm_string sname = make_scope_name(net->fullname());
|
||||
scope = new struct ivl_scope_s;
|
||||
scope->name_ = net->basename();
|
||||
scope->name_ = sname;
|
||||
scope->child_ = 0;
|
||||
scope->sibling_ = 0;
|
||||
scope->parent = find_scope(des_, net->parent());
|
||||
@@ -2022,8 +1993,7 @@ void dll_target::scope(const NetScope*net)
|
||||
scope->event_ = 0;
|
||||
scope->nlpm_ = 0;
|
||||
scope->lpm_ = 0;
|
||||
scope->nmem_ = 0;
|
||||
scope->mem_ = 0;
|
||||
scope->def = 0;
|
||||
make_scope_parameters(scope, net);
|
||||
scope->time_units = net->time_unit();
|
||||
scope->nattr = net->attr_cnt();
|
||||
@@ -2043,12 +2013,12 @@ void dll_target::scope(const NetScope*net)
|
||||
}
|
||||
assert(def);
|
||||
scope->type_ = IVL_SCT_TASK;
|
||||
scope->tname_ = strings_.make(def->name().c_str());
|
||||
scope->tname_ = def->scope()->basename();
|
||||
break;
|
||||
}
|
||||
case NetScope::FUNC:
|
||||
scope->type_ = IVL_SCT_FUNCTION;
|
||||
scope->tname_ = strings_.make(net->func_def()->name().c_str());
|
||||
scope->tname_ = net->func_def()->scope()->basename();
|
||||
break;
|
||||
case NetScope::BEGIN_END:
|
||||
scope->type_ = IVL_SCT_BEGIN;
|
||||
@@ -2110,6 +2080,8 @@ void dll_target::signal(const NetNet*net)
|
||||
obj->isint_ = false;
|
||||
obj->local_ = (net->local_flag() && (net->peek_eref() == 0))? 1 : 0;
|
||||
|
||||
obj->array_dimensions_ = net->array_dimensions();
|
||||
|
||||
switch (net->port_type()) {
|
||||
|
||||
case NetNet::PINPUT:
|
||||
@@ -2192,18 +2164,33 @@ void dll_target::signal(const NetNet*net)
|
||||
t_cookie of the Nexus object so that I find it again when I
|
||||
next encounter the nexus. */
|
||||
|
||||
const Nexus*nex = net->pin(0).nexus();
|
||||
if (nex->t_cookie()) {
|
||||
obj->pin_ = (ivl_nexus_t)nex->t_cookie();
|
||||
nexus_sig_add(obj->pin_, obj, 0);
|
||||
obj->array_base = net->array_first();
|
||||
obj->array_words = net->array_count();
|
||||
if (obj->array_words > 1)
|
||||
obj->pins = new ivl_nexus_t[obj->array_words];
|
||||
|
||||
} else {
|
||||
ivl_nexus_t tmp = nexus_sig_make(obj, 0);
|
||||
tmp->name_ = strings_.add(nex->name());
|
||||
nex->t_cookie(tmp);
|
||||
obj->pin_ = tmp;
|
||||
for (unsigned idx = 0 ; idx < obj->array_words ; idx += 1) {
|
||||
|
||||
const Nexus*nex = net->pin(idx).nexus();
|
||||
if (nex->t_cookie()) {
|
||||
if (obj->array_words > 1) {
|
||||
obj->pins[idx] = nex->t_cookie();
|
||||
nexus_sig_add(obj->pins[idx], obj, idx);
|
||||
} else {
|
||||
obj->pin = nex->t_cookie();
|
||||
nexus_sig_add(obj->pin, obj, idx);
|
||||
}
|
||||
} else {
|
||||
ivl_nexus_t tmp = nexus_sig_make(obj, idx);
|
||||
tmp->nexus_ = nex;
|
||||
tmp->name_ = 0;
|
||||
nex->t_cookie(tmp);
|
||||
if (obj->array_words > 1)
|
||||
obj->pins[idx] = tmp;
|
||||
else
|
||||
obj->pin = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool dll_target::signal_paths(const NetNet*net)
|
||||
@@ -2222,7 +2209,7 @@ bool dll_target::signal_paths(const NetNet*net)
|
||||
/* Figure out how many paths there really are. */
|
||||
for (unsigned idx = 0 ; idx < net->delay_paths() ; idx += 1) {
|
||||
const NetDelaySrc*src = net->delay_path(idx);
|
||||
obj->npath += src->pin_count();
|
||||
obj->npath += src->src_count();
|
||||
}
|
||||
|
||||
obj->path = new struct ivl_delaypath_s[obj->npath];
|
||||
@@ -2231,8 +2218,15 @@ bool dll_target::signal_paths(const NetNet*net)
|
||||
for (unsigned idx = 0 ; idx < net->delay_paths() ; idx += 1) {
|
||||
const NetDelaySrc*src = net->delay_path(idx);
|
||||
|
||||
for (unsigned pin = 0; pin < src->pin_count(); pin += 1) {
|
||||
const Nexus*nex = src->pin(pin).nexus();
|
||||
/* If this path has a condition, then hook it up. */
|
||||
ivl_nexus_t path_condit = 0;
|
||||
if (src->is_condit()) {
|
||||
const Nexus*nt = src->condit_pin().nexus();
|
||||
path_condit = nt->t_cookie();
|
||||
}
|
||||
|
||||
for (unsigned pin = 0; pin < src->src_count(); pin += 1) {
|
||||
const Nexus*nex = src->src_pin(pin).nexus();
|
||||
if (! nex->t_cookie()) {
|
||||
cerr << src->get_line() << ": internal error: "
|
||||
<< "No signal connected to pin " << pin
|
||||
@@ -2240,14 +2234,17 @@ bool dll_target::signal_paths(const NetNet*net)
|
||||
<< "." << endl;
|
||||
}
|
||||
assert(nex->t_cookie());
|
||||
obj->path[ptr].src = (ivl_nexus_t) nex->t_cookie();
|
||||
|
||||
obj->path[ptr].src = nex->t_cookie();
|
||||
obj->path[ptr].condit = path_condit;
|
||||
obj->path[ptr].posedge = src->is_posedge();
|
||||
obj->path[ptr].negedge = src->is_negedge();
|
||||
for (unsigned pe = 0 ; pe < 12 ; pe += 1) {
|
||||
obj->path[ptr].delay[pe] = src->get_delay(pe);
|
||||
}
|
||||
|
||||
ptr += 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -2258,6 +2255,39 @@ extern const struct target tgt_dll = { "dll", &dll_target_obj };
|
||||
|
||||
/*
|
||||
* $Log: t-dll.cc,v $
|
||||
* Revision 1.171 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.170 2007/04/02 01:12:34 steve
|
||||
* Seperate arrayness from word count
|
||||
*
|
||||
* Revision 1.169 2007/03/26 20:32:47 steve
|
||||
* More efficient allocate of ivl_nexus_t objects.
|
||||
*
|
||||
* Revision 1.168 2007/03/26 18:17:51 steve
|
||||
* Remove pretense of general use for t_cookie.
|
||||
*
|
||||
* Revision 1.167 2007/03/26 16:51:49 steve
|
||||
* do not calculate nexus name unless needed.
|
||||
*
|
||||
* Revision 1.166 2007/03/02 06:13:22 steve
|
||||
* Add support for edge sensitive spec paths.
|
||||
*
|
||||
* Revision 1.165 2007/03/01 06:19:39 steve
|
||||
* Add support for conditional specify delay paths.
|
||||
*
|
||||
* Revision 1.164 2007/01/29 01:52:51 steve
|
||||
* Clarify the use of ivl_scope_def for not-functions.
|
||||
*
|
||||
* Revision 1.163 2007/01/17 05:00:12 steve
|
||||
* Dead code for memories in scopes.
|
||||
*
|
||||
* Revision 1.162 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.161 2006/11/10 05:44:45 steve
|
||||
* Process delay paths in second path over signals.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: t-dll.h,v 1.134 2006/11/10 05:44:45 steve Exp $"
|
||||
#ident "$Id: t-dll.h,v 1.143 2007/06/02 03:42:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "target.h"
|
||||
@@ -74,6 +74,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
void net_case_cmp(const NetCaseCmp*);
|
||||
void udp(const NetUDP*);
|
||||
void lpm_add_sub(const NetAddSub*);
|
||||
bool lpm_array_dq(const NetArrayDq*);
|
||||
void lpm_clshift(const NetCLShift*);
|
||||
void lpm_compare(const NetCompare*);
|
||||
void lpm_divide(const NetDivide*);
|
||||
@@ -81,7 +82,6 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
void lpm_modulo(const NetModulo*);
|
||||
void lpm_mult(const NetMult*);
|
||||
void lpm_mux(const NetMux*);
|
||||
void lpm_ram_dq(const NetRamDq*);
|
||||
bool concat(const NetConcat*);
|
||||
bool part_select(const NetPartSelect*);
|
||||
bool replicate(const NetReplicate*);
|
||||
@@ -97,8 +97,6 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
void scope(const NetScope*);
|
||||
void signal(const NetNet*);
|
||||
bool signal_paths(const NetNet*);
|
||||
void memory(const NetMemory*);
|
||||
|
||||
ivl_dll_t dll_;
|
||||
|
||||
ivl_design_s des_;
|
||||
@@ -134,7 +132,6 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
struct ivl_expr_s*expr_;
|
||||
void expr_binary(const NetEBinary*);
|
||||
void expr_concat(const NetEConcat*);
|
||||
void expr_memory(const NetEMemory*);
|
||||
void expr_const(const NetEConst*);
|
||||
void expr_creal(const NetECReal*);
|
||||
void expr_param(const NetEConstParam*);
|
||||
@@ -157,8 +154,6 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
|
||||
static ivl_scope_t find_scope(ivl_design_s &des, const NetScope*cur);
|
||||
static ivl_signal_t find_signal(ivl_design_s &des, const NetNet*net);
|
||||
static ivl_memory_t find_memory(ivl_design_s &des, const NetMemory*net);
|
||||
|
||||
static ivl_parameter_t scope_find_param(ivl_scope_t scope,
|
||||
const char*name);
|
||||
|
||||
@@ -170,6 +165,7 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
|
||||
void make_logic_delays_(struct ivl_net_logic_s*obj, const NetObj*net);
|
||||
void make_scope_parameters(ivl_scope_t scope, const NetScope*net);
|
||||
void make_scope_param_expr(ivl_parameter_t cur_par, NetExpr*etmp);
|
||||
|
||||
static ivl_expr_t expr_from_value_(const verinum&that);
|
||||
};
|
||||
@@ -180,6 +176,9 @@ struct dll_target : public target_t, public expr_scan_t {
|
||||
|
||||
struct ivl_delaypath_s {
|
||||
ivl_nexus_t src;
|
||||
ivl_nexus_t condit;
|
||||
bool posedge;
|
||||
bool negedge;
|
||||
uint64_t delay[12];
|
||||
};
|
||||
|
||||
@@ -231,6 +230,7 @@ struct ivl_expr_s {
|
||||
|
||||
struct {
|
||||
ivl_signal_t sig;
|
||||
ivl_expr_t word;
|
||||
} signal_;
|
||||
|
||||
struct {
|
||||
@@ -294,7 +294,6 @@ struct ivl_lpm_s {
|
||||
|
||||
union {
|
||||
struct ivl_lpm_ff_s {
|
||||
unsigned swid; // ram only
|
||||
ivl_nexus_t clk;
|
||||
ivl_nexus_t we;
|
||||
ivl_nexus_t aclr;
|
||||
@@ -309,11 +308,6 @@ struct ivl_lpm_s {
|
||||
ivl_nexus_t*pins;
|
||||
ivl_nexus_t pin;
|
||||
} d;
|
||||
union { // ram only
|
||||
ivl_nexus_t*pins;
|
||||
ivl_nexus_t pin;
|
||||
} s;
|
||||
ivl_memory_t mem; // ram only
|
||||
ivl_expr_t aset_value;
|
||||
ivl_expr_t sset_value;
|
||||
} ff;
|
||||
@@ -336,6 +330,12 @@ struct ivl_lpm_s {
|
||||
ivl_nexus_t q, a, b;
|
||||
} arith;
|
||||
|
||||
struct ivl_lpm_array_s {
|
||||
ivl_signal_t sig;
|
||||
unsigned swid;
|
||||
ivl_nexus_t q, a;
|
||||
} array;
|
||||
|
||||
struct ivl_concat_s {
|
||||
unsigned inputs;
|
||||
ivl_nexus_t*pins;
|
||||
@@ -380,8 +380,9 @@ struct ivl_lpm_s {
|
||||
enum ivl_lval_type_t {
|
||||
IVL_LVAL_REG = 0,
|
||||
IVL_LVAL_MUX = 1,
|
||||
IVL_LVAL_MEM = 2,
|
||||
IVL_LVAL_NET = 3 /* Only force can have NET l-values */
|
||||
/* IVL_LVAL_MEM = 2, / Deprecated in favor of LVAL_ARR? */
|
||||
IVL_LVAL_NET = 3, /* Only force can have NET l-values */
|
||||
IVL_LVAL_ARR = 4
|
||||
};
|
||||
|
||||
struct ivl_lval_s {
|
||||
@@ -477,24 +478,18 @@ struct ivl_nexus_ptr_s {
|
||||
# define __NEXUS_PTR_CON 2
|
||||
# define __NEXUS_PTR_LPM 3
|
||||
|
||||
/*
|
||||
* NOTE: ONLY allocat ivl_nexus_s objects with the included "new" operator.
|
||||
*/
|
||||
struct ivl_nexus_s {
|
||||
unsigned nptr_;
|
||||
struct ivl_nexus_ptr_s*ptrs_;
|
||||
const Nexus*nexus_;
|
||||
const char*name_;
|
||||
void*private_data;
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* Memory.
|
||||
*/
|
||||
struct ivl_memory_s {
|
||||
perm_string basename_;
|
||||
ivl_scope_t scope_;
|
||||
unsigned width_;
|
||||
unsigned signed_ : 1;
|
||||
unsigned size_;
|
||||
int root_;
|
||||
void* operator new (size_t s);
|
||||
void operator delete(void*obj, size_t s); // Not implemented
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -547,9 +542,6 @@ struct ivl_scope_s {
|
||||
unsigned nlpm_;
|
||||
ivl_lpm_t* lpm_;
|
||||
|
||||
unsigned nmem_;
|
||||
ivl_memory_t* mem_;
|
||||
|
||||
unsigned nparam_;
|
||||
ivl_parameter_t param_;
|
||||
|
||||
@@ -581,6 +573,9 @@ struct ivl_signal_s {
|
||||
unsigned isint_ : 1;
|
||||
unsigned local_ : 1;
|
||||
|
||||
/* For now, support only 0 or 1 array dimensions. */
|
||||
unsigned array_dimensions_ : 1;
|
||||
|
||||
/* These encode the run-time index for the least significant
|
||||
bit, and the distance to the second bit. */
|
||||
signed lsb_index;
|
||||
@@ -589,7 +584,12 @@ struct ivl_signal_s {
|
||||
perm_string name_;
|
||||
ivl_scope_t scope_;
|
||||
|
||||
ivl_nexus_t pin_;
|
||||
unsigned array_words;
|
||||
int array_base;
|
||||
union {
|
||||
ivl_nexus_t pin;
|
||||
ivl_nexus_t*pins;
|
||||
};
|
||||
|
||||
ivl_delaypath_s*path;
|
||||
unsigned npath;
|
||||
@@ -680,6 +680,36 @@ struct ivl_statement_s {
|
||||
|
||||
/*
|
||||
* $Log: t-dll.h,v $
|
||||
* Revision 1.143 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.142 2007/04/02 01:12:34 steve
|
||||
* Seperate arrayness from word count
|
||||
*
|
||||
* Revision 1.141 2007/03/26 20:32:47 steve
|
||||
* More efficient allocate of ivl_nexus_t objects.
|
||||
*
|
||||
* Revision 1.140 2007/03/26 16:51:49 steve
|
||||
* do not calculate nexus name unless needed.
|
||||
*
|
||||
* Revision 1.139 2007/03/02 06:13:22 steve
|
||||
* Add support for edge sensitive spec paths.
|
||||
*
|
||||
* Revision 1.138 2007/03/01 06:19:39 steve
|
||||
* Add support for conditional specify delay paths.
|
||||
*
|
||||
* Revision 1.137 2007/01/17 05:00:12 steve
|
||||
* Dead code for memories in scopes.
|
||||
*
|
||||
* Revision 1.136 2007/01/17 04:39:18 steve
|
||||
* Remove dead code related to memories.
|
||||
*
|
||||
* Revision 1.135 2007/01/16 05:44:16 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.134 2006/11/10 05:44:45 steve
|
||||
* Process delay paths in second path over signals.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: target.cc,v 1.79 2006/11/10 05:44:45 steve Exp $"
|
||||
#ident "$Id: target.cc,v 1.81 2007/06/02 03:42:13 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -38,20 +38,13 @@ void target_t::scope(const NetScope*)
|
||||
void target_t::event(const NetEvent*ev)
|
||||
{
|
||||
cerr << ev->get_line() << ": error: target (" << typeid(*this).name()
|
||||
<< "): Unhandled event <" << ev->full_name() << ">." << endl;
|
||||
<< "): Unhandled event <" << ev->name() << ">." << endl;
|
||||
}
|
||||
|
||||
bool target_t::signal_paths(const NetNet*)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
void target_t::memory(const NetMemory*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled memory." << endl;
|
||||
}
|
||||
|
||||
bool target_t::func_def(const NetScope*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
@@ -97,6 +90,13 @@ void target_t::lpm_add_sub(const NetAddSub*)
|
||||
"Unhandled NetAddSub." << endl;
|
||||
}
|
||||
|
||||
bool target_t::lpm_array_dq(const NetArrayDq*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetArrayDq." << endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
void target_t::lpm_clshift(const NetCLShift*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
@@ -138,13 +138,6 @@ void target_t::lpm_mux(const NetMux*)
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetMux." << endl;
|
||||
}
|
||||
|
||||
void target_t::lpm_ram_dq(const NetRamDq*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
"Unhandled NetRamDq." << endl;
|
||||
}
|
||||
|
||||
bool target_t::concat(const NetConcat*)
|
||||
{
|
||||
cerr << "target (" << typeid(*this).name() << "): "
|
||||
@@ -380,13 +373,6 @@ void expr_scan_t::expr_concat(const NetEConcat*that)
|
||||
cerr << that->get_line() << ": expr_scan_t (" <<
|
||||
typeid(*this).name() << "): unhandled expr_concat." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_memory(const NetEMemory*)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
"unhandled expr_memory." << endl;
|
||||
}
|
||||
|
||||
void expr_scan_t::expr_event(const NetEEvent*)
|
||||
{
|
||||
cerr << "expr_scan_t (" << typeid(*this).name() << "): "
|
||||
@@ -443,6 +429,15 @@ void expr_scan_t::expr_binary(const NetEBinary*ex)
|
||||
|
||||
/*
|
||||
* $Log: target.cc,v $
|
||||
* Revision 1.81 2007/06/02 03:42:13 steve
|
||||
* Properly evaluate scope path expressions.
|
||||
*
|
||||
* Revision 1.80 2007/01/16 05:44:16 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.79 2006/11/10 05:44:45 steve
|
||||
* Process delay paths in second path over signals.
|
||||
*
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: target.h,v 1.76 2006/11/10 05:44:45 steve Exp $"
|
||||
#ident "$Id: target.h,v 1.77 2007/01/16 05:44:16 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "netlist.h"
|
||||
@@ -66,15 +66,13 @@ struct target_t {
|
||||
virtual void signal(const NetNet*) =0;
|
||||
virtual bool signal_paths(const NetNet*);
|
||||
|
||||
/* Output a memory (called for each memory object) */
|
||||
virtual void memory(const NetMemory*);
|
||||
|
||||
/* Output a defined task. */
|
||||
virtual void task_def(const NetScope*);
|
||||
virtual bool func_def(const NetScope*);
|
||||
|
||||
/* LPM style components are handled here. */
|
||||
virtual void lpm_add_sub(const NetAddSub*);
|
||||
virtual bool lpm_array_dq(const NetArrayDq*);
|
||||
virtual void lpm_clshift(const NetCLShift*);
|
||||
virtual void lpm_compare(const NetCompare*);
|
||||
virtual void lpm_divide(const NetDivide*);
|
||||
@@ -82,7 +80,6 @@ struct target_t {
|
||||
virtual void lpm_ff(const NetFF*);
|
||||
virtual void lpm_mult(const NetMult*);
|
||||
virtual void lpm_mux(const NetMux*);
|
||||
virtual void lpm_ram_dq(const NetRamDq*);
|
||||
|
||||
virtual bool concat(const NetConcat*);
|
||||
virtual bool part_select(const NetPartSelect*);
|
||||
@@ -139,7 +136,6 @@ struct expr_scan_t {
|
||||
virtual void expr_rparam(const NetECRealParam*);
|
||||
virtual void expr_creal(const NetECReal*);
|
||||
virtual void expr_concat(const NetEConcat*);
|
||||
virtual void expr_memory(const NetEMemory*);
|
||||
virtual void expr_event(const NetEEvent*);
|
||||
virtual void expr_scope(const NetEScope*);
|
||||
virtual void expr_select(const NetESelect*);
|
||||
@@ -172,6 +168,12 @@ extern const struct target *target_table[];
|
||||
|
||||
/*
|
||||
* $Log: target.h,v $
|
||||
* Revision 1.77 2007/01/16 05:44:16 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.76 2006/11/10 05:44:45 steve
|
||||
* Process delay paths in second path over signals.
|
||||
*
|
||||
|
||||
@@ -17,7 +17,7 @@ AC_CHECK_HEADERS(malloc.h)
|
||||
# may modify CPPFLAGS and CFLAGS
|
||||
AX_CPP_PRECOMP
|
||||
|
||||
# Compiler option for position independent code, needed whan making shared objects.
|
||||
# Compiler option for position independent code, needed when making shared objects.
|
||||
AX_C_PICFLAG
|
||||
|
||||
# linker options when building a shared library
|
||||
|
||||
+5
-2
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: device.h,v 1.14 2003/11/12 03:20:14 steve Exp $"
|
||||
#ident "$Id: device.h,v 1.15 2007/02/26 19:49:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <ivl_target.h>
|
||||
@@ -72,7 +72,7 @@ struct device_s {
|
||||
* Return the device_t cookie given the name of the architecture. If
|
||||
* the device is not found, return 0.
|
||||
*
|
||||
* This function is used if the user specifies the archetecture
|
||||
* This function is used if the user specifies the architecture
|
||||
* explicitly, with the -parch=name flag.
|
||||
*/
|
||||
extern device_t device_from_arch(const char*arch);
|
||||
@@ -80,6 +80,9 @@ extern device_t device_from_arch(const char*arch);
|
||||
|
||||
/*
|
||||
* $Log: device.h,v $
|
||||
* Revision 1.15 2007/02/26 19:49:49 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.14 2003/11/12 03:20:14 steve
|
||||
* devices need show_cmp_gt
|
||||
*
|
||||
|
||||
+6
-3
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: edif.h,v 1.7 2003/09/03 23:34:09 steve Exp $"
|
||||
#ident "$Id: edif.h,v 1.8 2007/02/26 19:49:49 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <stdio.h>
|
||||
@@ -47,7 +47,7 @@
|
||||
*
|
||||
* Declare external libraries with edif_xlibrary_create
|
||||
* Normally, this is the single technology library that contains
|
||||
* the primitive cells that the code generator intendes to
|
||||
* the primitive cells that the code generator intends to
|
||||
* use. The library is given a name, such as VIRTEX or whatever
|
||||
* the implementation tools expect. Cells are attached to the
|
||||
* library later. An edif netlist may include multiple external
|
||||
@@ -196,7 +196,7 @@ extern edif_cellref_t edif_cellref_create(edif_t edf, edif_cell_t cell);
|
||||
|
||||
/* Instances can have properties attached to them. The name and value
|
||||
given here are turned into a (property <name> (string "val"))
|
||||
sexpression attached to the instance.
|
||||
expression attached to the instance.
|
||||
|
||||
Examples of string properties commonly attached to cellref devices
|
||||
include such things as the INIT=<value> to initialize LUT cells in
|
||||
@@ -231,6 +231,9 @@ extern void edif_print(FILE*fd, edif_t design);
|
||||
|
||||
/*
|
||||
* $Log: edif.h,v $
|
||||
* Revision 1.8 2007/02/26 19:49:49 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.7 2003/09/03 23:34:09 steve
|
||||
* Support synchronous set of LPM_FF devices.
|
||||
*
|
||||
|
||||
+7
-4
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: xilinx.c,v 1.12 2004/02/15 18:03:30 steve Exp $"
|
||||
#ident "$Id: xilinx.c,v 1.13 2007/02/26 19:49:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "edif.h"
|
||||
@@ -273,7 +273,7 @@ edif_cell_t xilinx_cell_xorcy(edif_xlibrary_t xlib)
|
||||
|
||||
/*
|
||||
* This function does a lot of the stuff common to the header
|
||||
* functions of various Xilinx familes. This includes creating the edf
|
||||
* functions of various Xilinx families. This includes creating the edf
|
||||
* object that holds the netlist.
|
||||
*/
|
||||
void xilinx_common_header(ivl_design_t des)
|
||||
@@ -835,14 +835,14 @@ void xilinx_shiftl(ivl_lpm_t net)
|
||||
|
||||
/* Allocate a matrix of edif_cellref_t variables. A devices
|
||||
will be addressed by the expression table[sdx][qdx];
|
||||
This should make the algorighm code easier to read. */
|
||||
This should make the algorithm code easier to read. */
|
||||
cells = calloc(nsel * width, sizeof(edif_cellref_t));
|
||||
table = calloc(nsel, sizeof(edif_cellref_t*));
|
||||
|
||||
for (sdx = 0 ; sdx < nsel ; sdx += 1)
|
||||
table[sdx] = cells + sdx*width;
|
||||
|
||||
/* Make a 0 valued pad bit. I wlil use this for all the shifin
|
||||
/* Make a 0 valued pad bit. I will use this for all the shift in
|
||||
values that are beyond the input. */
|
||||
pad0_cell = edif_cellref_create(edf, cell_0);
|
||||
pad0 = edif_joint_create(edf);
|
||||
@@ -951,6 +951,9 @@ void xilinx_shiftl(ivl_lpm_t net)
|
||||
|
||||
/*
|
||||
* $Log: xilinx.c,v $
|
||||
* Revision 1.13 2007/02/26 19:49:50 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.12 2004/02/15 18:03:30 steve
|
||||
* Cleanup of warnings.
|
||||
*
|
||||
|
||||
+5
-2
@@ -19,13 +19,13 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: xilinx.h,v 1.8 2003/08/15 02:23:53 steve Exp $"
|
||||
#ident "$Id: xilinx.h,v 1.9 2007/02/26 19:49:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This header file includes XILINX library support functions. They
|
||||
* manage the creation and reference of cells from the library. Use
|
||||
* the xililx_cell_* functions to get an edif_cell_t from the
|
||||
* the xilinx_cell_* functions to get an edif_cell_t from the
|
||||
* library. The function will create the cell in the library if
|
||||
* needed, or will return the existing cell if it was already called.
|
||||
*/
|
||||
@@ -130,6 +130,9 @@ extern void xilinx_shiftl(ivl_lpm_t net);
|
||||
|
||||
/*
|
||||
* $Log: xilinx.h,v $
|
||||
* Revision 1.9 2007/02/26 19:49:50 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.8 2003/08/15 02:23:53 steve
|
||||
* Add synthesis support for synchronous reset.
|
||||
*
|
||||
|
||||
+5
-2
@@ -17,7 +17,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: fit_log.c,v 1.5 2002/08/12 01:35:03 steve Exp $"
|
||||
#ident "$Id: fit_log.c,v 1.6 2007/02/26 19:49:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include "config.h"
|
||||
@@ -29,7 +29,7 @@
|
||||
# include "priv.h"
|
||||
|
||||
/*
|
||||
* By the time we get here, all the flip-flops iave been placed in
|
||||
* By the time we get here, all the flip-flops have been placed in
|
||||
* macrocells, and enables attached to them. So all that's left is to
|
||||
* work backwards from each macrocell, making terms and sum-of-terms
|
||||
* from the asynchronous logic until we get to the table inputs.
|
||||
@@ -128,6 +128,9 @@ int fit_logic(void)
|
||||
|
||||
/*
|
||||
* $Log: fit_log.c,v $
|
||||
* Revision 1.6 2007/02/26 19:49:50 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.5 2002/08/12 01:35:03 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
|
||||
+5
-2
@@ -19,7 +19,7 @@
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
|
||||
*/
|
||||
#ifdef HAVE_CVS_IDENT
|
||||
#ident "$Id: priv.h,v 1.7 2002/08/12 01:35:03 steve Exp $"
|
||||
#ident "$Id: priv.h,v 1.8 2007/02/26 19:49:50 steve Exp $"
|
||||
#endif
|
||||
|
||||
# include <ivl_target.h>
|
||||
@@ -88,7 +88,7 @@ extern struct pal_bind_s* bind_pin;
|
||||
|
||||
|
||||
/*
|
||||
* These are various stepps in the fitting process.
|
||||
* These are various steps in the fitting process.
|
||||
*/
|
||||
extern int get_pad_bindings(ivl_scope_t net, void*x);
|
||||
|
||||
@@ -102,6 +102,9 @@ extern int emit_jedec(const char*path);
|
||||
|
||||
/*
|
||||
* $Log: priv.h,v $
|
||||
* Revision 1.8 2007/02/26 19:49:50 steve
|
||||
* Spelling fixes (larry doolittle)
|
||||
*
|
||||
* Revision 1.7 2002/08/12 01:35:03 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