Prevent invalid port redeclaration
(System)Verilog allows to declare the port direction separate from the signal declaration. E.g. ``` output x; integer x; ``` But this is only allowed if the port declaration * does not have an explicit net type * does not have an explicit data type * is a non-ANSI style declaration For all other cases of port declarations the signal is considered fully defined and it is not allowed to have a separate signal declaration. In addition the declared packed dimensions need to match between the port and signal declaration. In the current implementation there are a few cases where this is not handled correctly. 1) It is possible to declare non-ANSI task ports with the same name over and over again, if it was declared as a signal before the port. ``` task t; string x; input logic x; output real x; endtask ``` 2) It is possible to re-declare non-ANSI input ports of a module that have a data type, but no explicit net type. ``` module M; input integer x; wire integer x; endmodule ``` 3) It is possible to re-declare a ANSI port if it has an implicit data type. ``` module M(output [1:0] x); reg [1:0] x; endmodule ``` 4) It is possible to declare a vector signal for a scalar non-ANSI task port. ``` task t; input x; reg [7:0] x; ``` To handle all of these correctly refactor signal declaration and lookup a bit. The PWire class that represents a signal already has two flags `port_set_` and `net_set_`. These flags indicate whether a signal has already been used in a port or signal declaration. A port declaration that includes an explicit data type is considered both a port and signal declaration. Use these flags to decide whether it is possible to extend an existing declaration. E.g. when creating a port without an explicit data type and a PWire by that name already exists and the `port_set_` flag is not set extend the existing PWire. On the other hand if the `port_set_` flag is already set report an error. Similar for signals but with the `net_set_` flag. For port declarations with an explicit data type or ANSI style port declarations it is always an error if a PWire by that name already exists. This is for both module and task/function ports. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
parent
7fbfd82d51
commit
6204b78610
1
PExpr.cc
1
PExpr.cc
|
|
@ -436,7 +436,6 @@ void PEIdent::declare_implicit_nets(LexicalScope*scope, NetNet::Type type)
|
|||
PWire*net = new PWire(name, type, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
|
||||
net->set_file(get_file());
|
||||
net->set_lineno(get_lineno());
|
||||
net->set_range_scalar(SR_NET);
|
||||
scope->wires[name] = net;
|
||||
if (warn_implicit) {
|
||||
cerr << get_fileline() << ": warning: implicit "
|
||||
|
|
|
|||
122
PWire.cc
122
PWire.cc
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
# include "config.h"
|
||||
# include "ivl_assert.h"
|
||||
# include "PWire.h"
|
||||
# include "PExpr.h"
|
||||
# include <cassert>
|
||||
|
|
@ -27,13 +28,26 @@ using namespace std;
|
|||
PWire::PWire(perm_string n,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt)
|
||||
ivl_variable_type_t dt,
|
||||
PWSRType rt)
|
||||
: name_(n), type_(t), port_type_(pt), data_type_(dt),
|
||||
signed_(false),
|
||||
port_set_(false), net_set_(false), is_scalar_(false),
|
||||
error_cnt_(0), uarray_type_(0), set_data_type_(0),
|
||||
discipline_(0)
|
||||
{
|
||||
switch (rt) {
|
||||
case SR_PORT:
|
||||
port_set_ = true;
|
||||
break;
|
||||
case SR_NET:
|
||||
net_set_ = true;
|
||||
break;
|
||||
case SR_BOTH:
|
||||
port_set_ = true;
|
||||
net_set_ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
NetNet::Type PWire::get_wire_type() const
|
||||
|
|
@ -132,47 +146,23 @@ bool PWire::get_signed() const
|
|||
return signed_;
|
||||
}
|
||||
|
||||
void PWire::set_range_scalar(PWSRType type)
|
||||
void PWire::set_port(NetNet::PortType pt)
|
||||
{
|
||||
is_scalar_ = true;
|
||||
switch (type) {
|
||||
case SR_PORT:
|
||||
if (port_set_) {
|
||||
cerr << get_fileline() << ": error: Port ``" << name_
|
||||
<< "'' has already been declared a port." << endl;
|
||||
error_cnt_ += 1;
|
||||
} else {
|
||||
port_set_ = true;
|
||||
}
|
||||
return;
|
||||
ivl_assert(*this, !port_set_);
|
||||
port_set_ = true;
|
||||
|
||||
case SR_NET:
|
||||
if (net_set_) {
|
||||
cerr << get_fileline() << ": error: Net ``" << name_
|
||||
<< "'' has already been declared." << endl;
|
||||
error_cnt_ += 1;
|
||||
} else {
|
||||
net_set_ = true;
|
||||
}
|
||||
return;
|
||||
bool rc = set_port_type(pt);
|
||||
ivl_assert(*this, rc);
|
||||
}
|
||||
|
||||
case SR_BOTH:
|
||||
if (port_set_ || net_set_) {
|
||||
if (port_set_) {
|
||||
cerr << get_fileline() << ": error: Port ``" << name_
|
||||
<< "'' has already been declared a port." << endl;
|
||||
error_cnt_ += 1;
|
||||
}
|
||||
if (net_set_) {
|
||||
cerr << get_fileline() << ": error: Net ``" << name_
|
||||
<< "'' has already been declared." << endl;
|
||||
error_cnt_ += 1;
|
||||
}
|
||||
} else {
|
||||
port_set_ = true;
|
||||
net_set_ = true;
|
||||
}
|
||||
return;
|
||||
void PWire::set_net(NetNet::Type t)
|
||||
{
|
||||
ivl_assert(*this, !net_set_);
|
||||
net_set_ = true;
|
||||
|
||||
if (t != NetNet::IMPLICIT) {
|
||||
bool rc = set_wire_type(t);
|
||||
ivl_assert(*this, rc);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -180,49 +170,21 @@ void PWire::set_range(const list<pform_range_t>&rlist, PWSRType type)
|
|||
{
|
||||
switch (type) {
|
||||
case SR_PORT:
|
||||
if (port_set_) {
|
||||
cerr << get_fileline() << ": error: Port ``" << name_
|
||||
<< "'' has already been declared a port." << endl;
|
||||
error_cnt_ += 1;
|
||||
} else {
|
||||
port_ = rlist;
|
||||
port_set_ = true;
|
||||
is_scalar_ = false;
|
||||
}
|
||||
return;
|
||||
|
||||
if (!port_.empty())
|
||||
return;
|
||||
port_ = rlist;
|
||||
break;
|
||||
case SR_NET:
|
||||
if (net_set_) {
|
||||
cerr << get_fileline() << ": error: Net ``" << name_
|
||||
<< "'' has already been declared." << endl;
|
||||
error_cnt_ += 1;
|
||||
} else {
|
||||
net_ = rlist;
|
||||
net_set_ = true;
|
||||
is_scalar_ = false;
|
||||
}
|
||||
return;
|
||||
|
||||
if (!net_.empty())
|
||||
return;
|
||||
net_ = rlist;
|
||||
break;
|
||||
case SR_BOTH:
|
||||
if (port_set_ || net_set_) {
|
||||
if (port_set_) {
|
||||
cerr << get_fileline() << ": error: Port ``" << name_
|
||||
<< "'' has already been declared a port." << endl;
|
||||
error_cnt_ += 1;
|
||||
}
|
||||
if (net_set_) {
|
||||
cerr << get_fileline() << ": error: Net ``" << name_
|
||||
<< "'' has already been declared." << endl;
|
||||
error_cnt_ += 1;
|
||||
}
|
||||
} else {
|
||||
port_ = rlist;
|
||||
port_set_ = true;
|
||||
net_ = rlist;
|
||||
net_set_ = true;
|
||||
is_scalar_ = false;
|
||||
}
|
||||
return;
|
||||
if (!port_.empty() || !net_.empty())
|
||||
return;
|
||||
port_ = rlist;
|
||||
net_ = rlist;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
9
PWire.h
9
PWire.h
|
|
@ -57,7 +57,8 @@ class PWire : public PNamedItem {
|
|||
PWire(perm_string name,
|
||||
NetNet::Type t,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t dt);
|
||||
ivl_variable_type_t dt,
|
||||
PWSRType rt = SR_NET);
|
||||
|
||||
// Return a hierarchical name.
|
||||
perm_string basename() const;
|
||||
|
|
@ -74,7 +75,6 @@ class PWire : public PNamedItem {
|
|||
bool set_data_type(ivl_variable_type_t dt);
|
||||
ivl_variable_type_t get_data_type() const;
|
||||
|
||||
void set_range_scalar(PWSRType type);
|
||||
void set_range(const std::list<pform_range_t>&ranges, PWSRType type);
|
||||
|
||||
void set_unpacked_idx(const std::list<pform_range_t>&ranges);
|
||||
|
|
@ -94,6 +94,11 @@ class PWire : public PNamedItem {
|
|||
|
||||
SymbolType symbol_type() const;
|
||||
|
||||
bool is_net() const { return net_set_; };
|
||||
bool is_port() const { return port_set_; };
|
||||
void set_net(NetNet::Type t);
|
||||
void set_port(NetNet::PortType pt);
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
NetNet::Type type_;
|
||||
|
|
|
|||
22
elab_sig.cc
22
elab_sig.cc
|
|
@ -1040,8 +1040,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
<< "Evaluate ranges for port " << basename() << endl;
|
||||
}
|
||||
dimensions_ok &= evaluate_ranges(des, scope, this, plist, port_);
|
||||
nlist = plist;
|
||||
/* An implicit port can have a range so note that here. */
|
||||
}
|
||||
assert(port_set_ || port_.empty());
|
||||
|
||||
|
|
@ -1062,9 +1060,10 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
<< ". Now check for consistency." << endl;
|
||||
}
|
||||
|
||||
/* We have a port size error */
|
||||
if (port_set_ && net_set_ && !test_ranges_eeq(plist, nlist)) {
|
||||
|
||||
/* We have a port size error. Skip this if the dimensions could not
|
||||
* be evaluated since it will likely print nonsensical errors. */
|
||||
if (port_set_ && net_set_ && !test_ranges_eeq(plist, nlist) &&
|
||||
dimensions_ok) {
|
||||
/* Scalar port with a vector net/etc. definition */
|
||||
if (port_.empty()) {
|
||||
if (!gn_io_range_error_flag) {
|
||||
|
|
@ -1103,7 +1102,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
}
|
||||
}
|
||||
|
||||
packed_dimensions = nlist;
|
||||
packed_dimensions = net_set_ ? nlist : plist;
|
||||
wid = netrange_width(packed_dimensions);
|
||||
if (wid > warn_dimension_size) {
|
||||
cerr << get_fileline() << ": warning: Vector size "
|
||||
|
|
@ -1116,17 +1115,6 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
|||
attrib_list_t*attrib_list = evaluate_attributes(attributes, nattrib,
|
||||
des, scope);
|
||||
|
||||
if (data_type_ == IVL_VT_REAL && !packed_dimensions.empty()) {
|
||||
cerr << get_fileline() << ": error: real ";
|
||||
if (wtype == NetNet::REG) cerr << "variable";
|
||||
else cerr << "net";
|
||||
cerr << " '" << name_
|
||||
<< "' cannot be declared as a vector, found a range "
|
||||
<< packed_dimensions << "." << endl;
|
||||
des->errors += 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 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:
|
||||
|
|
|
|||
|
|
@ -1,23 +1,23 @@
|
|||
./ivltests/pr1723367.v:131: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:138: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:132: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:140: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:141: warning: Scalar port ``b'' has a vectored net declaration [15:0].
|
||||
./ivltests/pr1723367.v:148: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:156: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:167: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:174: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:149: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:157: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:168: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:176: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:177: warning: Scalar port ``b'' has a vectored net declaration [15:0].
|
||||
./ivltests/pr1723367.v:184: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:192: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:203: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:212: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:185: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:193: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:204: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:214: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:215: warning: Scalar port ``b'' has a vectored net declaration [31:0].
|
||||
./ivltests/pr1723367.v:246: warning: Scalar port ``a'' has a vectored net declaration [15:0].
|
||||
./ivltests/pr1723367.v:253: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:247: warning: Scalar port ``a'' has a vectored net declaration [15:0].
|
||||
./ivltests/pr1723367.v:255: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:256: warning: Scalar port ``b'' has a vectored net declaration [31:0].
|
||||
./ivltests/pr1723367.v:282: warning: Scalar port ``a'' has a vectored net declaration [15:0].
|
||||
./ivltests/pr1723367.v:289: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:283: warning: Scalar port ``a'' has a vectored net declaration [15:0].
|
||||
./ivltests/pr1723367.v:291: warning: Scalar port ``a'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1723367.v:292: warning: Scalar port ``b'' has a vectored net declaration [15:0].
|
||||
./ivltests/pr1723367.v:307: warning: Scalar port ``a'' has a vectored net declaration [15:0].
|
||||
./ivltests/pr1723367.v:308: warning: Scalar port ``a'' has a vectored net declaration [15:0].
|
||||
sum[ 1] = 0101010101100000
|
||||
sum[ 2] = 0101010101100000
|
||||
sum[ 3] = 0101010101100000
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
./ivltests/pr1841300.v:15: warning: Scalar port ``l'' has a vectored net declaration [4:0].
|
||||
a is '14'; b is 'fffffff4'; c is 'fffffff4'
|
||||
|
|
|
|||
|
|
@ -1 +1,8 @@
|
|||
./ivltests/pr1960619.v:26: warning: Scalar port ``l'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1960619.v:26: warning: Scalar port ``r'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1960619.v:14: warning: Scalar port ``l'' has a vectored net declaration [4:0].
|
||||
./ivltests/pr1960619.v:32: warning: Scalar port ``l'' has a vectored net declaration [31:0].
|
||||
./ivltests/pr1960619.v:47: warning: Scalar port ``l'' has a vectored net declaration [31:0].
|
||||
./ivltests/pr1960619.v:20: warning: Scalar port ``l'' has a vectored net declaration [7:0].
|
||||
./ivltests/pr1960619.v:20: warning: Scalar port ``r'' has a vectored net declaration [7:0].
|
||||
a is 14; b is fffffff4; c is 14; d is fffffff4
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
./ivltests/pr2001162.v:36: warning: Scalar port ``l'' has a vectored net declaration [31:0].
|
||||
./ivltests/pr2001162.v:36: warning: Scalar port ``r'' has a vectored net declaration [31:0].
|
||||
test2 increment; reading counter as 0
|
||||
test1 increment; reading counter as 1
|
||||
test2 increment; reading counter as 2
|
||||
|
|
|
|||
218
pform.cc
218
pform.cc
|
|
@ -2148,13 +2148,8 @@ static void pform_set_net_range(PWire *wire,
|
|||
PWSRType rt = SR_NET,
|
||||
std::list<named_pexpr_t>*attr = 0)
|
||||
{
|
||||
if (range == 0) {
|
||||
/* This is the special case that we really mean a
|
||||
scalar. Set a fake range. */
|
||||
wire->set_range_scalar(rt);
|
||||
} else {
|
||||
if (range)
|
||||
wire->set_range(*range, rt);
|
||||
}
|
||||
wire->set_signed(signed_flag);
|
||||
|
||||
pform_bind_attributes(wire->attributes, attr, true);
|
||||
|
|
@ -2515,6 +2510,68 @@ void pform_make_var_init(const struct vlltype&li,
|
|||
lexical_scope->var_inits.push_back(ass);
|
||||
}
|
||||
|
||||
/*
|
||||
* This function makes a single signal (a wire, a reg, etc) as
|
||||
* requested by the parser. The name is unscoped, so I attach the
|
||||
* current scope to it (with the scoped_name function) and I try to
|
||||
* resolve it with an existing PWire in the scope.
|
||||
*
|
||||
* The wire might already exist because of an implicit declaration in
|
||||
* a module port, i.e.:
|
||||
*
|
||||
* module foo (bar...
|
||||
*
|
||||
* reg bar;
|
||||
*
|
||||
* The output (or other port direction indicator) may or may not have
|
||||
* been seen already, so I do not do any checking with it yet. But I
|
||||
* do check to see if the name has already been declared, as this
|
||||
* function is called for every declaration.
|
||||
*/
|
||||
|
||||
|
||||
static PWire* pform_get_or_make_wire(const struct vlltype&li, perm_string name,
|
||||
NetNet::Type type, NetNet::PortType ptype,
|
||||
ivl_variable_type_t dtype, PWSRType rt)
|
||||
{
|
||||
PWire *cur = 0;
|
||||
|
||||
// If this is not a full declaration check if there is already a signal
|
||||
// with the same name that can be extended.
|
||||
if (rt != SR_BOTH)
|
||||
cur = pform_get_wire_in_scope(name);
|
||||
|
||||
// If the wire already exists but isn't yet fully defined,
|
||||
// carry on adding details.
|
||||
if (rt == SR_NET && cur && !cur->is_net()) {
|
||||
// At the moment there can only be one location for the PWire, if
|
||||
// there is both a port and signal declaration use the location of
|
||||
// the signal.
|
||||
FILE_NAME(cur, li);
|
||||
cur->set_net(type);
|
||||
return cur;
|
||||
}
|
||||
|
||||
if (rt == SR_PORT && cur && !cur->is_port()) {
|
||||
cur->set_port(ptype);
|
||||
return cur;
|
||||
}
|
||||
|
||||
// If the wire already exists and is fully defined, this
|
||||
// must be a redeclaration. Start again with a new wire.
|
||||
// The error will be reported when we add the new wire
|
||||
// to the scope. Do not delete the old wire - it will
|
||||
// remain in the local symbol map.
|
||||
|
||||
cur = new PWire(name, type, ptype, dtype, rt);
|
||||
FILE_NAME(cur, li);
|
||||
|
||||
pform_put_wire_in_scope(name, cur);
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* This function is used by the parser when I have port definition of
|
||||
* the form like this:
|
||||
|
|
@ -2536,16 +2593,6 @@ void pform_module_define_port(const struct vlltype&li,
|
|||
ivl_variable_type_t data_type = IVL_VT_NO_TYPE;
|
||||
bool signed_flag = false;
|
||||
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
if (cur) {
|
||||
ostringstream msg;
|
||||
msg << name << " definition conflicts with "
|
||||
<< "definition at " << cur->get_fileline()
|
||||
<< ".";
|
||||
VLerror(msg.str().c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
pform_check_net_data_type(li, type, vtype);
|
||||
|
||||
// Packed ranges
|
||||
|
|
@ -2583,27 +2630,22 @@ void pform_module_define_port(const struct vlltype&li,
|
|||
if (data_type == IVL_VT_NO_TYPE)
|
||||
data_type = IVL_VT_LOGIC;
|
||||
|
||||
cur = new PWire(name, type, port_kind, data_type);
|
||||
FILE_NAME(cur, li);
|
||||
PWire *cur = pform_get_or_make_wire(li, name, type, port_kind, data_type,
|
||||
SR_BOTH);
|
||||
|
||||
cur->set_signed(signed_flag);
|
||||
|
||||
if (vtype)
|
||||
cur->set_data_type(vtype);
|
||||
|
||||
if (prange == 0) {
|
||||
cur->set_range_scalar((type == NetNet::IMPLICIT) ? SR_PORT : SR_BOTH);
|
||||
|
||||
} else {
|
||||
cur->set_range(*prange, (type == NetNet::IMPLICIT) ? SR_PORT : SR_BOTH);
|
||||
}
|
||||
if (prange)
|
||||
cur->set_range(*prange, SR_BOTH);
|
||||
|
||||
if (urange) {
|
||||
cur->set_unpacked_idx(*urange);
|
||||
}
|
||||
|
||||
pform_bind_attributes(cur->attributes, attr, keep_attr);
|
||||
pform_put_wire_in_scope(name, cur);
|
||||
}
|
||||
|
||||
void pform_module_define_port(const struct vlltype&li,
|
||||
|
|
@ -2633,66 +2675,6 @@ void pform_module_define_port(const struct vlltype&li,
|
|||
delete attr;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function makes a single signal (a wire, a reg, etc) as
|
||||
* requested by the parser. The name is unscoped, so I attach the
|
||||
* current scope to it (with the scoped_name function) and I try to
|
||||
* resolve it with an existing PWire in the scope.
|
||||
*
|
||||
* The wire might already exist because of an implicit declaration in
|
||||
* a module port, i.e.:
|
||||
*
|
||||
* module foo (bar...
|
||||
*
|
||||
* reg bar;
|
||||
*
|
||||
* The output (or other port direction indicator) may or may not have
|
||||
* been seen already, so I do not do any checking with it yet. But I
|
||||
* do check to see if the name has already been declared, as this
|
||||
* function is called for every declaration.
|
||||
*/
|
||||
|
||||
static PWire* pform_get_or_make_wire(const vlltype&li, perm_string name,
|
||||
NetNet::Type type, NetNet::PortType ptype,
|
||||
ivl_variable_type_t dtype)
|
||||
{
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
|
||||
// If the wire already exists but isn't yet fully defined,
|
||||
// carry on adding details.
|
||||
if (cur && (cur->get_data_type() == IVL_VT_NO_TYPE ||
|
||||
cur->get_wire_type() == NetNet::IMPLICIT) ) {
|
||||
// If this is not implicit ("implicit" meaning we don't
|
||||
// know what the type is yet) then set the type now.
|
||||
if (type != NetNet::IMPLICIT) {
|
||||
bool rc = cur->set_wire_type(type);
|
||||
if (rc == false) {
|
||||
ostringstream msg;
|
||||
msg << name << " " << type
|
||||
<< " definition conflicts with " << cur->get_wire_type()
|
||||
<< " definition at " << cur->get_fileline()
|
||||
<< ".";
|
||||
VLerror(msg.str().c_str());
|
||||
}
|
||||
FILE_NAME(cur, li);
|
||||
}
|
||||
return cur;
|
||||
}
|
||||
|
||||
// If the wire already exists and is fully defined, this
|
||||
// must be a redeclaration. Start again with a new wire.
|
||||
// The error will be reported when we add the new wire
|
||||
// to the scope. Do not delete the old wire - it will
|
||||
// remain in the local symbol map.
|
||||
|
||||
cur = new PWire(name, type, ptype, dtype);
|
||||
FILE_NAME(cur, li);
|
||||
|
||||
pform_put_wire_in_scope(name, cur);
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
/*
|
||||
* this is the basic form of pform_makewire. This takes a single simple
|
||||
* name, port type, net type, data type, and attributes, and creates
|
||||
|
|
@ -2703,7 +2685,7 @@ PWire *pform_makewire(const vlltype&li, perm_string name, NetNet::Type type,
|
|||
ivl_variable_type_t dt, std::list<pform_range_t> *indices)
|
||||
{
|
||||
PWire*cur = pform_get_or_make_wire(li, name, type, NetNet::NOT_A_PORT,
|
||||
dt);
|
||||
dt, SR_NET);
|
||||
assert(cur);
|
||||
|
||||
bool flag;
|
||||
|
|
@ -2717,7 +2699,6 @@ PWire *pform_makewire(const vlltype&li, perm_string name, NetNet::Type type,
|
|||
<< " to " << dt << "." << endl;
|
||||
}
|
||||
ivl_assert(*cur, flag);
|
||||
cur->set_range_scalar(SR_NET);
|
||||
cur->set_signed(true);
|
||||
break;
|
||||
default:
|
||||
|
|
@ -2821,27 +2802,21 @@ static vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
|||
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
|
||||
assert(ports);
|
||||
vector<pform_tf_port_t>*res = new vector<pform_tf_port_t>(0);
|
||||
PWSRType rt = vtype != IVL_VT_NO_TYPE ? SR_BOTH : SR_PORT;
|
||||
|
||||
for (list<pform_port_t>::iterator cur = ports->begin()
|
||||
; cur != ports->end() ; ++ cur ) {
|
||||
perm_string &name = cur->name;
|
||||
|
||||
/* Look for a preexisting wire. If it exists, set the
|
||||
port direction. If not, create it. */
|
||||
PWire*curw = pform_get_wire_in_scope(name);
|
||||
if (curw) {
|
||||
curw->set_port_type(pt);
|
||||
} else {
|
||||
curw = new PWire(name, NetNet::IMPLICIT_REG, pt, vtype);
|
||||
FILE_NAME(curw, loc);
|
||||
pform_put_wire_in_scope(name, curw);
|
||||
}
|
||||
|
||||
PWire*curw = pform_get_or_make_wire(loc, name, NetNet::IMPLICIT_REG,
|
||||
pt, vtype, rt);
|
||||
curw->set_signed(signed_flag);
|
||||
|
||||
/* If there is a range involved, it needs to be set. */
|
||||
if (range) {
|
||||
curw->set_range(*range, SR_PORT);
|
||||
}
|
||||
if (range)
|
||||
curw->set_range(*range, rt);
|
||||
|
||||
if (cur->udims) {
|
||||
if (pform_requires_sv(loc, "Task/function port with unpacked dimensions"))
|
||||
|
|
@ -2857,27 +2832,23 @@ static vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
|||
|
||||
static vector<pform_tf_port_t>*do_make_task_ports(const struct vlltype&loc,
|
||||
NetNet::PortType pt,
|
||||
ivl_variable_type_t var_type,
|
||||
ivl_variable_type_t vtype,
|
||||
data_type_t*data_type,
|
||||
list<pform_port_t>*ports)
|
||||
{
|
||||
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
|
||||
assert(ports);
|
||||
vector<pform_tf_port_t>*res = new vector<pform_tf_port_t>(0);
|
||||
PWSRType rt = data_type ? SR_BOTH : SR_PORT;
|
||||
|
||||
for (list<pform_port_t>::iterator cur = ports->begin()
|
||||
; cur != ports->end() ; ++cur) {
|
||||
perm_string &name = cur->name;
|
||||
|
||||
PWire*curw = pform_get_wire_in_scope(name);
|
||||
if (curw) {
|
||||
curw->set_port_type(pt);
|
||||
} else {
|
||||
curw = new PWire(name, NetNet::IMPLICIT_REG, pt, var_type);
|
||||
FILE_NAME(curw, loc);
|
||||
PWire*curw = pform_get_or_make_wire(loc, name, NetNet::IMPLICIT_REG,
|
||||
pt, vtype, rt);
|
||||
if (data_type)
|
||||
curw->set_data_type(data_type);
|
||||
pform_put_wire_in_scope(name, curw);
|
||||
}
|
||||
|
||||
if (cur->udims) {
|
||||
if (pform_requires_sv(loc, "Task/function port with unpacked dimensions"))
|
||||
|
|
@ -3256,34 +3227,6 @@ extern void pform_module_specify_path(PSpecPath*obj)
|
|||
}
|
||||
|
||||
|
||||
static PWire *pform_set_port_type(const struct vlltype&li,
|
||||
perm_string name, NetNet::PortType pt)
|
||||
{
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_NO_TYPE);
|
||||
FILE_NAME(cur, li);
|
||||
pform_put_wire_in_scope(name, cur);
|
||||
}
|
||||
|
||||
switch (cur->get_port_type()) {
|
||||
case NetNet::NOT_A_PORT:
|
||||
case NetNet::PIMPLICIT:
|
||||
if (! cur->set_port_type(pt))
|
||||
VLerror("error setting port direction.");
|
||||
break;
|
||||
|
||||
default:
|
||||
cerr << li << ": error: "
|
||||
<< "port " << name << " already has a port declaration."
|
||||
<< endl;
|
||||
error_count += 1;
|
||||
break;
|
||||
}
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
void pform_set_port_type(const struct vlltype&li,
|
||||
list<pform_port_t>*ports,
|
||||
NetNet::PortType pt,
|
||||
|
|
@ -3306,7 +3249,8 @@ void pform_set_port_type(const struct vlltype&li,
|
|||
for (list<pform_port_t>::iterator cur = ports->begin()
|
||||
; cur != ports->end() ; ++ cur ) {
|
||||
|
||||
PWire *wire = pform_set_port_type(li, cur->name, pt);
|
||||
PWire *wire = pform_get_or_make_wire(li, cur->name, NetNet::IMPLICIT, pt,
|
||||
IVL_VT_NO_TYPE, SR_PORT);
|
||||
pform_set_net_range(wire, range, signed_flag, SR_PORT, attr);
|
||||
if (cur->udims) {
|
||||
cerr << li << ": warning: "
|
||||
|
|
|
|||
Loading…
Reference in New Issue