2000-05-02 18:27:38 +02:00
|
|
|
/*
|
2025-10-21 07:45:05 +02:00
|
|
|
* Copyright (c) 2000-2025 Stephen Williams (steve@icarus.com)
|
2012-08-06 01:28:40 +02:00
|
|
|
* Copyright CERN 2012 / Stephen Williams (steve@icarus.com)
|
2000-05-02 18:27:38 +02:00
|
|
|
*
|
|
|
|
|
* This source code is free software; you can redistribute it
|
|
|
|
|
* and/or modify it in source code form under the terms of the GNU
|
|
|
|
|
* General Public License as published by the Free Software
|
|
|
|
|
* Foundation; either version 2 of the License, or (at your option)
|
|
|
|
|
* any later version.
|
|
|
|
|
*
|
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
|
* along with this program; if not, write to the Free Software
|
2012-08-29 03:41:23 +02:00
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
2000-05-02 18:27:38 +02:00
|
|
|
*/
|
|
|
|
|
|
2001-07-25 05:10:48 +02:00
|
|
|
# include "config.h"
|
|
|
|
|
|
2012-08-06 01:28:40 +02:00
|
|
|
# include <typeinfo>
|
2008-01-05 00:23:47 +01:00
|
|
|
# include <cstdlib>
|
2001-07-25 05:10:48 +02:00
|
|
|
# include <iostream>
|
|
|
|
|
|
2000-05-02 18:27:38 +02:00
|
|
|
# include "Module.h"
|
2013-03-15 04:08:32 +01:00
|
|
|
# include "PClass.h"
|
2001-01-07 08:00:31 +01:00
|
|
|
# include "PExpr.h"
|
2000-05-02 18:27:38 +02:00
|
|
|
# include "PGate.h"
|
2006-04-10 02:37:42 +02:00
|
|
|
# include "PGenerate.h"
|
2013-04-07 02:38:36 +02:00
|
|
|
# include "PPackage.h"
|
2000-07-30 20:25:43 +02:00
|
|
|
# include "PTask.h"
|
2000-05-02 18:27:38 +02:00
|
|
|
# include "PWire.h"
|
2008-02-25 04:40:54 +01:00
|
|
|
# include "Statement.h"
|
2004-02-18 18:11:54 +01:00
|
|
|
# include "compiler.h"
|
2000-05-02 18:27:38 +02:00
|
|
|
# include "netlist.h"
|
2001-02-10 21:29:39 +01:00
|
|
|
# include "netmisc.h"
|
2012-11-12 02:42:31 +01:00
|
|
|
# include "netclass.h"
|
2012-07-14 03:41:41 +02:00
|
|
|
# include "netenum.h"
|
2012-09-15 19:27:43 +02:00
|
|
|
# include "netvector.h"
|
2012-07-14 03:41:41 +02:00
|
|
|
# include "netdarray.h"
|
2012-08-06 01:28:40 +02:00
|
|
|
# include "netparray.h"
|
2014-07-30 05:41:03 +02:00
|
|
|
# include "netqueue.h"
|
2020-12-30 19:39:51 +01:00
|
|
|
# include "netscalar.h"
|
2000-05-02 18:27:38 +02:00
|
|
|
# include "util.h"
|
2007-05-24 06:07:11 +02:00
|
|
|
# include "ivl_assert.h"
|
2000-05-02 18:27:38 +02:00
|
|
|
|
2012-08-06 01:28:40 +02:00
|
|
|
using namespace std;
|
|
|
|
|
|
2019-09-14 01:29:49 +02:00
|
|
|
#if 0
|
|
|
|
|
/* These functions are not currently used. */
|
2008-02-28 00:01:09 +01:00
|
|
|
static bool get_const_argument(NetExpr*exp, verinum&res)
|
|
|
|
|
{
|
|
|
|
|
switch (exp->expr_type()) {
|
|
|
|
|
case IVL_VT_REAL: {
|
|
|
|
|
NetECReal*cv = dynamic_cast<NetECReal*>(exp);
|
|
|
|
|
if (cv == 0) return false;
|
|
|
|
|
verireal tmp = cv->value();
|
|
|
|
|
res = verinum(tmp.as_long());
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
case IVL_VT_BOOL:
|
|
|
|
|
case IVL_VT_LOGIC: {
|
|
|
|
|
NetEConst*cv = dynamic_cast<NetEConst*>(exp);
|
|
|
|
|
if (cv == 0) return false;
|
|
|
|
|
res = cv->value();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
default:
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*exp, 0);;
|
2008-02-28 00:01:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-03 01:29:30 +02:00
|
|
|
static bool get_const_argument(NetExpr*exp, long&res)
|
|
|
|
|
{
|
|
|
|
|
verinum tmp;
|
|
|
|
|
bool rc = get_const_argument(exp, tmp);
|
|
|
|
|
if (rc == false) return false;
|
|
|
|
|
res = tmp.as_long();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2013-07-12 04:07:49 +02:00
|
|
|
#endif
|
2010-10-03 01:29:30 +02:00
|
|
|
|
2010-11-01 22:37:06 +01:00
|
|
|
void Statement::elaborate_sig(Design*, NetScope*) const
|
2001-01-07 08:00:31 +01:00
|
|
|
{
|
2008-02-25 04:40:54 +01:00
|
|
|
}
|
2007-05-24 06:07:11 +02:00
|
|
|
|
2025-10-23 18:58:49 +02:00
|
|
|
static void sig_check_data_type(Design*des, const NetScope*scope,
|
|
|
|
|
const PWire *wire, NetNet *sig)
|
2008-02-25 04:40:54 +01:00
|
|
|
{
|
2022-01-20 15:59:28 +01:00
|
|
|
ivl_type_t type = sig->net_type();
|
|
|
|
|
|
|
|
|
|
if (!type)
|
|
|
|
|
return;
|
|
|
|
|
|
2024-01-28 15:14:10 +01:00
|
|
|
if ((sig->type() == NetNet::WIRE) && (sig->data_type() != IVL_VT_LOGIC)) {
|
|
|
|
|
if (gn_cadence_types_flag) {
|
|
|
|
|
sig->type(NetNet::UNRESOLVED_WIRE);
|
|
|
|
|
} else {
|
|
|
|
|
cerr << wire->get_fileline() << ": error: Net `"
|
|
|
|
|
<< wire->basename() << "` can not be of type `"
|
|
|
|
|
<< sig->data_type() << "`." << endl;
|
|
|
|
|
des->errors++;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-20 15:59:28 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-07 08:00:31 +01:00
|
|
|
|
2022-01-20 15:59:28 +01:00
|
|
|
// 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++;
|
|
|
|
|
}
|
|
|
|
|
}
|
2001-01-07 08:00:31 +01:00
|
|
|
|
2025-10-23 18:58:49 +02:00
|
|
|
static void sig_check_port_type(Design*des, const NetScope*scope,
|
|
|
|
|
const PWire *wire, const NetNet *sig)
|
2022-01-20 15:59:28 +01:00
|
|
|
{
|
|
|
|
|
if (sig->port_type() == NetNet::PREF) {
|
|
|
|
|
cerr << wire->get_fileline() << ": sorry: "
|
|
|
|
|
<< "Reference ports not supported yet." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
2007-05-24 06:07:11 +02:00
|
|
|
|
2022-01-20 15:59:28 +01:00
|
|
|
// Some extra checks for module ports
|
|
|
|
|
if (scope->type() != NetScope::MODULE)
|
|
|
|
|
return;
|
2012-02-25 19:19:48 +01:00
|
|
|
|
2022-01-20 15:59:28 +01:00
|
|
|
/* If the signal is an input and is also declared as a
|
2022-05-22 16:38:42 +02:00
|
|
|
reg, then report an error. In SystemVerilog a input
|
|
|
|
|
is allowed to be a register. It will get converted
|
|
|
|
|
to a unresolved wire when the port is connected. */
|
2012-02-25 19:19:48 +01:00
|
|
|
|
2022-01-20 15:59:28 +01:00
|
|
|
if (sig->port_type() == NetNet::PINPUT &&
|
2022-05-22 16:38:42 +02:00
|
|
|
sig->type() == NetNet::REG && !gn_var_can_be_uwire()) {
|
2022-01-20 15:59:28 +01:00
|
|
|
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;
|
|
|
|
|
}
|
2007-05-24 06:07:11 +02:00
|
|
|
|
2022-01-20 15:59:28 +01:00
|
|
|
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;
|
|
|
|
|
}
|
2008-02-25 04:40:54 +01:00
|
|
|
|
2022-01-20 15:59:28 +01:00
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-02-25 04:40:54 +01:00
|
|
|
|
2022-01-20 15:59:28 +01:00
|
|
|
bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
bool flag = true;
|
2008-02-25 04:40:54 +01:00
|
|
|
|
2022-01-20 15:59:28 +01:00
|
|
|
for (map<perm_string,PWire*>::const_iterator wt = wires.begin()
|
|
|
|
|
; wt != wires.end() ; ++ wt ) {
|
2008-02-25 04:40:54 +01:00
|
|
|
|
2022-01-20 15:59:28 +01:00
|
|
|
PWire*cur = (*wt).second;
|
|
|
|
|
NetNet*sig = cur->elaborate_sig(des, scope);
|
2010-04-25 23:15:35 +02:00
|
|
|
|
2022-01-20 15:59:28 +01:00
|
|
|
if (!sig || sig->scope() != scope)
|
|
|
|
|
continue;
|
2010-04-25 23:15:35 +02:00
|
|
|
|
2022-01-20 15:59:28 +01:00
|
|
|
sig_check_data_type(des, scope, cur, sig);
|
|
|
|
|
sig_check_port_type(des, scope, cur, sig);
|
2008-02-25 04:40:54 +01:00
|
|
|
|
2001-01-07 08:00:31 +01:00
|
|
|
}
|
|
|
|
|
|
2008-02-25 04:40:54 +01:00
|
|
|
return flag;
|
2001-01-07 08:00:31 +01:00
|
|
|
}
|
2000-05-02 18:27:38 +02:00
|
|
|
|
2008-06-19 06:54:58 +02:00
|
|
|
static void elaborate_sig_funcs(Design*des, NetScope*scope,
|
|
|
|
|
const map<perm_string,PFunction*>&funcs)
|
|
|
|
|
{
|
|
|
|
|
typedef map<perm_string,PFunction*>::const_iterator mfunc_it_t;
|
|
|
|
|
|
|
|
|
|
for (mfunc_it_t cur = funcs.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; cur != funcs.end() ; ++ cur ) {
|
2008-06-19 06:54:58 +02:00
|
|
|
|
|
|
|
|
hname_t use_name ( (*cur).first );
|
|
|
|
|
NetScope*fscope = scope->child(use_name);
|
2009-08-31 20:33:00 +02:00
|
|
|
if (fscope == 0) {
|
2008-06-19 06:54:58 +02:00
|
|
|
cerr << (*cur).second->get_fileline() << ": internal error: "
|
|
|
|
|
<< "Child scope for function " << (*cur).first
|
|
|
|
|
<< " missing in " << scope_path(scope) << "." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-07 02:38:36 +02:00
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << cur->second->get_fileline() << ": elaborate_sig_funcs: "
|
|
|
|
|
<< "Elaborate function " << use_name
|
|
|
|
|
<< " in " << scope_path(fscope) << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cur->second->elaborate_sig(des, fscope);
|
2008-06-19 06:54:58 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void elaborate_sig_tasks(Design*des, NetScope*scope,
|
|
|
|
|
const map<perm_string,PTask*>&tasks)
|
|
|
|
|
{
|
|
|
|
|
typedef map<perm_string,PTask*>::const_iterator mtask_it_t;
|
|
|
|
|
|
|
|
|
|
for (mtask_it_t cur = tasks.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; cur != tasks.end() ; ++ cur ) {
|
2008-06-19 06:54:58 +02:00
|
|
|
NetScope*tscope = scope->child( hname_t((*cur).first) );
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*(*cur).second, tscope);
|
2008-06-19 06:54:58 +02:00
|
|
|
(*cur).second->elaborate_sig(des, tscope);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-15 04:08:32 +01:00
|
|
|
static void elaborate_sig_classes(Design*des, NetScope*scope,
|
|
|
|
|
const map<perm_string,PClass*>&classes)
|
|
|
|
|
{
|
|
|
|
|
for (map<perm_string,PClass*>::const_iterator cur = classes.begin()
|
|
|
|
|
; cur != classes.end() ; ++ cur) {
|
2020-12-23 20:16:14 +01:00
|
|
|
netclass_t*use_class = scope->find_class(des, cur->second->pscope_name());
|
2013-03-15 04:08:32 +01:00
|
|
|
use_class->elaborate_sig(des, cur->second);
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-09-04 18:41:51 +02:00
|
|
|
|
2013-04-07 02:38:36 +02:00
|
|
|
bool PPackage::elaborate_sig(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
bool flag = true;
|
|
|
|
|
|
2014-10-11 03:53:53 +02:00
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << get_fileline() << ": PPackage::elaborate_sig: "
|
|
|
|
|
<< "Start package scope=" << scope_path(scope) << endl;
|
|
|
|
|
}
|
|
|
|
|
|
2013-04-07 02:38:36 +02:00
|
|
|
flag = elaborate_sig_wires_(des, scope) && flag;
|
|
|
|
|
|
|
|
|
|
// After all the wires are elaborated, we are free to
|
|
|
|
|
// elaborate the ports of the tasks defined within this
|
|
|
|
|
// module. Run through them now.
|
|
|
|
|
|
|
|
|
|
elaborate_sig_funcs(des, scope, funcs);
|
|
|
|
|
elaborate_sig_tasks(des, scope, tasks);
|
2014-10-11 03:53:53 +02:00
|
|
|
elaborate_sig_classes(des, scope, classes);
|
|
|
|
|
|
|
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << get_fileline() << ": PPackage::elaborate_sig: "
|
|
|
|
|
<< "Done package scope=" << scope_path(scope)
|
|
|
|
|
<< ", flag=" << flag << endl;
|
|
|
|
|
}
|
2013-04-07 02:38:36 +02:00
|
|
|
|
|
|
|
|
return flag;
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-02 18:27:38 +02:00
|
|
|
bool Module::elaborate_sig(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
bool flag = true;
|
|
|
|
|
|
2001-10-31 04:11:15 +01:00
|
|
|
// Scan all the ports of the module, and make sure that each
|
|
|
|
|
// is connected to wires that have port declarations.
|
2008-11-03 05:08:38 +01:00
|
|
|
for (unsigned idx = 0 ; idx < ports.size() ; idx += 1) {
|
2002-05-20 01:37:28 +02:00
|
|
|
Module::port_t*pp = ports[idx];
|
2001-10-31 04:11:15 +01:00
|
|
|
if (pp == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
2008-02-25 04:40:54 +01:00
|
|
|
// The port has a name and an array of expressions. The
|
|
|
|
|
// expression are all identifiers that should reference
|
|
|
|
|
// wires within the scope.
|
|
|
|
|
map<perm_string,PWire*>::const_iterator wt;
|
2008-11-03 05:08:38 +01:00
|
|
|
for (unsigned cc = 0 ; cc < pp->expr.size() ; cc += 1) {
|
2022-09-25 10:39:41 +02:00
|
|
|
pform_name_t port_path (pp->expr[cc]->path().name);
|
2008-02-25 04:40:54 +01:00
|
|
|
// A concatenated wire of a port really should not
|
|
|
|
|
// have any hierarchy.
|
|
|
|
|
if (port_path.size() != 1) {
|
|
|
|
|
cerr << get_fileline() << ": internal error: "
|
|
|
|
|
<< "Port " << port_path << " has a funny name?"
|
|
|
|
|
<< endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wt = wires.find(peek_tail_name(port_path));
|
2001-10-31 04:11:15 +01:00
|
|
|
|
2008-02-25 04:40:54 +01:00
|
|
|
if (wt == wires.end()) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": error: "
|
2008-02-25 04:40:54 +01:00
|
|
|
<< "Port " << port_path << " ("
|
2008-02-14 04:59:05 +01:00
|
|
|
<< (idx+1) << ") of module " << mod_name()
|
2001-10-31 04:11:15 +01:00
|
|
|
<< " is not declared within module." << endl;
|
|
|
|
|
des->errors += 1;
|
2001-11-01 06:21:26 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((*wt).second->get_port_type() == NetNet::NOT_A_PORT) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": error: "
|
2001-12-03 05:47:14 +01:00
|
|
|
<< "Port " << pp->expr[cc]->path() << " ("
|
2008-02-14 04:59:05 +01:00
|
|
|
<< (idx+1) << ") of module " << mod_name()
|
2001-11-01 06:21:26 +01:00
|
|
|
<< " has no direction declaration."
|
|
|
|
|
<< endl;
|
|
|
|
|
des->errors += 1;
|
2001-10-31 04:11:15 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-02-25 04:40:54 +01:00
|
|
|
flag = elaborate_sig_wires_(des, scope) && flag;
|
2006-04-10 02:37:42 +02:00
|
|
|
|
2008-01-29 21:19:59 +01:00
|
|
|
// Run through all the generate schemes to elaborate the
|
2006-04-10 02:37:42 +02:00
|
|
|
// signals that they hold. Note that the generate schemes hold
|
|
|
|
|
// the scopes that they instantiated, so we don't pass any
|
|
|
|
|
// scope in.
|
|
|
|
|
typedef list<PGenerate*>::const_iterator generate_it_t;
|
|
|
|
|
for (generate_it_t cur = generate_schemes.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; cur != generate_schemes.end() ; ++ cur ) {
|
2007-06-22 04:04:48 +02:00
|
|
|
(*cur) -> elaborate_sig(des, scope);
|
2000-05-02 18:27:38 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Get all the gates of the module and elaborate them by
|
|
|
|
|
// connecting them to the signals. The gate may be simple or
|
|
|
|
|
// complex. What we are looking for is gates that are modules
|
|
|
|
|
// that can create scopes and signals.
|
|
|
|
|
|
|
|
|
|
const list<PGate*>&gl = get_gates();
|
|
|
|
|
|
|
|
|
|
for (list<PGate*>::const_iterator gt = gl.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; gt != gl.end() ; ++ gt ) {
|
2000-05-02 18:27:38 +02:00
|
|
|
|
|
|
|
|
flag &= (*gt)->elaborate_sig(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
2000-07-30 20:25:43 +02:00
|
|
|
// After all the wires are elaborated, we are free to
|
|
|
|
|
// elaborate the ports of the tasks defined within this
|
|
|
|
|
// module. Run through them now.
|
|
|
|
|
|
2008-06-19 06:54:58 +02:00
|
|
|
elaborate_sig_funcs(des, scope, funcs);
|
|
|
|
|
elaborate_sig_tasks(des, scope, tasks);
|
2013-03-15 04:08:32 +01:00
|
|
|
elaborate_sig_classes(des, scope, classes);
|
2000-07-30 20:25:43 +02:00
|
|
|
|
2008-02-25 04:40:54 +01:00
|
|
|
// initial and always blocks may contain begin-end and
|
|
|
|
|
// fork-join blocks that can introduce scopes. Therefore, I
|
|
|
|
|
// get to scan processes here.
|
|
|
|
|
|
|
|
|
|
typedef list<PProcess*>::const_iterator proc_it_t;
|
|
|
|
|
|
2008-03-04 05:49:52 +01:00
|
|
|
for (proc_it_t cur = behaviors.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; cur != behaviors.end() ; ++ cur ) {
|
2008-02-25 04:40:54 +01:00
|
|
|
|
|
|
|
|
(*cur) -> statement() -> elaborate_sig(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-02 18:27:38 +02:00
|
|
|
return flag;
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-15 04:08:32 +01:00
|
|
|
void netclass_t::elaborate_sig(Design*des, PClass*pclass)
|
|
|
|
|
{
|
2022-09-21 10:04:45 +02:00
|
|
|
// Collect the properties, elaborate them, and add them to the
|
|
|
|
|
// elaborated class definition.
|
2013-07-03 04:41:58 +02:00
|
|
|
for (map<perm_string,struct class_type_t::prop_info_t>::iterator cur = pclass->type->properties.begin()
|
|
|
|
|
; cur != pclass->type->properties.end() ; ++ cur) {
|
|
|
|
|
|
2022-09-21 10:04:45 +02:00
|
|
|
ivl_type_t use_type = cur->second.type->elaborate_type(des, class_scope_);
|
|
|
|
|
if (debug_scopes) {
|
|
|
|
|
cerr << pclass->get_fileline() << ": elaborate_scope_class: "
|
|
|
|
|
<< " Property " << cur->first
|
|
|
|
|
<< " type=" << *use_type << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dynamic_cast<const netqueue_t *> (use_type)) {
|
|
|
|
|
cerr << cur->second.get_fileline() << ": sorry: "
|
|
|
|
|
<< "Queues inside classes are not yet supported." << endl;
|
|
|
|
|
des->errors++;
|
|
|
|
|
}
|
|
|
|
|
set_property(cur->first, cur->second.qual, use_type);
|
|
|
|
|
|
2013-07-03 04:41:58 +02:00
|
|
|
if (! cur->second.qual.test_static())
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << pclass->get_fileline() << ": netclass_t::elaborate_sig: "
|
|
|
|
|
<< "Elaborate static property " << cur->first
|
|
|
|
|
<< " as signal in scope " << scope_path(class_scope_)
|
|
|
|
|
<< "." << endl;
|
|
|
|
|
}
|
|
|
|
|
|
2013-07-12 04:07:49 +02:00
|
|
|
/* NetNet*sig = */ new NetNet(class_scope_, cur->first, NetNet::REG,
|
2022-04-27 10:48:13 +02:00
|
|
|
use_type);
|
2013-07-03 04:41:58 +02:00
|
|
|
}
|
|
|
|
|
|
2013-03-15 04:08:32 +01:00
|
|
|
for (map<perm_string,PFunction*>::iterator cur = pclass->funcs.begin()
|
|
|
|
|
; cur != pclass->funcs.end() ; ++ cur) {
|
|
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << cur->second->get_fileline() << ": netclass_t::elaborate_sig: "
|
|
|
|
|
<< "Elaborate signals in function method " << cur->first << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetScope*scope = class_scope_->child( hname_t(cur->first) );
|
|
|
|
|
ivl_assert(*cur->second, scope);
|
|
|
|
|
cur->second->elaborate_sig(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (map<perm_string,PTask*>::iterator cur = pclass->tasks.begin()
|
|
|
|
|
; cur != pclass->tasks.end() ; ++ cur) {
|
|
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << cur->second->get_fileline() << ": netclass_t::elaborate_sig: "
|
|
|
|
|
<< "Elaborate signals in task method " << cur->first << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
NetScope*scope = class_scope_->child( hname_t(cur->first) );
|
|
|
|
|
ivl_assert(*cur->second, scope);
|
|
|
|
|
cur->second->elaborate_sig(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-01 22:37:06 +01:00
|
|
|
bool PGate::elaborate_sig(Design*, NetScope*) const
|
2008-03-19 04:50:40 +01:00
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-01 22:37:06 +01:00
|
|
|
bool PGBuiltin::elaborate_sig(Design*, NetScope*) const
|
2008-03-19 04:50:40 +01:00
|
|
|
{
|
2010-01-12 21:11:01 +01:00
|
|
|
return true;
|
2008-03-19 04:50:40 +01:00
|
|
|
}
|
|
|
|
|
|
2010-11-01 22:37:06 +01:00
|
|
|
bool PGAssign::elaborate_sig(Design*, NetScope*) const
|
2008-03-19 04:50:40 +01:00
|
|
|
{
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-02 18:27:38 +02:00
|
|
|
bool PGModule::elaborate_sig_mod_(Design*des, NetScope*scope,
|
2025-10-23 18:58:49 +02:00
|
|
|
const Module*rmod) const
|
2000-05-02 18:27:38 +02:00
|
|
|
{
|
2004-09-05 19:44:41 +02:00
|
|
|
bool flag = true;
|
2000-05-02 18:27:38 +02:00
|
|
|
|
2004-09-05 19:44:41 +02:00
|
|
|
NetScope::scope_vec_t instance = scope->instance_arrays[get_name()];
|
2000-05-02 18:27:38 +02:00
|
|
|
|
2008-11-03 05:08:38 +01:00
|
|
|
for (unsigned idx = 0 ; idx < instance.size() ; idx += 1) {
|
2004-09-05 19:44:41 +02:00
|
|
|
// I know a priori that the elaborate_scope created the scope
|
|
|
|
|
// already, so just look it up as a child of the current scope.
|
|
|
|
|
NetScope*my_scope = instance[idx];
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, my_scope);
|
2000-05-02 18:27:38 +02:00
|
|
|
|
2004-09-05 19:44:41 +02:00
|
|
|
if (my_scope->parent() != scope) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": internal error: "
|
2007-06-02 05:42:12 +02:00
|
|
|
<< "Instance " << scope_path(my_scope)
|
|
|
|
|
<< " is in parent " << scope_path(my_scope->parent())
|
|
|
|
|
<< " instead of " << scope_path(scope)
|
2004-09-05 19:44:41 +02:00
|
|
|
<< endl;
|
|
|
|
|
}
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, my_scope->parent() == scope);
|
2000-05-02 18:27:38 +02:00
|
|
|
|
2004-09-05 19:44:41 +02:00
|
|
|
if (! rmod->elaborate_sig(des, my_scope))
|
|
|
|
|
flag = false;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return flag;
|
2000-05-02 18:27:38 +02:00
|
|
|
}
|
|
|
|
|
|
2010-11-01 22:37:06 +01:00
|
|
|
// Not currently used.
|
|
|
|
|
#if 0
|
2008-03-21 05:44:35 +01:00
|
|
|
bool PGModule::elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const
|
|
|
|
|
{
|
2010-01-12 21:11:01 +01:00
|
|
|
return true;
|
2008-03-21 05:44:35 +01:00
|
|
|
}
|
2010-11-01 22:37:06 +01:00
|
|
|
#endif
|
2008-03-21 05:44:35 +01:00
|
|
|
|
2007-06-22 04:04:48 +02:00
|
|
|
bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
|
2006-04-10 02:37:42 +02:00
|
|
|
{
|
2021-08-03 22:29:46 +02:00
|
|
|
if (directly_nested)
|
2008-11-28 04:45:22 +01:00
|
|
|
return elaborate_sig_direct_(des, container);
|
|
|
|
|
|
2006-04-10 02:37:42 +02:00
|
|
|
bool flag = true;
|
|
|
|
|
|
2008-02-28 05:54:47 +01:00
|
|
|
// Handle the special case that this is a CASE scheme. In this
|
|
|
|
|
// case the PGenerate itself does not have the generated
|
|
|
|
|
// item. Look instead for the case ITEM that has a scope
|
|
|
|
|
// generated for it.
|
|
|
|
|
if (scheme_type == PGenerate::GS_CASE) {
|
|
|
|
|
if (debug_elaborate)
|
|
|
|
|
cerr << get_fileline() << ": debug: generate case"
|
|
|
|
|
<< " elaborate_sig in scope "
|
|
|
|
|
<< scope_path(container) << "." << endl;
|
|
|
|
|
|
|
|
|
|
typedef list<PGenerate*>::const_iterator generate_it_t;
|
2008-06-18 06:45:37 +02:00
|
|
|
for (generate_it_t cur = generate_schemes.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; cur != generate_schemes.end() ; ++ cur ) {
|
2008-02-28 05:54:47 +01:00
|
|
|
PGenerate*item = *cur;
|
2021-08-03 22:29:46 +02:00
|
|
|
if (item->directly_nested || !item->scope_list_.empty()) {
|
2008-02-28 05:54:47 +01:00
|
|
|
flag &= item->elaborate_sig(des, container);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return flag;
|
|
|
|
|
}
|
|
|
|
|
|
2006-04-10 02:37:42 +02:00
|
|
|
typedef list<NetScope*>::const_iterator scope_list_it_t;
|
|
|
|
|
for (scope_list_it_t cur = scope_list_.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; cur != scope_list_.end() ; ++ cur ) {
|
2006-04-10 02:37:42 +02:00
|
|
|
|
2007-06-22 04:04:48 +02:00
|
|
|
NetScope*scope = *cur;
|
|
|
|
|
|
|
|
|
|
if (scope->parent() != container)
|
|
|
|
|
continue;
|
|
|
|
|
|
2006-04-10 02:37:42 +02:00
|
|
|
if (debug_elaborate)
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": debug: Elaborate nets in "
|
2007-06-22 04:04:48 +02:00
|
|
|
<< "scope " << scope_path(*cur)
|
|
|
|
|
<< " in generate " << id_number << endl;
|
2025-10-21 07:45:05 +02:00
|
|
|
flag = elaborate_sig_(des, *cur) && flag;
|
2006-04-10 02:37:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return flag;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-28 04:45:22 +01:00
|
|
|
bool PGenerate::elaborate_sig_direct_(Design*des, NetScope*container) const
|
|
|
|
|
{
|
|
|
|
|
if (debug_elaborate)
|
|
|
|
|
cerr << get_fileline() << ": debug: "
|
|
|
|
|
<< "Direct nesting " << scope_name
|
|
|
|
|
<< " (scheme_type=" << scheme_type << ")"
|
|
|
|
|
<< " elaborate_sig in scope "
|
|
|
|
|
<< scope_path(container) << "." << endl;
|
|
|
|
|
|
|
|
|
|
// Elaborate_sig for a direct nested generated scheme knows
|
|
|
|
|
// that there are only sub_schemes to be elaborated. There
|
|
|
|
|
// should be exactly 1 active generate scheme, search for it
|
|
|
|
|
// using this loop.
|
|
|
|
|
bool flag = true;
|
|
|
|
|
typedef list<PGenerate*>::const_iterator generate_it_t;
|
|
|
|
|
for (generate_it_t cur = generate_schemes.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; cur != generate_schemes.end() ; ++ cur ) {
|
2008-11-28 04:45:22 +01:00
|
|
|
PGenerate*item = *cur;
|
2012-05-01 01:00:25 +02:00
|
|
|
if (item->scheme_type == PGenerate::GS_CASE) {
|
|
|
|
|
for (generate_it_t icur = item->generate_schemes.begin()
|
|
|
|
|
; icur != item->generate_schemes.end() ; ++ icur ) {
|
|
|
|
|
PGenerate*case_item = *icur;
|
2021-08-03 22:29:46 +02:00
|
|
|
if (case_item->directly_nested || !case_item->scope_list_.empty()) {
|
2012-05-01 01:00:25 +02:00
|
|
|
flag &= case_item->elaborate_sig(des, container);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2021-08-03 22:29:46 +02:00
|
|
|
if (item->directly_nested || !item->scope_list_.empty()) {
|
2012-05-01 01:00:25 +02:00
|
|
|
// Found the item, and it is direct nested.
|
|
|
|
|
flag &= item->elaborate_sig(des, container);
|
|
|
|
|
}
|
2008-11-28 04:45:22 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return flag;
|
|
|
|
|
}
|
|
|
|
|
|
2006-04-10 02:37:42 +02:00
|
|
|
bool PGenerate::elaborate_sig_(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
// Scan the declared PWires to elaborate the obvious signals
|
|
|
|
|
// in the current scope.
|
2008-02-25 04:40:54 +01:00
|
|
|
typedef map<perm_string,PWire*>::const_iterator wires_it_t;
|
2006-04-10 02:37:42 +02:00
|
|
|
for (wires_it_t wt = wires.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; wt != wires.end() ; ++ wt ) {
|
2006-04-10 02:37:42 +02:00
|
|
|
|
|
|
|
|
PWire*cur = (*wt).second;
|
|
|
|
|
|
|
|
|
|
if (debug_elaborate)
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": debug: Elaborate PWire "
|
2008-02-25 04:40:54 +01:00
|
|
|
<< cur->basename() << " in scope " << scope_path(scope) << endl;
|
2006-04-10 02:37:42 +02:00
|
|
|
|
|
|
|
|
cur->elaborate_sig(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-19 06:54:58 +02:00
|
|
|
elaborate_sig_funcs(des, scope, funcs);
|
|
|
|
|
elaborate_sig_tasks(des, scope, tasks);
|
|
|
|
|
|
2007-10-28 13:07:25 +01:00
|
|
|
typedef list<PGenerate*>::const_iterator generate_it_t;
|
2008-06-18 06:45:37 +02:00
|
|
|
for (generate_it_t cur = generate_schemes.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; cur != generate_schemes.end() ; ++ cur ) {
|
2007-10-28 13:07:25 +01:00
|
|
|
(*cur) -> elaborate_sig(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
2007-03-08 07:11:35 +01:00
|
|
|
typedef list<PGate*>::const_iterator pgate_list_it_t;
|
|
|
|
|
for (pgate_list_it_t cur = gates.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; cur != gates.end() ; ++ cur ) {
|
2007-03-08 07:11:35 +01:00
|
|
|
(*cur) ->elaborate_sig(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-19 05:10:10 +01:00
|
|
|
typedef list<PProcess*>::const_iterator proc_it_t;
|
|
|
|
|
for (proc_it_t cur = behaviors.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; cur != behaviors.end() ; ++ cur ) {
|
2008-11-19 05:10:10 +01:00
|
|
|
(*cur) -> statement() -> elaborate_sig(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2006-04-10 02:37:42 +02:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-07-30 20:25:43 +02:00
|
|
|
/*
|
2004-06-01 01:34:36 +02:00
|
|
|
* A function definition exists within an elaborated module. This
|
|
|
|
|
* matters when elaborating signals, as the ports of the function are
|
|
|
|
|
* created as signals/variables for each instance of the
|
|
|
|
|
* function. That is why PFunction has an elaborate_sig method.
|
2000-07-30 20:25:43 +02:00
|
|
|
*/
|
|
|
|
|
void PFunction::elaborate_sig(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
2011-04-05 21:43:54 +02:00
|
|
|
if (scope->elab_stage() > 1)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
scope->set_elab_stage(2);
|
|
|
|
|
|
2004-02-18 18:11:54 +01:00
|
|
|
perm_string fname = scope->basename();
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, scope->type() == NetScope::FUNC);
|
2000-07-30 20:25:43 +02:00
|
|
|
|
2008-02-25 04:40:54 +01:00
|
|
|
elaborate_sig_wires_(des, scope);
|
|
|
|
|
|
2013-04-21 01:27:51 +02:00
|
|
|
NetNet*ret_sig;
|
2013-07-12 04:07:49 +02:00
|
|
|
if (gn_system_verilog() && (fname=="new" || fname=="new@")) {
|
2013-04-21 01:27:51 +02:00
|
|
|
// Special case: this is a constructor, so the return
|
|
|
|
|
// signal is also the first argument. For example, the
|
|
|
|
|
// source code for the definition may be:
|
2014-04-25 03:36:49 +02:00
|
|
|
// function new(...);
|
2013-04-21 01:27:51 +02:00
|
|
|
// endfunction
|
2020-11-22 22:42:28 +01:00
|
|
|
// In this case, the "@" port (THIS_TOKEN) is the synthetic
|
|
|
|
|
// "this" argument and we also use it as a return value at
|
|
|
|
|
// the same time.
|
|
|
|
|
ret_sig = scope->find_signal(perm_string::literal(THIS_TOKEN));
|
2013-04-21 01:27:51 +02:00
|
|
|
ivl_assert(*this, ret_sig);
|
|
|
|
|
|
|
|
|
|
if (debug_elaborate)
|
|
|
|
|
cerr << get_fileline() << ": PFunction::elaborate_sig: "
|
|
|
|
|
<< "Scope " << scope_path(scope)
|
|
|
|
|
<< " is a CONSTRUCTOR, so use \"this\" argument"
|
|
|
|
|
<< " as return value." << endl;
|
2013-04-15 03:03:21 +02:00
|
|
|
|
|
|
|
|
} else {
|
2013-04-21 01:27:51 +02:00
|
|
|
ivl_type_t ret_type;
|
2013-04-15 03:03:21 +02:00
|
|
|
|
2013-04-21 01:27:51 +02:00
|
|
|
if (return_type_) {
|
2013-09-19 03:48:16 +02:00
|
|
|
if (dynamic_cast<const struct void_type_t*> (return_type_)) {
|
|
|
|
|
ret_type = 0;
|
|
|
|
|
} else {
|
2014-10-30 22:09:17 +01:00
|
|
|
ret_type = return_type_->elaborate_type(des, scope->parent());
|
2013-09-19 03:48:16 +02:00
|
|
|
ivl_assert(*this, ret_type);
|
|
|
|
|
}
|
2013-04-21 01:27:51 +02:00
|
|
|
} else {
|
2025-10-21 07:45:05 +02:00
|
|
|
const netvector_t*tmp = new netvector_t(IVL_VT_LOGIC);
|
2013-04-21 01:27:51 +02:00
|
|
|
ret_type = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-19 03:48:16 +02:00
|
|
|
if (ret_type) {
|
2014-04-25 03:36:49 +02:00
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << get_fileline() << ": PFunction::elaborate_sig: "
|
|
|
|
|
<< "return type: " << *ret_type << endl;
|
2014-10-31 19:38:37 +01:00
|
|
|
if (return_type_)
|
|
|
|
|
return_type_->pform_dump(cerr, 8);
|
2014-04-25 03:36:49 +02:00
|
|
|
}
|
2022-04-27 10:48:13 +02:00
|
|
|
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_type);
|
2013-09-19 03:48:16 +02:00
|
|
|
|
|
|
|
|
ret_sig->set_line(*this);
|
|
|
|
|
ret_sig->port_type(NetNet::POUTPUT);
|
|
|
|
|
} else {
|
|
|
|
|
ret_sig = 0;
|
|
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << get_fileline() << ": PFunction::elaborate_sig: "
|
|
|
|
|
<< "Detected that function is void." << endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-04-21 01:27:51 +02:00
|
|
|
}
|
2000-07-30 20:25:43 +02:00
|
|
|
|
2013-03-15 04:08:32 +01:00
|
|
|
vector<NetNet*>ports;
|
2013-09-15 04:54:35 +02:00
|
|
|
vector<NetExpr*>pdef;
|
2023-01-07 04:13:29 +01:00
|
|
|
vector<perm_string> port_names;
|
|
|
|
|
elaborate_sig_ports_(des, scope, ports, pdef, port_names);
|
2000-07-30 20:25:43 +02:00
|
|
|
|
2013-09-19 03:48:16 +02:00
|
|
|
NetFuncDef*def = new NetFuncDef(scope, ret_sig, ports, pdef);
|
2004-06-01 01:34:36 +02:00
|
|
|
|
2008-02-28 05:54:47 +01:00
|
|
|
if (debug_elaborate)
|
2014-04-25 03:36:49 +02:00
|
|
|
cerr << get_fileline() << ": PFunction::elaborate_sig: "
|
|
|
|
|
<< "Attach function definition " << scope_path(scope)
|
|
|
|
|
<< " with ret_sig width=" << (ret_sig? ret_sig->vector_width() : 0)
|
|
|
|
|
<< "." << endl;
|
2008-02-28 05:54:47 +01:00
|
|
|
|
2000-07-30 20:25:43 +02:00
|
|
|
scope->set_func_def(def);
|
2008-02-25 04:40:54 +01:00
|
|
|
|
|
|
|
|
// Look for further signals in the sub-statement
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_->elaborate_sig(des, scope);
|
2000-07-30 20:25:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A task definition is a scope within an elaborated module. When we
|
|
|
|
|
* are elaborating signals, the scopes have already been created, as
|
|
|
|
|
* have the reg objects that are the parameters of this task. The
|
|
|
|
|
* elaborate_sig method of PTask is therefore left to connect the
|
|
|
|
|
* signals to the ports of the NetTaskDef definition. We know for
|
|
|
|
|
* certain that signals exist (They are in my scope!) so the port
|
|
|
|
|
* binding is sure to work.
|
|
|
|
|
*/
|
|
|
|
|
void PTask::elaborate_sig(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, scope->type() == NetScope::TASK);
|
2000-07-30 20:25:43 +02:00
|
|
|
|
2008-02-25 04:40:54 +01:00
|
|
|
elaborate_sig_wires_(des, scope);
|
|
|
|
|
|
2013-03-15 04:08:32 +01:00
|
|
|
vector<NetNet*>ports;
|
2013-09-15 04:54:35 +02:00
|
|
|
vector<NetExpr*>pdefs;
|
2023-01-07 04:13:29 +01:00
|
|
|
vector<perm_string> port_names;
|
|
|
|
|
elaborate_sig_ports_(des, scope, ports, pdefs, port_names);
|
2013-09-15 04:54:35 +02:00
|
|
|
NetTaskDef*def = new NetTaskDef(scope, ports, pdefs);
|
2013-03-15 04:08:32 +01:00
|
|
|
scope->set_task_def(def);
|
2000-07-30 20:25:43 +02:00
|
|
|
|
2013-03-15 04:08:32 +01:00
|
|
|
// Look for further signals in the sub-statement
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_->elaborate_sig(des, scope);
|
|
|
|
|
}
|
2000-07-30 20:25:43 +02:00
|
|
|
|
2013-03-15 04:08:32 +01:00
|
|
|
void PTaskFunc::elaborate_sig_ports_(Design*des, NetScope*scope,
|
2023-01-07 04:13:29 +01:00
|
|
|
vector<NetNet*> &ports,
|
|
|
|
|
vector<NetExpr*> &pdefs,
|
|
|
|
|
vector<perm_string> &port_names) const
|
2013-03-15 04:08:32 +01:00
|
|
|
{
|
|
|
|
|
if (ports_ == 0) {
|
|
|
|
|
ports.clear();
|
2013-09-15 04:54:35 +02:00
|
|
|
pdefs.clear();
|
2023-01-07 04:13:29 +01:00
|
|
|
port_names.clear();
|
2013-03-15 04:08:32 +01:00
|
|
|
|
|
|
|
|
/* Make sure the function has at least one input
|
|
|
|
|
port. If it fails this test, print an error
|
|
|
|
|
message. Keep going so we can find more errors. */
|
|
|
|
|
if (scope->type()==NetScope::FUNC && !gn_system_verilog()) {
|
|
|
|
|
cerr << get_fileline() << ": error: "
|
|
|
|
|
<< "Function " << scope->basename()
|
|
|
|
|
<< " has no ports." << endl;
|
|
|
|
|
cerr << get_fileline() << ": : "
|
|
|
|
|
<< "Functions must have at least one input port." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
2000-07-30 20:25:43 +02:00
|
|
|
|
2013-03-15 04:08:32 +01:00
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ports.resize(ports_->size());
|
2013-09-15 04:54:35 +02:00
|
|
|
pdefs.resize(ports_->size());
|
2023-01-07 04:13:29 +01:00
|
|
|
port_names.resize(ports_->size());
|
2013-03-15 04:08:32 +01:00
|
|
|
|
|
|
|
|
for (size_t idx = 0 ; idx < ports_->size() ; idx += 1) {
|
|
|
|
|
|
2013-09-14 02:04:25 +02:00
|
|
|
perm_string port_name = ports_->at(idx).port->basename();
|
2013-03-15 04:08:32 +01:00
|
|
|
|
|
|
|
|
ports[idx] = 0;
|
2013-09-15 04:54:35 +02:00
|
|
|
pdefs[idx] = 0;
|
2013-03-15 04:08:32 +01:00
|
|
|
NetNet*tmp = scope->find_signal(port_name);
|
2013-09-15 04:54:35 +02:00
|
|
|
NetExpr*tmp_def = 0;
|
2000-07-30 20:25:43 +02:00
|
|
|
if (tmp == 0) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": internal error: "
|
2013-03-15 04:08:32 +01:00
|
|
|
<< "task/function " << scope_path(scope)
|
|
|
|
|
<< " is missing port " << port_name << "." << endl;
|
2000-07-30 20:25:43 +02:00
|
|
|
scope->dump(cerr);
|
2013-03-15 04:08:32 +01:00
|
|
|
cerr << get_fileline() << ": Continuing..." << endl;
|
2008-02-25 04:40:54 +01:00
|
|
|
des->errors += 1;
|
2013-03-15 04:08:32 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2015-06-20 22:39:45 +02:00
|
|
|
// If the port has a default expression, elaborate
|
|
|
|
|
// that expression here.
|
2013-09-14 02:04:25 +02:00
|
|
|
if (ports_->at(idx).defe != 0) {
|
2015-06-20 22:39:45 +02:00
|
|
|
if (tmp->port_type() == NetNet::PINPUT) {
|
2021-02-17 08:45:27 +01:00
|
|
|
// Elaborate a class port default in the context of
|
|
|
|
|
// the class type.
|
|
|
|
|
if (tmp->data_type() == IVL_VT_CLASS) {
|
|
|
|
|
tmp_def = elab_and_eval(des, scope,
|
|
|
|
|
ports_->at(idx).defe,
|
|
|
|
|
tmp->net_type(),
|
|
|
|
|
scope->need_const_func());
|
|
|
|
|
} else {
|
|
|
|
|
tmp_def = elab_and_eval(des, scope,
|
|
|
|
|
ports_->at(idx).defe,
|
|
|
|
|
-1,
|
|
|
|
|
scope->need_const_func());
|
|
|
|
|
}
|
2015-06-20 22:39:45 +02:00
|
|
|
if (tmp_def == 0) {
|
|
|
|
|
cerr << get_fileline()
|
|
|
|
|
<< ": error: Unable to evaluate "
|
|
|
|
|
<< *ports_->at(idx).defe
|
|
|
|
|
<< " as a port default expression." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
cerr << get_fileline() << ": sorry: Default arguments "
|
|
|
|
|
"for subroutine output or inout ports are not "
|
|
|
|
|
"yet supported." << endl;
|
2013-09-15 04:54:35 +02:00
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
2013-09-14 02:04:25 +02:00
|
|
|
}
|
|
|
|
|
|
2013-03-15 04:08:32 +01:00
|
|
|
if (tmp->port_type() == NetNet::NOT_A_PORT) {
|
|
|
|
|
cerr << get_fileline() << ": internal error: "
|
|
|
|
|
<< "task/function " << scope_path(scope)
|
|
|
|
|
<< " port " << port_name
|
|
|
|
|
<< " is a port but is not a port?" << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
scope->dump(cerr);
|
|
|
|
|
continue;
|
2000-07-30 20:25:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ports[idx] = tmp;
|
2023-01-07 04:13:29 +01:00
|
|
|
port_names[idx] = port_name;
|
2013-09-15 04:54:35 +02:00
|
|
|
pdefs[idx] = tmp_def;
|
2013-03-15 04:08:32 +01:00
|
|
|
if (scope->type()==NetScope::FUNC && tmp->port_type()!=NetNet::PINPUT) {
|
|
|
|
|
cerr << tmp->get_fileline() << ": error: "
|
|
|
|
|
<< "Function " << scope_path(scope)
|
|
|
|
|
<< " port " << port_name
|
2013-09-15 04:54:35 +02:00
|
|
|
<< " is not an input port." << endl;
|
2013-03-15 04:08:32 +01:00
|
|
|
cerr << tmp->get_fileline() << ": : "
|
|
|
|
|
<< "Function arguments must be input ports." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
2019-08-02 16:34:31 +02:00
|
|
|
if (tmp->unpacked_dimensions() != 0) {
|
|
|
|
|
cerr << get_fileline() << ": sorry: Subroutine ports with "
|
|
|
|
|
"unpacked dimensions are not yet supported." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
2000-07-30 20:25:43 +02:00
|
|
|
}
|
2008-02-25 04:40:54 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PBlock::elaborate_sig(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
NetScope*my_scope = scope;
|
|
|
|
|
|
|
|
|
|
if (pscope_name() != 0) {
|
|
|
|
|
hname_t use_name (pscope_name());
|
|
|
|
|
my_scope = scope->child(use_name);
|
|
|
|
|
if (my_scope == 0) {
|
|
|
|
|
cerr << get_fileline() << ": internal error: "
|
|
|
|
|
<< "Unable to find child scope " << pscope_name()
|
|
|
|
|
<< " in this context?" << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
my_scope = scope;
|
|
|
|
|
} else {
|
|
|
|
|
if (debug_elaborate)
|
|
|
|
|
cerr << get_fileline() << ": debug: "
|
|
|
|
|
<< "elaborate_sig descending into "
|
|
|
|
|
<< scope_path(my_scope) << "." << endl;
|
|
|
|
|
|
|
|
|
|
elaborate_sig_wires_(des, my_scope);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// elaborate_sig in the statements included in the
|
|
|
|
|
// block. There may be named blocks in there.
|
2011-09-17 21:10:05 +02:00
|
|
|
for (unsigned idx = 0 ; idx < list_.size() ; idx += 1)
|
2008-02-25 04:40:54 +01:00
|
|
|
list_[idx] -> elaborate_sig(des, my_scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PCase::elaborate_sig(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
if (items_ == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
2022-02-17 10:48:43 +01:00
|
|
|
for (unsigned idx = 0 ; idx < items_->size() ; idx += 1) {
|
2008-02-25 04:40:54 +01:00
|
|
|
if ( (*items_)[idx]->stat )
|
|
|
|
|
(*items_)[idx]->stat ->elaborate_sig(des,scope);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PCondit::elaborate_sig(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
if (if_)
|
|
|
|
|
if_->elaborate_sig(des, scope);
|
|
|
|
|
if (else_)
|
|
|
|
|
else_->elaborate_sig(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PDelayStatement::elaborate_sig(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_->elaborate_sig(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-17 05:01:06 +02:00
|
|
|
void PDoWhile::elaborate_sig(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_->elaborate_sig(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
2008-02-25 04:40:54 +01:00
|
|
|
void PEventStatement::elaborate_sig(Design*des, NetScope*scope) const
|
2014-08-22 00:47:46 +02:00
|
|
|
{
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_->elaborate_sig(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PForeach::elaborate_sig(Design*des, NetScope*scope) const
|
2008-02-25 04:40:54 +01:00
|
|
|
{
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_->elaborate_sig(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PForever::elaborate_sig(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_->elaborate_sig(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PForStatement::elaborate_sig(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_->elaborate_sig(des, scope);
|
2000-07-30 20:25:43 +02:00
|
|
|
}
|
2000-05-02 18:27:38 +02:00
|
|
|
|
2008-05-15 05:19:51 +02:00
|
|
|
void PRepeat::elaborate_sig(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_->elaborate_sig(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PWhile::elaborate_sig(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_->elaborate_sig(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-06 15:24:20 +01:00
|
|
|
bool test_ranges_eeq(const netranges_t&lef, const netranges_t&rig)
|
2012-02-06 02:41:11 +01:00
|
|
|
{
|
|
|
|
|
if (lef.size() != rig.size())
|
|
|
|
|
return false;
|
|
|
|
|
|
2022-01-06 15:24:20 +01:00
|
|
|
netranges_t::const_iterator lcur = lef.begin();
|
|
|
|
|
netranges_t::const_iterator rcur = rig.begin();
|
2012-02-06 02:41:11 +01:00
|
|
|
while (lcur != lef.end()) {
|
2012-07-14 03:41:41 +02:00
|
|
|
if (lcur->get_msb() != rcur->get_msb())
|
2012-02-06 02:41:11 +01:00
|
|
|
return false;
|
2012-07-14 03:41:41 +02:00
|
|
|
if (lcur->get_lsb() != rcur->get_lsb())
|
2012-02-06 02:41:11 +01:00
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
++ lcur;
|
|
|
|
|
++ rcur;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-04 09:12:50 +01:00
|
|
|
ivl_type_t PWire::elaborate_type(Design*des, NetScope*scope,
|
2022-01-06 15:24:20 +01:00
|
|
|
const netranges_t &packed_dimensions) const
|
2022-03-04 09:12:50 +01:00
|
|
|
{
|
2025-10-21 07:45:05 +02:00
|
|
|
const vector_type_t *vec_type = dynamic_cast<vector_type_t*>(set_data_type_.get());
|
2022-03-24 11:05:33 +01:00
|
|
|
if (set_data_type_ && !vec_type) {
|
2022-03-04 09:12:50 +01:00
|
|
|
ivl_assert(*this, packed_dimensions.empty());
|
2022-03-24 11:05:33 +01:00
|
|
|
return set_data_type_->elaborate_type(des, scope);
|
2022-03-04 09:12:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Fallback method. Create vector type.
|
|
|
|
|
|
2022-04-23 12:24:26 +02:00
|
|
|
ivl_variable_type_t use_data_type;
|
|
|
|
|
if (vec_type) {
|
|
|
|
|
use_data_type = vec_type->base_type;
|
|
|
|
|
} else {
|
|
|
|
|
use_data_type = IVL_VT_LOGIC;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-04 09:12:50 +01:00
|
|
|
if (use_data_type == IVL_VT_NO_TYPE) {
|
|
|
|
|
use_data_type = IVL_VT_LOGIC;
|
|
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
|
|
|
|
<< "Signal " << name_
|
|
|
|
|
<< " in scope " << scope_path(scope)
|
|
|
|
|
<< " defaults to data type " << use_data_type << endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ivl_assert(*this, use_data_type == IVL_VT_LOGIC ||
|
2022-01-09 00:27:56 +01:00
|
|
|
use_data_type == IVL_VT_BOOL);
|
2022-03-04 09:12:50 +01:00
|
|
|
|
|
|
|
|
netvector_t*vec = new netvector_t(packed_dimensions, use_data_type);
|
|
|
|
|
vec->set_signed(get_signed());
|
|
|
|
|
|
|
|
|
|
return vec;
|
|
|
|
|
}
|
|
|
|
|
|
2000-05-02 18:27:38 +02:00
|
|
|
/*
|
|
|
|
|
* Elaborate a source wire. The "wire" is the declaration of wires,
|
|
|
|
|
* registers, ports and memories. The parser has already merged the
|
2009-03-11 17:18:30 +01:00
|
|
|
* multiple properties of a wire (i.e., "input wire"), so come the
|
|
|
|
|
* elaboration this creates an object in the design that represents the
|
2000-05-02 18:27:38 +02:00
|
|
|
* defined item.
|
|
|
|
|
*/
|
2024-02-12 19:38:00 +01:00
|
|
|
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope)
|
2000-05-02 18:27:38 +02:00
|
|
|
{
|
2015-04-26 13:00:21 +02:00
|
|
|
// This sets the vector or array dimension size that will
|
|
|
|
|
// cause a warning. For now, these warnings are permanently
|
|
|
|
|
// enabled.
|
|
|
|
|
const long warn_dimension_size = 1 << 30;
|
|
|
|
|
|
2024-02-12 19:38:00 +01:00
|
|
|
// Check if we elaborated this signal earlier because it was
|
|
|
|
|
// used in another declaration.
|
|
|
|
|
if (NetNet*sig = scope->find_signal(name_))
|
|
|
|
|
return sig;
|
|
|
|
|
|
|
|
|
|
if (is_elaborating_) {
|
|
|
|
|
cerr << get_fileline() << ": error: Circular dependency "
|
|
|
|
|
"detected in declaration of '" << name_ << "'."
|
|
|
|
|
<< endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
is_elaborating_ = true;
|
|
|
|
|
|
2000-05-02 18:27:38 +02:00
|
|
|
NetNet::Type wtype = type_;
|
2022-03-04 11:24:08 +01:00
|
|
|
if (wtype == NetNet::IMPLICIT)
|
2000-05-02 18:27:38 +02:00
|
|
|
wtype = NetNet::WIRE;
|
2022-03-04 11:24:08 +01:00
|
|
|
|
2019-10-30 06:58:48 +01:00
|
|
|
// Certain contexts, such as arguments to functions, presume
|
|
|
|
|
// "reg" instead of "wire". The parser reports these as
|
2022-03-04 11:24:08 +01:00
|
|
|
// IMPLICIT_REG.
|
|
|
|
|
if (wtype == NetNet::IMPLICIT_REG)
|
2000-05-02 18:27:38 +02:00
|
|
|
wtype = NetNet::REG;
|
2019-10-30 06:58:48 +01:00
|
|
|
|
|
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
|
|
|
|
<< "Signal " << basename()
|
2022-04-23 12:24:26 +02:00
|
|
|
<< ", wtype=" << wtype;
|
|
|
|
|
if (set_data_type_)
|
|
|
|
|
cerr << ", set_data_type_=" << *set_data_type_;
|
|
|
|
|
cerr << ", unpacked_.size()=" << unpacked_.size()
|
2019-10-30 06:58:48 +01:00
|
|
|
<< endl;
|
2009-04-15 01:08:27 +02:00
|
|
|
}
|
2000-05-02 18:27:38 +02:00
|
|
|
|
|
|
|
|
unsigned wid = 1;
|
2022-01-06 15:24:20 +01:00
|
|
|
netranges_t packed_dimensions;
|
2000-05-02 18:27:38 +02:00
|
|
|
|
2007-08-22 04:52:42 +02:00
|
|
|
des->errors += error_cnt_;
|
|
|
|
|
|
|
|
|
|
if (port_set_ || net_set_) {
|
2016-02-07 01:07:50 +01:00
|
|
|
|
|
|
|
|
if (warn_implicit_dimensions
|
|
|
|
|
&& port_set_ && net_set_
|
|
|
|
|
&& net_.empty() && !port_.empty()) {
|
|
|
|
|
cerr << get_fileline() << ": warning: "
|
|
|
|
|
<< "var/net declaration of " << basename()
|
|
|
|
|
<< " inherits dimensions from port declaration." << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (warn_implicit_dimensions
|
|
|
|
|
&& port_set_ && net_set_
|
2016-02-10 19:56:14 +01:00
|
|
|
&& port_.empty() && !net_.empty()) {
|
2016-02-07 01:07:50 +01:00
|
|
|
cerr << get_fileline() << ": warning: "
|
|
|
|
|
<< "Port declaration of " << basename()
|
|
|
|
|
<< " inherits dimensions from var/net." << endl;
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-14 01:29:49 +02:00
|
|
|
bool dimensions_ok = true;
|
2022-01-06 15:24:20 +01:00
|
|
|
netranges_t plist, nlist;
|
2007-08-22 04:52:42 +02:00
|
|
|
/* If they exist get the port definition MSB and LSB */
|
2012-02-05 01:19:27 +01:00
|
|
|
if (port_set_ && !port_.empty()) {
|
2013-06-03 01:56:46 +02:00
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
|
|
|
|
<< "Evaluate ranges for port " << basename() << endl;
|
|
|
|
|
}
|
2019-09-14 01:29:49 +02:00
|
|
|
dimensions_ok &= evaluate_ranges(des, scope, this, plist, port_);
|
2007-08-22 04:52:42 +02:00
|
|
|
}
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, port_set_ || port_.empty());
|
2001-02-10 21:29:39 +01:00
|
|
|
|
2007-08-22 04:52:42 +02:00
|
|
|
/* If they exist get the net/etc. definition MSB and LSB */
|
2019-09-14 01:29:49 +02:00
|
|
|
if (net_set_ && !net_.empty() && dimensions_ok) {
|
2012-02-06 02:41:11 +01:00
|
|
|
nlist.clear();
|
2013-06-03 01:56:46 +02:00
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
|
|
|
|
<< "Evaluate ranges for net " << basename() << endl;
|
|
|
|
|
}
|
2022-03-24 11:05:33 +01:00
|
|
|
dimensions_ok &= evaluate_ranges(des, scope, this, nlist, net_);
|
2002-01-26 06:28:28 +01:00
|
|
|
}
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, net_set_ || net_.empty());
|
2012-02-06 02:41:11 +01:00
|
|
|
|
2013-06-03 01:56:46 +02:00
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << get_fileline() << ": PWire::elaborate_sig: "
|
|
|
|
|
<< "Calculated ranges for " << basename()
|
|
|
|
|
<< ". Now check for consistency." << endl;
|
|
|
|
|
}
|
|
|
|
|
|
2022-03-13 09:50:52 +01:00
|
|
|
/* 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) {
|
2007-08-22 04:52:42 +02:00
|
|
|
/* Scalar port with a vector net/etc. definition */
|
2012-02-05 01:19:27 +01:00
|
|
|
if (port_.empty()) {
|
2022-12-18 13:12:26 +01:00
|
|
|
if (gn_io_range_error_flag) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline()
|
2022-12-18 13:12:26 +01:00
|
|
|
<< ": error: Scalar port ``" << name_
|
2012-02-06 02:41:11 +01:00
|
|
|
<< "'' has a vectored net declaration "
|
|
|
|
|
<< nlist << "." << endl;
|
2022-12-18 13:12:26 +01:00
|
|
|
des->errors += 1;
|
|
|
|
|
} else if (warn_anachronisms) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline()
|
2022-12-18 13:12:26 +01:00
|
|
|
<< ": warning: Scalar port ``" << name_
|
2012-02-06 02:41:11 +01:00
|
|
|
<< "'' has a vectored net declaration "
|
|
|
|
|
<< nlist << "." << endl;
|
2007-08-22 04:52:42 +02:00
|
|
|
}
|
|
|
|
|
}
|
2002-01-26 06:28:28 +01:00
|
|
|
|
2007-08-22 04:52:42 +02:00
|
|
|
/* Vectored port with a scalar net/etc. definition */
|
2012-02-05 01:19:27 +01:00
|
|
|
if (net_.empty()) {
|
2012-04-10 23:29:28 +02:00
|
|
|
cerr << port_.front().first->get_fileline()
|
2007-08-22 04:52:42 +02:00
|
|
|
<< ": error: Vectored port ``"
|
2012-02-06 02:41:11 +01:00
|
|
|
<< name_ << "'' " << plist
|
|
|
|
|
<< " has a scalar net declaration at "
|
2007-12-20 18:31:01 +01:00
|
|
|
<< get_fileline() << "." << endl;
|
2007-08-22 04:52:42 +02:00
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
2002-01-26 06:28:28 +01:00
|
|
|
|
2007-08-22 04:52:42 +02:00
|
|
|
/* Both vectored, but they have different ranges. */
|
2012-02-05 01:19:27 +01:00
|
|
|
if (!port_.empty() && !net_.empty()) {
|
2012-04-10 23:29:28 +02:00
|
|
|
cerr << port_.front().first->get_fileline()
|
2007-08-22 04:52:42 +02:00
|
|
|
<< ": error: Vectored port ``"
|
2012-02-06 02:41:11 +01:00
|
|
|
<< name_ << "'' " << plist
|
|
|
|
|
<< " has a net declaration " << nlist
|
2012-04-10 23:29:28 +02:00
|
|
|
<< " at " << net_.front().first->get_fileline()
|
2007-08-22 04:52:42 +02:00
|
|
|
<< " that does not match." << endl;
|
2000-05-02 18:27:38 +02:00
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
2007-08-22 04:52:42 +02:00
|
|
|
}
|
2000-05-02 18:27:38 +02:00
|
|
|
|
2022-03-13 09:50:52 +01:00
|
|
|
packed_dimensions = net_set_ ? nlist : plist;
|
2012-03-26 02:59:05 +02:00
|
|
|
wid = netrange_width(packed_dimensions);
|
2015-04-26 13:00:21 +02:00
|
|
|
if (wid > warn_dimension_size) {
|
|
|
|
|
cerr << get_fileline() << ": warning: Vector size "
|
|
|
|
|
"is greater than " << warn_dimension_size
|
|
|
|
|
<< "." << endl;
|
|
|
|
|
}
|
2000-05-02 18:27:38 +02:00
|
|
|
}
|
|
|
|
|
|
2002-05-23 05:08:50 +02:00
|
|
|
unsigned nattrib = 0;
|
2025-10-21 07:45:05 +02:00
|
|
|
const attrib_list_t*attrib_list = evaluate_attributes(attributes, nattrib,
|
|
|
|
|
des, scope);
|
2002-05-23 05:08:50 +02:00
|
|
|
|
2007-01-16 06:44:14 +01:00
|
|
|
/* 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:
|
2005-02-13 02:15:07 +01:00
|
|
|
|
2007-01-16 06:44:14 +01:00
|
|
|
supply0 foo;
|
2005-02-13 02:15:07 +01:00
|
|
|
|
2007-01-16 06:44:14 +01:00
|
|
|
to:
|
2005-02-13 02:15:07 +01:00
|
|
|
|
2007-01-16 06:44:14 +01:00
|
|
|
wire foo;
|
|
|
|
|
pulldown #(supply0) (foo);
|
2005-02-13 02:15:07 +01:00
|
|
|
|
2007-01-16 06:44:14 +01:00
|
|
|
This reduces the backend burden, and behaves exactly
|
|
|
|
|
the same. */
|
2005-02-13 02:15:07 +01:00
|
|
|
|
2007-01-16 06:44:14 +01:00
|
|
|
NetLogic*pull = 0;
|
|
|
|
|
if (wtype == NetNet::SUPPLY0 || wtype == NetNet::SUPPLY1) {
|
2016-03-15 11:48:12 +01:00
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << get_fileline() << ": debug: "
|
|
|
|
|
<< "Generate a SUPPLY pull for the ";
|
|
|
|
|
if (wtype == NetNet::SUPPLY0) cerr << "supply0";
|
|
|
|
|
else cerr << "supply1";
|
|
|
|
|
cerr << " net." << endl;
|
|
|
|
|
}
|
|
|
|
|
|
2007-01-16 06:44:14 +01:00
|
|
|
NetLogic::TYPE pull_type = (wtype==NetNet::SUPPLY1)
|
|
|
|
|
? NetLogic::PULLUP
|
|
|
|
|
: NetLogic::PULLDOWN;
|
|
|
|
|
pull = new NetLogic(scope, scope->local_symbol(),
|
|
|
|
|
1, pull_type, wid);
|
|
|
|
|
pull->set_line(*this);
|
2010-03-16 23:16:53 +01:00
|
|
|
pull->pin(0).drive0(IVL_DR_SUPPLY);
|
|
|
|
|
pull->pin(0).drive1(IVL_DR_SUPPLY);
|
2007-01-16 06:44:14 +01:00
|
|
|
des->add_node(pull);
|
|
|
|
|
wtype = NetNet::WIRE;
|
|
|
|
|
}
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2022-03-24 11:05:33 +01:00
|
|
|
ivl_type_t type = elaborate_type(des, scope, packed_dimensions);
|
2022-03-26 16:40:32 +01:00
|
|
|
// Create the type for the unpacked dimensions. If the
|
|
|
|
|
// unpacked_dimensions are empty this will just return the base type.
|
2022-03-24 11:05:33 +01:00
|
|
|
type = elaborate_array_type(des, scope, *this, type, unpacked_);
|
2022-03-26 16:40:32 +01:00
|
|
|
|
2022-01-06 15:41:18 +01:00
|
|
|
netranges_t unpacked_dimensions;
|
2022-03-26 16:40:32 +01:00
|
|
|
// If this is an unpacked array extract the base type and unpacked
|
|
|
|
|
// dimensions as these are separate properties of the NetNet.
|
2022-03-20 16:25:51 +01:00
|
|
|
while (const netuarray_t *atype = dynamic_cast<const netuarray_t*>(type)) {
|
2022-03-26 16:40:32 +01:00
|
|
|
unpacked_dimensions.insert(unpacked_dimensions.begin(),
|
|
|
|
|
atype->static_dimensions().begin(),
|
|
|
|
|
atype->static_dimensions().end());
|
|
|
|
|
type = atype->element_type();
|
|
|
|
|
}
|
2011-12-11 19:28:04 +01:00
|
|
|
|
2022-03-26 16:40:32 +01:00
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << get_fileline() << ": debug: Create signal " << wtype;
|
|
|
|
|
if (set_data_type_)
|
|
|
|
|
cout << " " << *set_data_type_;
|
2023-12-09 21:49:25 +01:00
|
|
|
cout << " " << name_ << unpacked_dimensions << " in scope "
|
2022-03-26 16:40:32 +01:00
|
|
|
<< scope_path(scope) << endl;
|
2007-01-29 03:07:34 +01:00
|
|
|
}
|
|
|
|
|
|
2022-03-26 16:40:32 +01:00
|
|
|
NetNet*sig = new NetNet(scope, name_, wtype, unpacked_dimensions, type);
|
|
|
|
|
|
2012-09-15 19:27:43 +02:00
|
|
|
if (wtype == NetNet::WIRE) sig->devirtualize_pins();
|
2007-01-16 06:44:14 +01:00
|
|
|
sig->set_line(*this);
|
|
|
|
|
sig->port_type(port_type_);
|
2024-02-18 17:47:10 +01:00
|
|
|
sig->lexical_pos(lexical_pos_);
|
2005-02-13 02:15:07 +01:00
|
|
|
|
2008-11-02 17:10:41 +01:00
|
|
|
if (ivl_discipline_t dis = get_discipline()) {
|
2008-08-05 05:54:05 +02:00
|
|
|
sig->set_discipline(dis);
|
|
|
|
|
}
|
|
|
|
|
|
2007-01-16 06:44:14 +01:00
|
|
|
if (pull)
|
|
|
|
|
connect(sig->pin(0), pull->pin(0));
|
|
|
|
|
|
|
|
|
|
for (unsigned idx = 0 ; idx < nattrib ; idx += 1)
|
|
|
|
|
sig->attribute(attrib_list[idx].key, attrib_list[idx].val);
|
2007-05-24 06:07:11 +02:00
|
|
|
|
2022-01-03 21:24:23 +01:00
|
|
|
sig->set_const(is_const_);
|
|
|
|
|
|
2024-02-12 19:38:00 +01:00
|
|
|
scope->rem_signal_placeholder(this);
|
|
|
|
|
is_elaborating_ = false;
|
|
|
|
|
|
2007-05-24 06:07:11 +02:00
|
|
|
return sig;
|
2000-05-02 18:27:38 +02:00
|
|
|
}
|