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:
Lars-Peter Clausen 2022-02-19 22:44:02 +01:00
parent c631ff2483
commit b0c386182a
4 changed files with 39 additions and 35 deletions

14
parse.y
View File

@ -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;

View File

@ -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;
}

View File

@ -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);
/*

View File

@ -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,