diff --git a/elab_sig.cc b/elab_sig.cc index ceb4256c4..3378902eb 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -90,6 +90,90 @@ void Statement::elaborate_sig(Design*, NetScope*) const { } +static void sig_check_data_type(Design*des, NetScope*scope, + PWire *wire, NetNet *sig) +{ + ivl_type_t type = sig->net_type(); + + if (!type) + return; + + if (type->packed()) { + switch (type->base_type()) { + case IVL_VT_LOGIC: // 4-state packed is allowed by the standard + case IVL_VT_BOOL: // Icarus allows 2-state packed as an extension + return; + default: + break; + } + } + + // Icarus allows real nets as an extension + if (type->base_type() == IVL_VT_REAL) + return; + + if (wire->symbol_type() == PNamedItem::NET) { + cerr << wire->get_fileline() << ": error: Net `" + << wire->basename() << "` can not be of type `" + << sig->data_type() << "`." << endl; + des->errors++; + } else if (scope->type() == NetScope::MODULE && + sig->port_type() != NetNet::NOT_A_PORT) { + // Module ports only support wire types a the moment + cerr << wire->get_fileline() << ": sorry: Port `" + << wire->basename() << "` of module `" + << scope->module_name() + << "` with type `" << sig->data_type() + << "` is not supported." + << endl; + des->errors++; + } +} + +static void sig_check_port_type(Design*des, NetScope*scope, + PWire *wire, NetNet *sig) +{ + if (sig->port_type() == NetNet::PREF) { + cerr << wire->get_fileline() << ": sorry: " + << "Reference ports not supported yet." << endl; + des->errors += 1; + } + + // Some extra checks for module ports + if (scope->type() != NetScope::MODULE) + return; + + /* If the signal is an input and is also declared as a + reg, then report an error. */ + + if (sig->port_type() == NetNet::PINPUT && + sig->type() == NetNet::REG) { + cerr << wire->get_fileline() << ": error: Port `" + << wire->basename() << "` of module `" + << scope->module_name() + << "` is declared as input and as a reg type." << endl; + des->errors += 1; + } + + if (sig->port_type() == NetNet::PINOUT && + sig->type() == NetNet::REG) { + cerr << wire->get_fileline() << ": error: Port `" + << wire->basename() << "` of module `" + << scope->module_name() + << "` is declared as inout and as a reg type." << endl; + des->errors += 1; + } + + if (sig->port_type() == NetNet::PINOUT && + sig->data_type() == IVL_VT_REAL) { + cerr << wire->get_fileline() << ": error: Port `" + << wire->basename() << "` of module `" + << scope->module_name() + << "` is declared as a real inout port." << endl; + des->errors += 1; + } +} + bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const { bool flag = true; @@ -100,53 +184,11 @@ bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const PWire*cur = (*wt).second; NetNet*sig = cur->elaborate_sig(des, scope); - if (sig && (sig->scope() == scope) - && (sig->port_type() == NetNet::PREF)) { + if (!sig || sig->scope() != scope) + continue; - cerr << cur->get_fileline() << ": sorry: " - << "Reference ports not supported yet." << endl; - des->errors += 1; - } - - - /* If the signal is an input and is also declared as a - reg, then report an error. */ - - if (sig && (sig->scope() == scope) - && (scope->type() == NetScope::MODULE) - && (sig->port_type() == NetNet::PINPUT) - && (sig->type() == NetNet::REG)) { - - cerr << cur->get_fileline() << ": error: Port " - << cur->basename() << " of module " - << scope->module_name() - << " is declared as input and as a reg type." << endl; - des->errors += 1; - } - - if (sig && (sig->scope() == scope) - && (scope->type() == NetScope::MODULE) - && (sig->port_type() == NetNet::PINOUT) - && (sig->type() == NetNet::REG)) { - - cerr << cur->get_fileline() << ": error: Port " - << cur->basename() << " of module " - << scope->module_name() - << " is declared as inout and as a reg type." << endl; - des->errors += 1; - } - - if (sig && (sig->scope() == scope) - && (scope->type() == NetScope::MODULE) - && (sig->port_type() == NetNet::PINOUT) - && (sig->data_type() == IVL_VT_REAL)) { - - cerr << cur->get_fileline() << ": error: Port " - << cur->basename() << " of module " - << scope->module_name() - << " is declared as a real inout port." << endl; - des->errors += 1; - } + sig_check_data_type(des, scope, cur, sig); + sig_check_port_type(des, scope, cur, sig); } diff --git a/ivtest/gold/pr2976242c.gold b/ivtest/gold/pr2976242c.gold index 45baf1d45..ade3d00bb 100644 --- a/ivtest/gold/pr2976242c.gold +++ b/ivtest/gold/pr2976242c.gold @@ -1,4 +1,4 @@ -./ivltests/pr2976242c.v:43: error: Port out of module io_real_to_vec is declared as a real inout port. +./ivltests/pr2976242c.v:43: error: Port `out` of module `io_real_to_vec` is declared as a real inout port. ./ivltests/pr2976242c.v:11: error: Cannot connect an arrayed instance of module vec_to_real to real signal r_vec. ./ivltests/pr2976242c.v:14: error: When automatically converting a real port of an arrayed instance to a bit signal ./ivltests/pr2976242c.v:14: : the signal width (5) must be an integer multiple of the instance count (2). diff --git a/parse.y b/parse.y index 32cbe6823..206caade4 100644 --- a/parse.y +++ b/parse.y @@ -4891,6 +4891,7 @@ module_item | attribute_list_opt net_type data_type_or_implicit delay3_opt net_variable_list ';' { data_type_t*data_type = $3; + pform_check_net_data_type(@2, $2, $3); if (data_type == 0) { data_type = new vector_type_t(IVL_VT_LOGIC, false, 0); FILE_NAME(data_type, @2); @@ -4925,6 +4926,7 @@ module_item | attribute_list_opt net_type data_type_or_implicit delay3_opt net_decl_assigns ';' { data_type_t*data_type = $3; + pform_check_net_data_type(@2, $2, $3); if (data_type == 0) { data_type = new vector_type_t(IVL_VT_LOGIC, false, 0); FILE_NAME(data_type, @2); @@ -4938,6 +4940,7 @@ module_item | attribute_list_opt net_type data_type_or_implicit drive_strength net_decl_assigns ';' { data_type_t*data_type = $3; + pform_check_net_data_type(@2, $2, $3); if (data_type == 0) { data_type = new vector_type_t(IVL_VT_LOGIC, false, 0); FILE_NAME(data_type, @2); diff --git a/pform.cc b/pform.cc index 27416c9c3..ca45e53eb 100644 --- a/pform.cc +++ b/pform.cc @@ -2634,6 +2634,8 @@ void pform_module_define_port(const struct vlltype&li, return; } + pform_check_net_data_type(li, type, vtype); + // Packed ranges list*prange = 0; // Unpacked dimensions @@ -3748,6 +3750,37 @@ bool pform_requires_sv(const struct vlltype&loc, const char *feature) return false; } +void pform_check_net_data_type(const struct vlltype&loc, NetNet::Type net_type, + const data_type_t *data_type) +{ + // For SystemVerilog the type is checked during elaboration since due to + // forward typedefs and type parameters the actual type might not be known + // yet. + if (gn_system_verilog()) + return; + + switch (net_type) { + case NetNet::REG: + case NetNet::IMPLICIT_REG: + return; + default: + break; + } + + if (!data_type) + return; + + const vector_type_t*vec_type = dynamic_cast(data_type); + if (vec_type && vec_type->implicit_flag) + return; + + const real_type_t*rtype = dynamic_cast(data_type); + if (rtype && rtype->type_code() == real_type_t::REAL) + return; + + pform_requires_sv(loc, "Net data type"); +} + FILE*vl_input = 0; extern void reset_lexor(); diff --git a/pform.h b/pform.h index 4e30ab750..5468d44b7 100644 --- a/pform.h +++ b/pform.h @@ -587,4 +587,7 @@ bool pform_requires_sv(const struct vlltype&loc, const char *feature); void pform_start_parameter_port_list(); void pform_end_parameter_port_list(); +void pform_check_net_data_type(const struct vlltype&loc, NetNet::Type net_type, + const data_type_t *data_type); + #endif /* IVL_pform_H */