Fix range handling/checking and add a flag to allow deprecated port syntax.
This patch is rather large and fixes a couple of problems. The major change is that instead of keeping all the range specifications in a list that is later processed the information is now kept as individual entries for the port and net definitions. This allows easier checking for multiple definitions (pr1660028), more detailed error messages and the ability to pass the now deprecated style of a scalar I/O definition used with a vectored net definition. These changes did require extra code to prevent a single definition from setting the range values in more than on place. When using the new ANSI-C style of port declarations (1364-2001 12.3.4 list_of_port_declarations) the compiler ensures that you do not redeclare the port in the body (it is already completely defined). This caught a few errors in the test suite (pr859 and sqrt32*). The flag to disable the normal port checking and allow the deprecated port syntax is -gno-io-range-error. This will print a warning for the case of a scalar port with a vectored definition in the body. All other cases are still considered an error.
This commit is contained in:
parent
d08817aec1
commit
b69c4c9a2c
117
PWire.cc
117
PWire.cc
|
|
@ -22,6 +22,7 @@
|
|||
|
||||
# include "config.h"
|
||||
# include "PWire.h"
|
||||
# include "PExpr.h"
|
||||
# include <assert.h>
|
||||
|
||||
PWire::PWire(const pform_name_t&n,
|
||||
|
|
@ -29,8 +30,8 @@ PWire::PWire(const pform_name_t&n,
|
|||
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)
|
||||
signed_(false), isint_(false), port_set_(false), net_set_(false),
|
||||
error_cnt_(0), lidx_(0), ridx_(0)
|
||||
{
|
||||
if (t == NetNet::INTEGER) {
|
||||
type_ = NetNet::REG;
|
||||
|
|
@ -129,10 +130,62 @@ bool PWire::get_isint() const
|
|||
return isint_;
|
||||
}
|
||||
|
||||
void PWire::set_range(PExpr*m, PExpr*l)
|
||||
void PWire::set_net_range()
|
||||
{
|
||||
msb_ = svector<PExpr*>(msb_,m);
|
||||
lsb_ = svector<PExpr*>(lsb_,l);
|
||||
net_msb_ = port_msb_;
|
||||
net_lsb_ = port_lsb_;
|
||||
net_set_ = true;
|
||||
}
|
||||
|
||||
void PWire::set_range(PExpr*m, PExpr*l, PWSRType type)
|
||||
{
|
||||
switch (type) {
|
||||
case SR_PORT:
|
||||
if (port_set_) {
|
||||
cerr << get_line() << ": error: Port ``" << hname_
|
||||
<< "'' has already been declared a port." << endl;
|
||||
error_cnt_ += 1;
|
||||
} else {
|
||||
port_msb_ = m;
|
||||
port_lsb_ = l;
|
||||
port_set_ = true;
|
||||
}
|
||||
return;
|
||||
|
||||
case SR_NET:
|
||||
if (net_set_) {
|
||||
cerr << get_line() << ": error: Net ``" << hname_
|
||||
<< "'' has already been declared." << endl;
|
||||
error_cnt_ += 1;
|
||||
} else {
|
||||
net_msb_ = m;
|
||||
net_lsb_ = l;
|
||||
net_set_ = true;
|
||||
}
|
||||
return;
|
||||
|
||||
case SR_BOTH:
|
||||
if (port_set_ || net_set_) {
|
||||
if (port_set_) {
|
||||
cerr << get_line() << ": error: Port ``" << hname_
|
||||
<< "'' has already been declared a port." << endl;
|
||||
error_cnt_ += 1;
|
||||
}
|
||||
if (net_set_) {
|
||||
cerr << get_line() << ": error: Net ``" << hname_
|
||||
<< "'' has already been declared." << endl;
|
||||
error_cnt_ += 1;
|
||||
}
|
||||
} else {
|
||||
port_msb_ = m;
|
||||
port_lsb_ = l;
|
||||
port_set_ = true;
|
||||
net_msb_ = m;
|
||||
net_lsb_ = l;
|
||||
net_set_ = true;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
|
||||
|
|
@ -143,57 +196,3 @@ void PWire::set_memory_idx(PExpr*ldx, PExpr*rdx)
|
|||
ridx_ = rdx;
|
||||
}
|
||||
|
||||
/*
|
||||
* $Log: PWire.cc,v $
|
||||
* Revision 1.14 2007/05/24 04:07:11 steve
|
||||
* Rework the heirarchical identifier parse syntax and pform
|
||||
* to handle more general combinations of heirarch and bit selects.
|
||||
*
|
||||
* Revision 1.13 2007/04/26 03:06:21 steve
|
||||
* Rework hname_t to use perm_strings.
|
||||
*
|
||||
* Revision 1.12 2007/01/16 05:44:14 steve
|
||||
* Major rework of array handling. Memories are replaced with the
|
||||
* more general concept of arrays. The NetMemory and NetEMemory
|
||||
* classes are removed from the ivl core program, and the IVL_LPM_RAM
|
||||
* lpm type is removed from the ivl_target API.
|
||||
*
|
||||
* Revision 1.11 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.10 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.9 2002/06/21 04:59:35 steve
|
||||
* Carry integerness throughout the compilation.
|
||||
*
|
||||
* Revision 1.8 2002/01/26 05:28:28 steve
|
||||
* Detect scalar/vector declarion mismatch.
|
||||
*
|
||||
* Revision 1.7 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
*
|
||||
* Revision 1.6 2001/07/25 03:10:48 steve
|
||||
* Create a config.h.in file to hold all the config
|
||||
* junk, and support gcc 3.0. (Stephan Boettcher)
|
||||
*
|
||||
* Revision 1.5 2001/01/06 02:29:35 steve
|
||||
* Support arrays of integers.
|
||||
*
|
||||
* Revision 1.4 2000/12/11 00:31:43 steve
|
||||
* Add support for signed reg variables,
|
||||
* simulate in t-vvm signed comparisons.
|
||||
*
|
||||
* Revision 1.3 2000/02/23 02:56:54 steve
|
||||
* Macintosh compilers do not support ident.
|
||||
*
|
||||
* Revision 1.2 1999/09/10 05:02:09 steve
|
||||
* Handle integers at task parameters.
|
||||
*
|
||||
* Revision 1.1 1999/06/17 05:34:42 steve
|
||||
* Clean up interface of the PWire class,
|
||||
* Properly match wire ranges.
|
||||
*
|
||||
*/
|
||||
|
||||
|
|
|
|||
63
PWire.h
63
PWire.h
|
|
@ -37,6 +37,11 @@ class ostream;
|
|||
class PExpr;
|
||||
class Design;
|
||||
|
||||
/*
|
||||
* The different type of PWire::set_range() calls.
|
||||
*/
|
||||
enum PWSRType {SR_PORT, SR_NET, SR_BOTH};
|
||||
|
||||
/*
|
||||
* Wires include nets, registers and ports. A net or register becomes
|
||||
* a port by declaration, so ports are not separate. The module
|
||||
|
|
@ -72,7 +77,8 @@ class PWire : public LineInfo {
|
|||
bool set_data_type(ivl_variable_type_t dt);
|
||||
ivl_variable_type_t get_data_type() const;
|
||||
|
||||
void set_range(PExpr*msb, PExpr*lsb);
|
||||
void set_range(PExpr*msb, PExpr*lsb, PWSRType type);
|
||||
void set_net_range();
|
||||
|
||||
void set_memory_idx(PExpr*ldx, PExpr*rdx);
|
||||
|
||||
|
|
@ -93,8 +99,13 @@ class PWire : public LineInfo {
|
|||
|
||||
// These members hold expressions for the bit width of the
|
||||
// wire. If they do not exist, the wire is 1 bit wide.
|
||||
svector<PExpr*>msb_;
|
||||
svector<PExpr*>lsb_;
|
||||
PExpr*port_msb_;
|
||||
PExpr*port_lsb_;
|
||||
bool port_set_;
|
||||
PExpr*net_msb_;
|
||||
PExpr*net_lsb_;
|
||||
bool net_set_;
|
||||
unsigned error_cnt_;
|
||||
|
||||
// If this wire is actually a memory, these indices will give
|
||||
// me the size and address range of the memory.
|
||||
|
|
@ -106,50 +117,4 @@ class PWire : public LineInfo {
|
|||
PWire& operator= (const PWire&);
|
||||
};
|
||||
|
||||
/*
|
||||
* $Log: PWire.h,v $
|
||||
* Revision 1.21 2007/05/24 04:07:11 steve
|
||||
* Rework the heirarchical identifier parse syntax and pform
|
||||
* to handle more general combinations of heirarch and bit selects.
|
||||
*
|
||||
* Revision 1.20 2007/04/26 03:06:22 steve
|
||||
* Rework hname_t to use perm_strings.
|
||||
*
|
||||
* Revision 1.19 2006/04/10 00:37:42 steve
|
||||
* Add support for generate loops w/ wires and gates.
|
||||
*
|
||||
* Revision 1.18 2005/07/07 16:22:49 steve
|
||||
* Generalize signals to carry types.
|
||||
*
|
||||
* Revision 1.17 2004/02/20 18:53:33 steve
|
||||
* Addtrbute keys are perm_strings.
|
||||
*
|
||||
* Revision 1.16 2003/01/30 16:23:07 steve
|
||||
* Spelling fixes.
|
||||
*
|
||||
* Revision 1.15 2003/01/26 21:15:58 steve
|
||||
* Rework expression parsing and elaboration to
|
||||
* accommodate real/realtime values and expressions.
|
||||
*
|
||||
* Revision 1.14 2002/08/12 01:34:58 steve
|
||||
* conditional ident string using autoconfig.
|
||||
*
|
||||
* Revision 1.13 2002/06/21 04:59:35 steve
|
||||
* Carry integerness throughout the compilation.
|
||||
*
|
||||
* Revision 1.12 2002/05/23 03:08:51 steve
|
||||
* Add language support for Verilog-2001 attribute
|
||||
* syntax. Hook this support into existing $attribute
|
||||
* handling, and add number and void value types.
|
||||
*
|
||||
* Add to the ivl_target API new functions for access
|
||||
* of complex attributes attached to gates.
|
||||
*
|
||||
* Revision 1.11 2001/12/03 04:47:14 steve
|
||||
* Parser and pform use hierarchical names as hname_t
|
||||
* objects instead of encoded strings.
|
||||
*
|
||||
* Revision 1.10 2001/01/16 02:44:18 steve
|
||||
* Use the iosfwd header if available.
|
||||
*/
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -112,6 +112,10 @@ inline bool gn_cadence_types_enabled()
|
|||
is false, then skip elaboration of specify behavior. */
|
||||
extern bool gn_specify_blocks_flag;
|
||||
|
||||
/* If this flag is false a warning is printed when the port declaration
|
||||
is scalar and the net/register definition is vectored. */
|
||||
extern bool gn_io_range_error_flag;
|
||||
|
||||
/* This is the string to use to invoke the preprocessor. */
|
||||
extern char*ivlpp_string;
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,8 @@ iverilog - Icarus Verilog compiler
|
|||
|
||||
.SH SYNOPSIS
|
||||
.B iverilog
|
||||
[-ESVv] [-Bpath] [-ccmdfile] [-g1|-g2|-g2x|-gspecify-gxtypes] [-Dmacro[=defn]] [-pflag=value]
|
||||
[-ESVv] [-Bpath] [-ccmdfile] [-Dmacro[=defn]] [-pflag=value]
|
||||
[-g1|-g2|-g2x|-gspecify|-gxtypes|-gio-range-error]
|
||||
[-Iincludedir] [-mmodule] [-Mfile] [-Nfile] [-ooutputfilename]
|
||||
[-stopmodule] [-ttype] [-Tmin/typ/max] [-Wclass] [-ypath] sourcefile
|
||||
|
||||
|
|
@ -72,6 +73,15 @@ Verilog as extensions beyond the baseline Verilog. It may be necessary
|
|||
to disable extended types if compiling code that clashes with the few
|
||||
new keywords used to implement the type system.
|
||||
.TP 8
|
||||
.B -gio-range-error\fI|\fP-gno-io-range-error
|
||||
The standards requires that a vectored port have matching ranges for its
|
||||
port declaration as well as any net/register declaration. It was common
|
||||
practice in the past to only specify the range for the net/register
|
||||
declaration and some tools still allow this. By default any mismatch is
|
||||
reported as a error. Using \fI-gno-io-range-error\fP will produce a
|
||||
warning instead of a fatal error for the case of a vectored net/register
|
||||
and a scalar port declaration.
|
||||
.TP 8
|
||||
.B -I\fIincludedir\fP
|
||||
Append directory \fIincludedir\fP to list of directories searched
|
||||
for Verilog include files. The \fB-I\fP switch may be used many times
|
||||
|
|
|
|||
|
|
@ -110,6 +110,7 @@ const char*depfile = 0;
|
|||
const char*generation = "2x";
|
||||
const char*gen_specify = "specify";
|
||||
const char*gen_xtypes = "xtypes";
|
||||
const char*gen_io_range_error = "io-range-error";
|
||||
|
||||
char warning_flags[16] = "";
|
||||
|
||||
|
|
@ -439,6 +440,12 @@ int process_generation(const char*name)
|
|||
else if (strcmp(name,"no-specify") == 0)
|
||||
gen_specify = "no-specify";
|
||||
|
||||
else if (strcmp(name,"io-range-error") == 0)
|
||||
gen_io_range_error = "io-range-error";
|
||||
|
||||
else if (strcmp(name,"no-io-range-error") == 0)
|
||||
gen_io_range_error = "no-io-range-error";
|
||||
|
||||
else {
|
||||
fprintf(stderr, "Unknown/Unsupported Language generation "
|
||||
"%s\n", name);
|
||||
|
|
@ -448,7 +455,8 @@ int process_generation(const char*name)
|
|||
" 2x -- Verilog with extensions\n"
|
||||
"Other generation flags:\n"
|
||||
" specify | no-specify\n"
|
||||
" xtypes | no-xtypes\n");
|
||||
" xtypes | no-xtypes\n"
|
||||
" io-range-error | no-io-range-error\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
@ -694,6 +702,7 @@ int main(int argc, char **argv)
|
|||
fprintf(iconfig_file, "generation:%s\n", generation);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_specify);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_xtypes);
|
||||
fprintf(iconfig_file, "generation:%s\n", gen_io_range_error);
|
||||
fprintf(iconfig_file, "warnings:%s\n", warning_flags);
|
||||
fprintf(iconfig_file, "out:%s\n", opath);
|
||||
if (depfile) fprintf(iconfig_file, "depfile:%s\n", depfile);
|
||||
|
|
|
|||
146
elab_sig.cc
146
elab_sig.cc
|
|
@ -560,86 +560,118 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
unsigned wid = 1;
|
||||
long lsb = 0, msb = 0;
|
||||
|
||||
assert(msb_.count() == lsb_.count());
|
||||
if (msb_.count()) {
|
||||
svector<long>mnum (msb_.count());
|
||||
svector<long>lnum (msb_.count());
|
||||
/* There may be places where the signal is declared as a
|
||||
scalar. Count those here, for consistency check
|
||||
later. */
|
||||
unsigned count_scalars = 0;
|
||||
des->errors += error_cnt_;
|
||||
|
||||
/* There may be multiple declarations of ranges, because
|
||||
the symbol may have its range declared in e.g., input
|
||||
and reg declarations. Calculate *all* the numbers
|
||||
here. I will resolve the values later. */
|
||||
if (port_set_ || net_set_) {
|
||||
long pmsb = 0, plsb = 0, nmsb = 0, nlsb = 0;
|
||||
/* If they exist get the port definition MSB and LSB */
|
||||
if (port_set_ && port_msb_ != 0) {
|
||||
NetExpr*texpr = elab_and_eval(des, scope, port_msb_, -1);
|
||||
|
||||
for (unsigned idx = 0 ; idx < msb_.count() ; idx += 1) {
|
||||
|
||||
if (msb_[idx] == 0) {
|
||||
count_scalars += 1;
|
||||
assert(lsb_[idx] == 0);
|
||||
mnum[idx] = 0;
|
||||
lnum[idx] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
NetExpr*texpr = elab_and_eval(des, scope, msb_[idx], -1);
|
||||
|
||||
if (! eval_as_long(mnum[idx], texpr)) {
|
||||
cerr << msb_[idx]->get_line() << ": error: "
|
||||
"Unable to evaluate constant expression ``" <<
|
||||
*msb_[idx] << "''." << endl;
|
||||
if (! eval_as_long(pmsb, texpr)) {
|
||||
cerr << port_msb_->get_line() << ": error: "
|
||||
"Unable to evaluate MSB constant expression ``"
|
||||
<< *port_msb_ << "''." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
|
||||
texpr = elab_and_eval(des, scope, lsb_[idx], -1);
|
||||
texpr = elab_and_eval(des, scope, port_lsb_, -1);
|
||||
|
||||
if (! eval_as_long(lnum[idx], texpr) ) {
|
||||
cerr << msb_[idx]->get_line() << ": error: "
|
||||
"Unable to evaluate constant expression ``" <<
|
||||
*lsb_[idx] << "''." << endl;
|
||||
if (! eval_as_long(plsb, texpr)) {
|
||||
cerr << port_lsb_->get_line() << ": error: "
|
||||
"Unable to evaluate LSB constant expression ``"
|
||||
<< *port_lsb_ << "''." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
nmsb = pmsb;
|
||||
nlsb = plsb;
|
||||
}
|
||||
if (port_msb_ == 0) assert(port_lsb_ == 0);
|
||||
|
||||
/* If they exist get the net/etc. definition MSB and LSB */
|
||||
if (net_set_ && net_msb_ != 0) {
|
||||
NetExpr*texpr = elab_and_eval(des, scope, net_msb_, -1);
|
||||
|
||||
if (! eval_as_long(nmsb, texpr)) {
|
||||
cerr << net_msb_->get_line() << ": error: "
|
||||
"Unable to evaluate MSB constant expression ``"
|
||||
<< *net_msb_ << "''." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
|
||||
texpr = elab_and_eval(des, scope, net_lsb_, -1);
|
||||
|
||||
if (! eval_as_long(nlsb, texpr)) {
|
||||
cerr << net_lsb_->get_line() << ": error: "
|
||||
"Unable to evaluate LSB constant expression ``"
|
||||
<< *net_lsb_ << "''." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
delete texpr;
|
||||
}
|
||||
if (net_msb_ == 0) assert(net_lsb_ == 0);
|
||||
|
||||
/* Check that the declarations were all scalar or all
|
||||
vector. It is an error to mix them. Use the
|
||||
count_scalars to know. */
|
||||
if ((count_scalars > 0) && (count_scalars != msb_.count())) {
|
||||
cerr << get_line() << ": error: Signal ``" << hname_
|
||||
<< "'' declared both as a vector and a scalar."
|
||||
<< endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
/* We have a port size error */
|
||||
if (port_set_ && net_set_ && (pmsb != nmsb || plsb != nlsb)) {
|
||||
|
||||
/* Scalar port with a vector net/etc. definition */
|
||||
if (port_msb_ == 0) {
|
||||
if (!gn_io_range_error_flag) {
|
||||
cerr << get_line()
|
||||
<< ": warning: Scalar port ``" << hname_
|
||||
<< "'' has a vectored net declaration ["
|
||||
<< nmsb << ":" << nlsb << "]." << endl;
|
||||
} else {
|
||||
cerr << get_line()
|
||||
<< ": error: Scalar port ``" << hname_
|
||||
<< "'' has a vectored net declaration ["
|
||||
<< nmsb << ":" << nlsb << "]." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Make sure all the values for msb and lsb match by
|
||||
value. If not, report an error. */
|
||||
for (unsigned idx = 1 ; idx < msb_.count() ; idx += 1) {
|
||||
if ((mnum[idx] != mnum[0]) || (lnum[idx] != lnum[0])) {
|
||||
cerr << get_line() << ": error: Inconsistent width, "
|
||||
"[" << mnum[idx] << ":" << lnum[idx] << "]"
|
||||
" vs. [" << mnum[0] << ":" << lnum[0] << "]"
|
||||
" for signal ``" << hname_ << "''" << endl;
|
||||
/* Vectored port with a scalar net/etc. definition */
|
||||
if (net_msb_ == 0) {
|
||||
cerr << port_msb_->get_line()
|
||||
<< ": error: Vectored port ``"
|
||||
<< hname_ << "'' [" << pmsb << ":" << plsb
|
||||
<< "] has a scalar net declaration at "
|
||||
<< get_line() << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
lsb = lnum[0];
|
||||
msb = mnum[0];
|
||||
if (mnum[0] > lnum[0])
|
||||
wid = mnum[0] - lnum[0] + 1;
|
||||
/* Both vectored, but they have different ranges. */
|
||||
if (port_msb_ != 0 && net_msb_ != 0) {
|
||||
cerr << port_msb_->get_line()
|
||||
<< ": error: Vectored port ``"
|
||||
<< hname_ << "'' [" << pmsb << ":" << plsb
|
||||
<< "] has a net declaration [" << nmsb << ":"
|
||||
<< nlsb << "] at " << net_msb_->get_line()
|
||||
<< " that does not match." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
lsb = nlsb;
|
||||
msb = nmsb;
|
||||
if (nmsb > nlsb)
|
||||
wid = nmsb - nlsb + 1;
|
||||
else
|
||||
wid = lnum[0] - mnum[0] + 1;
|
||||
wid = nlsb - nmsb + 1;
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
7
main.cc
7
main.cc
|
|
@ -89,6 +89,7 @@ const char*target = "null";
|
|||
generation_t generation_flag = GN_DEFAULT;
|
||||
bool gn_cadence_types_flag = true;
|
||||
bool gn_specify_blocks_flag = true;
|
||||
bool gn_io_range_error_flag = true;
|
||||
|
||||
map<string,const char*> flags;
|
||||
char*vpi_module_list = 0;
|
||||
|
|
@ -211,6 +212,12 @@ static void process_generation_flag(const char*gen)
|
|||
} else if (strcmp(gen,"no-specify") == 0) {
|
||||
gn_specify_blocks_flag = false;
|
||||
|
||||
} else if (strcmp(gen,"io-range-error") == 0) {
|
||||
gn_io_range_error_flag = true;
|
||||
|
||||
} else if (strcmp(gen,"no-io-range-error") == 0) {
|
||||
gn_io_range_error_flag = false;
|
||||
|
||||
} else {
|
||||
}
|
||||
}
|
||||
|
|
|
|||
11
parse.y
11
parse.y
|
|
@ -1411,12 +1411,14 @@ list_of_port_declarations
|
|||
{ svector<Module::port_t*>*tmp
|
||||
= new svector<Module::port_t*>(1);
|
||||
(*tmp)[0] = $1;
|
||||
pform_set_net_range($1[0].name);
|
||||
$$ = tmp;
|
||||
}
|
||||
| list_of_port_declarations ',' port_declaration
|
||||
{ svector<Module::port_t*>*tmp
|
||||
= new svector<Module::port_t*>(*$1, $3);
|
||||
delete $1;
|
||||
pform_set_net_range($3[0].name);
|
||||
$$ = tmp;
|
||||
}
|
||||
| list_of_port_declarations ',' IDENTIFIER
|
||||
|
|
@ -1435,6 +1437,7 @@ list_of_port_declarations
|
|||
port_declaration_context.sign_flag,
|
||||
port_declaration_context.range, 0);
|
||||
delete $1;
|
||||
pform_set_net_range($3);
|
||||
$$ = tmp;
|
||||
}
|
||||
;
|
||||
|
|
@ -1694,13 +1697,13 @@ module_item
|
|||
This creates the wire and sets the port type all at once. */
|
||||
|
||||
| port_type net_type signed_opt range_opt list_of_identifiers ';'
|
||||
{ pform_makewire(@1, $4, $3, $5, $2, $1, IVL_VT_NO_TYPE, 0);
|
||||
{ pform_makewire(@1, $4, $3, $5, $2, $1, IVL_VT_NO_TYPE, 0,
|
||||
SR_BOTH);
|
||||
}
|
||||
|
||||
| K_output var_type signed_opt range_opt list_of_identifiers ';'
|
||||
{ pform_makewire(@1, $4, $3, $5, $2,
|
||||
NetNet::POUTPUT,
|
||||
IVL_VT_NO_TYPE, 0);
|
||||
{ pform_makewire(@1, $4, $3, $5, $2, NetNet::POUTPUT,
|
||||
IVL_VT_NO_TYPE, 0, SR_BOTH);
|
||||
}
|
||||
|
||||
/* var_type declaration (reg variables) cannot be input or output,
|
||||
|
|
|
|||
62
pform.cc
62
pform.cc
|
|
@ -828,6 +828,21 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
|
|||
delete init_expr;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function is used to set the net range for a port that uses
|
||||
* the new (1364-2001) list_of_port_declarations, but omitted a
|
||||
* register/wire/etc. that would have triggered it to be set elsewhere.
|
||||
*/
|
||||
void pform_set_net_range(const char* name)
|
||||
{
|
||||
PWire*cur = get_wire_in_module(hier_name(name));
|
||||
if (cur == 0) {
|
||||
VLerror("error: name is not a valid net.");
|
||||
return;
|
||||
}
|
||||
cur->set_net_range();
|
||||
}
|
||||
|
||||
/*
|
||||
* This function attaches a range to a given name. The function is
|
||||
* only called by the parser within the scope of the net declaration,
|
||||
|
|
@ -836,7 +851,8 @@ void pform_make_udp(perm_string name, bool synchronous_flag,
|
|||
static void pform_set_net_range(const char* name,
|
||||
const svector<PExpr*>*range,
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t dt)
|
||||
ivl_variable_type_t dt,
|
||||
PWSRType rt)
|
||||
{
|
||||
PWire*cur = get_wire_in_module(hier_name(name));
|
||||
if (cur == 0) {
|
||||
|
|
@ -847,13 +863,13 @@ static void pform_set_net_range(const char* name,
|
|||
if (range == 0) {
|
||||
/* This is the special case that we really mean a
|
||||
scalar. Set a fake range. */
|
||||
cur->set_range(0, 0);
|
||||
cur->set_range(0, 0, rt);
|
||||
|
||||
} else {
|
||||
assert(range->count() == 2);
|
||||
assert((*range)[0]);
|
||||
assert((*range)[1]);
|
||||
cur->set_range((*range)[0], (*range)[1]);
|
||||
cur->set_range((*range)[0], (*range)[1], rt);
|
||||
}
|
||||
cur->set_signed(signed_flag);
|
||||
|
||||
|
|
@ -864,7 +880,8 @@ static void pform_set_net_range(const char* name,
|
|||
void pform_set_net_range(list<perm_string>*names,
|
||||
svector<PExpr*>*range,
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t dt)
|
||||
ivl_variable_type_t dt,
|
||||
PWSRType rt)
|
||||
{
|
||||
assert((range == 0) || (range->count() == 2));
|
||||
|
||||
|
|
@ -872,7 +889,7 @@ void pform_set_net_range(list<perm_string>*names,
|
|||
; cur != names->end()
|
||||
; cur ++ ) {
|
||||
perm_string txt = *cur;
|
||||
pform_set_net_range(txt, range, signed_flag, dt);
|
||||
pform_set_net_range(txt, range, signed_flag, dt, rt);
|
||||
}
|
||||
|
||||
delete names;
|
||||
|
|
@ -1217,13 +1234,15 @@ void pform_module_define_port(const struct vlltype&li,
|
|||
cur->set_signed(signed_flag);
|
||||
|
||||
if (range == 0) {
|
||||
cur->set_range(0, 0);
|
||||
cur->set_range(0, 0, (type == NetNet::IMPLICIT) ? SR_PORT :
|
||||
SR_BOTH);
|
||||
|
||||
} else {
|
||||
assert(range->count() == 2);
|
||||
assert((*range)[0]);
|
||||
assert((*range)[1]);
|
||||
cur->set_range((*range)[0], (*range)[1]);
|
||||
cur->set_range((*range)[0], (*range)[1],
|
||||
(type == NetNet::IMPLICIT) ? SR_PORT : SR_BOTH);
|
||||
}
|
||||
|
||||
if (attr) {
|
||||
|
|
@ -1296,7 +1315,7 @@ void pform_makewire(const vlltype&li, const char*nm,
|
|||
switch (dt) {
|
||||
case IVL_VT_REAL:
|
||||
cur->set_data_type(dt);
|
||||
cur->set_range(0, 0);
|
||||
cur->set_range(0, 0, SR_NET);
|
||||
cur->set_signed(true);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -1320,7 +1339,7 @@ void pform_makewire(const vlltype&li, const char*nm,
|
|||
|
||||
/*
|
||||
* This form takes a list of names and some type information, and
|
||||
* generates a bunch of variables/nets. We hse the basic
|
||||
* generates a bunch of variables/nets. We use the basic
|
||||
* pform_makewire above.
|
||||
*/
|
||||
void pform_makewire(const vlltype&li,
|
||||
|
|
@ -1330,14 +1349,18 @@ void pform_makewire(const vlltype&li,
|
|||
NetNet::Type type,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt,
|
||||
svector<named_pexpr_t*>*attr)
|
||||
svector<named_pexpr_t*>*attr,
|
||||
PWSRType rt)
|
||||
{
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end()
|
||||
; cur ++ ) {
|
||||
perm_string txt = *cur;
|
||||
pform_makewire(li, txt, type, pt, dt, attr);
|
||||
pform_set_net_range(txt, range, signed_flag, dt);
|
||||
/* This has already been done for real variables. */
|
||||
if (dt != IVL_VT_REAL) {
|
||||
pform_set_net_range(txt, range, signed_flag, dt, rt);
|
||||
}
|
||||
}
|
||||
|
||||
delete names;
|
||||
|
|
@ -1364,7 +1387,11 @@ void pform_makewire(const vlltype&li,
|
|||
net_decl_assign_t*next = first->next;
|
||||
|
||||
pform_makewire(li, first->name, type, NetNet::NOT_A_PORT, dt, 0);
|
||||
pform_set_net_range(first->name, range, signed_flag, dt);
|
||||
/* This has already been done for real variables. */
|
||||
if (dt != IVL_VT_REAL) {
|
||||
pform_set_net_range(first->name, range, signed_flag, dt,
|
||||
SR_NET);
|
||||
}
|
||||
|
||||
perm_string first_name = lex_strings.make(first->name);
|
||||
pform_name_t name = hier_name(first_name);
|
||||
|
|
@ -1491,7 +1518,7 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
|||
|
||||
/* If there is a range involved, it needs to be set. */
|
||||
if (range)
|
||||
curw->set_range((*range)[0], (*range)[1]);
|
||||
curw->set_range((*range)[0], (*range)[1], SR_PORT);
|
||||
|
||||
svector<PWire*>*tmp = new svector<PWire*>(*res, curw);
|
||||
|
||||
|
|
@ -1694,7 +1721,8 @@ void pform_set_port_type(const struct vlltype&li,
|
|||
; cur ++ ) {
|
||||
perm_string txt = *cur;
|
||||
pform_set_port_type(txt, pt, li.text, li.first_line);
|
||||
pform_set_net_range(txt, range, signed_flag, IVL_VT_NO_TYPE);
|
||||
pform_set_net_range(txt, range, signed_flag, IVL_VT_NO_TYPE,
|
||||
SR_PORT);
|
||||
}
|
||||
|
||||
delete names;
|
||||
|
|
@ -1721,7 +1749,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)));
|
||||
new PENumber(new verinum((uint64_t)0, integer_width)),
|
||||
SR_NET);
|
||||
cur->set_signed(true);
|
||||
}
|
||||
|
||||
|
|
@ -1752,7 +1781,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)));
|
||||
new PENumber(new verinum((uint64_t)0, integer_width)),
|
||||
SR_NET);
|
||||
}
|
||||
|
||||
void pform_set_reg_time(list<perm_string>*names)
|
||||
|
|
|
|||
7
pform.h
7
pform.h
|
|
@ -210,7 +210,8 @@ extern void pform_makewire(const struct vlltype&li,
|
|||
NetNet::Type type,
|
||||
NetNet::PortType,
|
||||
ivl_variable_type_t,
|
||||
svector<named_pexpr_t*>*attr);
|
||||
svector<named_pexpr_t*>*attr,
|
||||
PWSRType rt = SR_NET);
|
||||
|
||||
/* This form handles assignment declarations. */
|
||||
extern void pform_makewire(const struct vlltype&li,
|
||||
|
|
@ -236,10 +237,12 @@ extern void pform_set_port_type(const struct vlltype&li,
|
|||
extern void pform_set_port_type(perm_string nm, NetNet::PortType pt,
|
||||
const char*file, unsigned lineno);
|
||||
|
||||
extern void pform_set_net_range(const char* name);
|
||||
extern void pform_set_net_range(list<perm_string>*names,
|
||||
svector<PExpr*>*,
|
||||
bool signed_flag,
|
||||
ivl_variable_type_t);
|
||||
ivl_variable_type_t,
|
||||
PWSRType rt = SR_NET);
|
||||
extern void pform_set_reg_idx(const char*name, PExpr*l, PExpr*r);
|
||||
extern void pform_set_reg_integer(list<perm_string>*names);
|
||||
extern void pform_set_reg_time(list<perm_string>*names);
|
||||
|
|
|
|||
|
|
@ -281,18 +281,18 @@ void PWire::dump(ostream&out, unsigned ind) const
|
|||
out << " signed";
|
||||
}
|
||||
|
||||
assert(msb_.count() == lsb_.count());
|
||||
for (unsigned idx = 0 ; idx < msb_.count() ; idx += 1) {
|
||||
|
||||
if (msb_[idx] == 0) {
|
||||
assert(lsb_[idx] == 0);
|
||||
out << " <scalar>";
|
||||
|
||||
if (port_set_) {
|
||||
if (port_msb_ == 0) {
|
||||
out << " port<scalar>";
|
||||
} else {
|
||||
if (lsb_[idx])
|
||||
out << " [" << *msb_[idx] << ":" << *lsb_[idx] << "]";
|
||||
else
|
||||
out << " [" << *msb_[idx] << "]";
|
||||
out << " port[" << *port_msb_ << ":" << *port_lsb_ << "]";
|
||||
}
|
||||
}
|
||||
if (net_set_) {
|
||||
if (net_msb_ == 0) {
|
||||
out << " net<scalar>";
|
||||
} else {
|
||||
out << " net[" << *net_msb_ << ":" << *net_lsb_ << "]";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue