Support unpacked array dimensions on non-ansi style task ports
SystemVerilog allows unpacked array dimensions on non-ANSI style task and function ports. To support this refactor pform_make_task_ports() to accept a of pform_port_t, which in addition to the identifier name also allows to specify per port unpacked dimensions. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de>
This commit is contained in:
parent
c631ff2483
commit
b0c386182a
14
parse.y
14
parse.y
|
|
@ -2346,7 +2346,7 @@ task_declaration /* IEEE1800-2005: A.2.7 */
|
|||
|
||||
|
||||
tf_port_declaration /* IEEE1800-2005: A.2.7 */
|
||||
: port_direction data_type_or_implicit list_of_identifiers ';'
|
||||
: port_direction data_type_or_implicit list_of_port_identifiers ';'
|
||||
{ $$ = pform_make_task_ports(@1, $1, $2, $3, true);
|
||||
}
|
||||
;
|
||||
|
|
@ -2367,8 +2367,7 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
|
|||
NetNet::PortType use_port_type = $1;
|
||||
if ((use_port_type == NetNet::PIMPLICIT) && (gn_system_verilog() || ($2 == 0)))
|
||||
use_port_type = port_declaration_context.port_type;
|
||||
perm_string name = lex_strings.make($3);
|
||||
list<perm_string>* ilist = list_from_identifier($3);
|
||||
list<pform_port_t>* port_list = make_port_list($3, $4, 0);
|
||||
|
||||
if (use_port_type == NetNet::PIMPLICIT) {
|
||||
yyerror(@1, "error: missing task/function port direction.");
|
||||
|
|
@ -2383,7 +2382,7 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
|
|||
}
|
||||
tmp = pform_make_task_ports(@3, use_port_type,
|
||||
port_declaration_context.data_type,
|
||||
ilist);
|
||||
port_list);
|
||||
|
||||
} else {
|
||||
// Otherwise, the decorations for this identifier
|
||||
|
|
@ -2395,12 +2394,7 @@ tf_port_item /* IEEE1800-2005: A.2.7 */
|
|||
FILE_NAME($2, @3);
|
||||
}
|
||||
port_declaration_context.data_type = $2;
|
||||
tmp = pform_make_task_ports(@3, use_port_type, $2, ilist);
|
||||
}
|
||||
if ($4 != 0) {
|
||||
if (pform_requires_sv(@4, "Task/function port with unpacked dimensions")) {
|
||||
pform_set_reg_idx(name, $4);
|
||||
}
|
||||
tmp = pform_make_task_ports(@3, use_port_type, $2, port_list);
|
||||
}
|
||||
|
||||
$$ = tmp;
|
||||
|
|
|
|||
54
pform.cc
54
pform.cc
|
|
@ -2928,16 +2928,15 @@ static vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
|||
ivl_variable_type_t vtype,
|
||||
bool signed_flag,
|
||||
list<pform_range_t>*range,
|
||||
list<perm_string>*names,
|
||||
list<pform_port_t>*ports,
|
||||
bool isint = false)
|
||||
{
|
||||
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
|
||||
assert(names);
|
||||
assert(ports);
|
||||
vector<pform_tf_port_t>*res = new vector<pform_tf_port_t>(0);
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ cur ) {
|
||||
|
||||
perm_string name = *cur;
|
||||
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. */
|
||||
|
|
@ -2961,6 +2960,11 @@ static vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
|||
curw->set_range(*range, SR_PORT);
|
||||
}
|
||||
|
||||
if (cur->udims) {
|
||||
if (pform_requires_sv(loc, "Task/function port with unpacked dimensions"))
|
||||
curw->set_unpacked_idx(*cur->udims);
|
||||
}
|
||||
|
||||
res->push_back(pform_tf_port_t(curw));
|
||||
}
|
||||
|
||||
|
|
@ -2972,15 +2976,16 @@ static vector<pform_tf_port_t>*do_make_task_ports(const struct vlltype&loc,
|
|||
NetNet::PortType pt,
|
||||
ivl_variable_type_t var_type,
|
||||
data_type_t*data_type,
|
||||
list<perm_string>*names)
|
||||
list<pform_port_t>*ports)
|
||||
{
|
||||
assert(pt != NetNet::PIMPLICIT && pt != NetNet::NOT_A_PORT);
|
||||
assert(names);
|
||||
assert(ports);
|
||||
vector<pform_tf_port_t>*res = new vector<pform_tf_port_t>(0);
|
||||
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++cur) {
|
||||
perm_string name = *cur;
|
||||
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);
|
||||
|
|
@ -2991,6 +2996,11 @@ static vector<pform_tf_port_t>*do_make_task_ports(const struct vlltype&loc,
|
|||
pform_put_wire_in_scope(name, curw);
|
||||
}
|
||||
|
||||
if (cur->udims) {
|
||||
if (pform_requires_sv(loc, "Task/function port with unpacked dimensions"))
|
||||
curw->set_unpacked_idx(*cur->udims);
|
||||
}
|
||||
|
||||
res->push_back(pform_tf_port_t(curw));
|
||||
}
|
||||
return res;
|
||||
|
|
@ -2999,7 +3009,7 @@ static vector<pform_tf_port_t>*do_make_task_ports(const struct vlltype&loc,
|
|||
vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
||||
NetNet::PortType pt,
|
||||
data_type_t*vtype,
|
||||
list<perm_string>*names,
|
||||
list<pform_port_t>*ports,
|
||||
bool allow_implicit)
|
||||
{
|
||||
vector<pform_tf_port_t>*ret = NULL;
|
||||
|
|
@ -3014,7 +3024,7 @@ vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
|||
list<pform_range_t>*range_tmp = make_range_from_width(atype->type_code);
|
||||
ret = pform_make_task_ports(loc, pt, IVL_VT_BOOL,
|
||||
atype->signed_flag,
|
||||
range_tmp, names);
|
||||
range_tmp, ports);
|
||||
}
|
||||
|
||||
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (vtype)) {
|
||||
|
|
@ -3025,36 +3035,36 @@ vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
|||
ret = pform_make_task_ports(loc, pt, base_type,
|
||||
vec_type->signed_flag,
|
||||
copy_range(vec_type->pdims.get()),
|
||||
names, vec_type->integer_flag);
|
||||
ports, vec_type->integer_flag);
|
||||
}
|
||||
|
||||
if (/*real_type_t*real_type = */ dynamic_cast<real_type_t*> (vtype)) {
|
||||
ret = pform_make_task_ports(loc, pt, IVL_VT_REAL,
|
||||
true, 0, names);
|
||||
true, 0, ports);
|
||||
}
|
||||
|
||||
if (dynamic_cast<string_type_t*> (vtype)) {
|
||||
ret = pform_make_task_ports(loc, pt, IVL_VT_STRING,
|
||||
false, 0, names);
|
||||
false, 0, ports);
|
||||
}
|
||||
|
||||
if (class_type_t*class_type = dynamic_cast<class_type_t*> (vtype)) {
|
||||
ret = do_make_task_ports(loc, pt, IVL_VT_CLASS, class_type, names);
|
||||
ret = do_make_task_ports(loc, pt, IVL_VT_CLASS, class_type, ports);
|
||||
}
|
||||
|
||||
if (! ret) {
|
||||
ret = do_make_task_ports(loc, pt, IVL_VT_NO_TYPE, vtype, names);
|
||||
ret = do_make_task_ports(loc, pt, IVL_VT_NO_TYPE, vtype, ports);
|
||||
}
|
||||
|
||||
if (unpacked_dims) {
|
||||
for (list<perm_string>::iterator cur = names->begin()
|
||||
; cur != names->end() ; ++ cur ) {
|
||||
PWire*wire = pform_get_wire_in_scope(*cur);
|
||||
for (list<pform_port_t>::iterator cur = ports->begin()
|
||||
; cur != ports->end() ; ++ cur ) {
|
||||
PWire*wire = pform_get_wire_in_scope(cur->name);
|
||||
wire->set_unpacked_idx(*unpacked_dims);
|
||||
}
|
||||
}
|
||||
|
||||
delete names;
|
||||
delete ports;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
2
pform.h
2
pform.h
|
|
@ -495,7 +495,7 @@ extern void pform_make_pgassign_list(std::list<PExpr*>*alist,
|
|||
extern std::vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
||||
NetNet::PortType pt,
|
||||
data_type_t*vtype,
|
||||
std::list<perm_string>*names,
|
||||
std::list<pform_port_t>*ports,
|
||||
bool allow_implicit = false);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -106,8 +106,8 @@ void pform_set_this_class(const struct vlltype&loc, PTaskFunc*net)
|
|||
if (pform_cur_class == 0)
|
||||
return;
|
||||
|
||||
list<perm_string>*this_name = new list<perm_string>;
|
||||
this_name->push_back(perm_string::literal(THIS_TOKEN));
|
||||
list<pform_port_t>*this_name = new list<pform_port_t>;
|
||||
this_name->push_back(pform_port_t(perm_string::literal(THIS_TOKEN), 0, 0));
|
||||
vector<pform_tf_port_t>*this_port = pform_make_task_ports(loc,
|
||||
NetNet::PINPUT,
|
||||
pform_cur_class->type,
|
||||
|
|
|
|||
Loading…
Reference in New Issue