2000-05-02 18:27:38 +02:00
|
|
|
/*
|
2012-02-05 01:19:27 +01:00
|
|
|
* Copyright (c) 2000-2012 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"
|
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"
|
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-07-14 03:41:41 +02:00
|
|
|
# include "netenum.h"
|
2011-12-04 02:16:01 +01:00
|
|
|
# include "netstruct.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"
|
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;
|
|
|
|
|
|
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:
|
|
|
|
|
assert(0);;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
2008-02-25 04:40:54 +01:00
|
|
|
bool PScope::elaborate_sig_wires_(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
bool flag = true;
|
2001-01-07 08:00:31 +01:00
|
|
|
|
2008-02-25 04:40:54 +01:00
|
|
|
for (map<perm_string,PWire*>::const_iterator wt = wires.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; wt != wires.end() ; ++ wt ) {
|
2001-01-07 08:00:31 +01:00
|
|
|
|
2008-02-25 04:40:54 +01:00
|
|
|
PWire*cur = (*wt).second;
|
|
|
|
|
NetNet*sig = cur->elaborate_sig(des, scope);
|
2007-05-24 06:07:11 +02:00
|
|
|
|
2012-02-25 19:19:48 +01:00
|
|
|
if (sig && (sig->scope() == scope)
|
|
|
|
|
&& (sig->port_type() == NetNet::PREF)) {
|
|
|
|
|
|
|
|
|
|
cerr << cur->get_fileline() << ": sorry: "
|
|
|
|
|
<< "Reference ports not supported yet." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2007-05-24 06:07:11 +02:00
|
|
|
|
2008-02-25 04:40:54 +01:00
|
|
|
/* 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)) {
|
|
|
|
|
|
2010-04-25 23:15:35 +02:00
|
|
|
cerr << cur->get_fileline() << ": error: Port "
|
|
|
|
|
<< cur->basename() << " of module "
|
2008-02-25 04:40:54 +01:00
|
|
|
<< scope->module_name()
|
2010-04-25 23:15:35 +02:00
|
|
|
<< " is declared as input and as a reg type." << endl;
|
2008-02-25 04:40:54 +01:00
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sig && (sig->scope() == scope)
|
|
|
|
|
&& (scope->type() == NetScope::MODULE)
|
|
|
|
|
&& (sig->port_type() == NetNet::PINOUT)
|
|
|
|
|
&& (sig->type() == NetNet::REG)) {
|
|
|
|
|
|
2010-04-25 23:15:35 +02:00
|
|
|
cerr << cur->get_fileline() << ": error: Port "
|
|
|
|
|
<< cur->basename() << " of module "
|
2008-02-25 04:40:54 +01:00
|
|
|
<< scope->module_name()
|
2010-04-25 23:15:35 +02:00
|
|
|
<< " 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;
|
2008-02-25 04:40:54 +01:00
|
|
|
des->errors += 1;
|
2001-01-07 08:00:31 +01:00
|
|
|
}
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
(*cur).second->elaborate_sig(des, fscope);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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) );
|
|
|
|
|
assert(tscope);
|
|
|
|
|
(*cur).second->elaborate_sig(des, tscope);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-04 18:41:51 +02:00
|
|
|
|
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) {
|
2007-05-24 06:07:11 +02:00
|
|
|
pform_name_t port_path (pp->expr[cc]->path());
|
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);
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
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,
|
|
|
|
|
Module*rmod) const
|
|
|
|
|
{
|
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];
|
|
|
|
|
assert(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;
|
|
|
|
|
}
|
|
|
|
|
assert(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
|
|
|
{
|
2008-11-28 04:45:22 +01:00
|
|
|
if (direct_nested_)
|
|
|
|
|
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;
|
2008-11-28 04:45:22 +01:00
|
|
|
if (item->direct_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;
|
2006-04-10 02:37:42 +02:00
|
|
|
flag = elaborate_sig_(des, *cur) & flag;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
if (case_item->direct_nested_ || !case_item->scope_list_.empty()) {
|
|
|
|
|
flag &= case_item->elaborate_sig(des, container);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if (item->direct_nested_ || !item->scope_list_.empty()) {
|
|
|
|
|
// 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();
|
2000-07-30 20:25:43 +02:00
|
|
|
assert(scope->type() == NetScope::FUNC);
|
|
|
|
|
|
2008-02-25 04:40:54 +01:00
|
|
|
elaborate_sig_wires_(des, scope);
|
|
|
|
|
|
2002-01-23 04:35:17 +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. */
|
2011-09-17 21:10:05 +02:00
|
|
|
if (ports_ == 0 && !gn_system_verilog()) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": error: Function " << fname
|
2002-01-23 04:35:17 +01:00
|
|
|
<< " has no ports." << endl;
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": : Functions must have"
|
2002-01-23 04:35:17 +01:00
|
|
|
<< " at least one input port." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2004-06-01 01:34:36 +02:00
|
|
|
NetNet*ret_sig = 0;
|
2012-09-15 19:27:43 +02:00
|
|
|
netvector_t*ret_vec = 0;
|
2004-06-01 01:34:36 +02:00
|
|
|
|
|
|
|
|
/* Create the signals/variables of the return value and write
|
|
|
|
|
them into the function scope. */
|
|
|
|
|
switch (return_type_.type) {
|
|
|
|
|
|
|
|
|
|
case PTF_REG:
|
2007-03-06 06:22:49 +01:00
|
|
|
case PTF_REG_S:
|
2004-06-01 01:34:36 +02:00
|
|
|
if (return_type_.range) {
|
2012-03-03 03:34:43 +01:00
|
|
|
ivl_assert(*this, return_type_.range->size() == 1);
|
2012-04-10 23:29:28 +02:00
|
|
|
pform_range_t&return_range = return_type_.range->front();
|
2008-11-27 00:37:38 +01:00
|
|
|
|
2012-04-10 23:29:28 +02:00
|
|
|
NetExpr*me = elab_and_eval(des, scope,
|
|
|
|
|
return_range.first, -1,
|
|
|
|
|
true);
|
2004-06-01 01:34:36 +02:00
|
|
|
assert(me);
|
2012-04-10 23:29:28 +02:00
|
|
|
NetExpr*le = elab_and_eval(des, scope,
|
|
|
|
|
return_range.second, -1,
|
|
|
|
|
true);
|
2004-06-01 01:34:36 +02:00
|
|
|
assert(le);
|
|
|
|
|
|
|
|
|
|
long mnum = 0, lnum = 0;
|
2010-10-03 01:29:30 +02:00
|
|
|
if ( ! get_const_argument(me, mnum) ) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << me->get_fileline() << ": error: "
|
2004-06-01 01:34:36 +02:00
|
|
|
"Unable to evaluate constant expression "
|
|
|
|
|
<< *me << "." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2010-10-03 01:29:30 +02:00
|
|
|
if ( ! get_const_argument(le, lnum) ) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << le->get_fileline() << ": error: "
|
2004-06-01 01:34:36 +02:00
|
|
|
"Unable to evaluate constant expression "
|
|
|
|
|
<< *le << "." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-26 02:59:05 +02:00
|
|
|
list<netrange_t> packed;
|
|
|
|
|
packed.push_back(netrange_t(mnum, lnum));
|
2012-09-15 19:27:43 +02:00
|
|
|
ret_vec = new netvector_t(packed, IVL_VT_LOGIC);
|
2012-09-16 02:16:05 +02:00
|
|
|
ret_vec->set_signed(return_type_.type == PTF_REG_S);
|
|
|
|
|
ret_vec->set_scalar(false);
|
2012-09-15 19:27:43 +02:00
|
|
|
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
|
2004-06-01 01:34:36 +02:00
|
|
|
|
|
|
|
|
} else {
|
2012-09-15 19:27:43 +02:00
|
|
|
ret_vec = new netvector_t(IVL_VT_LOGIC);
|
2012-09-16 02:16:05 +02:00
|
|
|
ret_vec->set_signed(return_type_.type == PTF_REG_S);
|
|
|
|
|
ret_vec->set_scalar(true);
|
2012-09-15 19:27:43 +02:00
|
|
|
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
|
2004-06-01 01:34:36 +02:00
|
|
|
}
|
|
|
|
|
ret_sig->set_line(*this);
|
|
|
|
|
ret_sig->port_type(NetNet::POUTPUT);
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PTF_INTEGER:
|
2012-09-15 19:27:43 +02:00
|
|
|
ret_vec = new netvector_t(IVL_VT_LOGIC, integer_width-1,0);
|
2012-09-16 02:16:05 +02:00
|
|
|
ret_vec->set_signed(true);
|
|
|
|
|
ret_vec->set_isint(true);
|
|
|
|
|
ret_vec->set_scalar(false);
|
2012-09-15 19:27:43 +02:00
|
|
|
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
|
2004-06-01 01:34:36 +02:00
|
|
|
ret_sig->set_line(*this);
|
|
|
|
|
ret_sig->port_type(NetNet::POUTPUT);
|
|
|
|
|
break;
|
|
|
|
|
|
2004-09-28 00:34:10 +02:00
|
|
|
case PTF_TIME:
|
2012-09-15 19:27:43 +02:00
|
|
|
ret_vec = new netvector_t(IVL_VT_LOGIC, 64-1,0);
|
2012-09-16 02:16:05 +02:00
|
|
|
ret_vec->set_isint(false);
|
|
|
|
|
ret_vec->set_scalar(false);
|
2012-09-15 19:27:43 +02:00
|
|
|
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
|
2004-09-28 00:34:10 +02:00
|
|
|
ret_sig->set_line(*this);
|
|
|
|
|
ret_sig->port_type(NetNet::POUTPUT);
|
|
|
|
|
break;
|
|
|
|
|
|
2004-06-01 01:34:36 +02:00
|
|
|
case PTF_REAL:
|
|
|
|
|
case PTF_REALTIME:
|
2012-09-15 19:27:43 +02:00
|
|
|
ret_vec = new netvector_t(IVL_VT_REAL);
|
2012-09-16 02:16:05 +02:00
|
|
|
ret_vec->set_signed(true);
|
|
|
|
|
ret_vec->set_isint(false);
|
|
|
|
|
ret_vec->set_scalar(true);
|
2012-09-15 19:27:43 +02:00
|
|
|
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
|
2005-07-11 18:56:50 +02:00
|
|
|
ret_sig->set_line(*this);
|
|
|
|
|
ret_sig->port_type(NetNet::POUTPUT);
|
2004-06-01 01:34:36 +02:00
|
|
|
break;
|
|
|
|
|
|
2010-10-03 01:29:30 +02:00
|
|
|
case PTF_ATOM2:
|
|
|
|
|
case PTF_ATOM2_S:
|
|
|
|
|
long use_wid;
|
|
|
|
|
{
|
2012-03-03 03:34:43 +01:00
|
|
|
ivl_assert(*this, return_type_.range->size() == 1);
|
2012-04-10 23:29:28 +02:00
|
|
|
pform_range_t&return_range = return_type_.range->front();
|
|
|
|
|
NetExpr*me = elab_and_eval(des, scope,
|
|
|
|
|
return_range.first, -1,
|
|
|
|
|
true);
|
2012-03-03 03:34:43 +01:00
|
|
|
ivl_assert(*this, me);
|
2012-04-10 23:29:28 +02:00
|
|
|
NetExpr*le = elab_and_eval(des, scope,
|
|
|
|
|
return_range.second, -1,
|
|
|
|
|
true);
|
2012-03-03 03:34:43 +01:00
|
|
|
ivl_assert(*this, le);
|
2010-10-03 01:29:30 +02:00
|
|
|
|
|
|
|
|
long mnum = 0, lnum = 0;
|
|
|
|
|
if ( ! get_const_argument(me, mnum) ) {
|
|
|
|
|
cerr << me->get_fileline() << ": error: "
|
|
|
|
|
"Unable to evaluate constant expression "
|
|
|
|
|
<< *me << "." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ( ! get_const_argument(le, lnum) ) {
|
|
|
|
|
cerr << le->get_fileline() << ": error: "
|
|
|
|
|
"Unable to evaluate constant expression "
|
|
|
|
|
<< *le << "." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
use_wid = mnum - lnum + 1;
|
|
|
|
|
}
|
2012-09-15 19:27:43 +02:00
|
|
|
ret_vec = new netvector_t(IVL_VT_BOOL, use_wid-1, 0);
|
2012-09-16 02:16:05 +02:00
|
|
|
ret_vec->set_isint(true);
|
|
|
|
|
ret_vec->set_scalar(false);
|
|
|
|
|
ret_vec->set_signed(return_type_.type == PTF_ATOM2_S? true : false);
|
2012-09-15 19:27:43 +02:00
|
|
|
ret_sig = new NetNet(scope, fname, NetNet::REG, ret_vec);
|
2010-10-03 01:29:30 +02:00
|
|
|
ret_sig->set_line(*this);
|
|
|
|
|
ret_sig->port_type(NetNet::POUTPUT);
|
|
|
|
|
break;
|
|
|
|
|
|
2012-03-05 04:33:16 +01:00
|
|
|
case PTF_STRING:
|
|
|
|
|
cerr << get_fileline() << ": sorry: String functions are not supported yet" << endl;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case PTF_VOID:
|
|
|
|
|
// Void functions have no return value, so there is no
|
|
|
|
|
// signal to create here.
|
|
|
|
|
break;
|
|
|
|
|
|
2004-06-01 01:34:36 +02:00
|
|
|
default:
|
2008-08-09 01:34:24 +02:00
|
|
|
if (ports_) {
|
|
|
|
|
cerr << get_fileline() << ": internal error: I don't know "
|
|
|
|
|
<< "how to deal with return type of function "
|
|
|
|
|
<< scope->basename() << "." << endl;
|
|
|
|
|
} else {
|
|
|
|
|
/* If we do not have any ports or a return type this
|
|
|
|
|
* is probably a bad function definition. */
|
|
|
|
|
cerr << get_fileline() << ": error: Bad definition for "
|
|
|
|
|
<< "function " << scope->basename() << "?" << endl;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2000-07-30 20:25:43 +02:00
|
|
|
}
|
|
|
|
|
|
2012-05-29 01:49:41 +02:00
|
|
|
vector<NetNet*>ports (ports_? ports_->count() : 0);
|
2004-06-01 01:34:36 +02:00
|
|
|
|
2001-01-13 23:20:08 +01:00
|
|
|
if (ports_)
|
|
|
|
|
for (unsigned idx = 0 ; idx < ports_->count() ; idx += 1) {
|
2000-07-30 20:25:43 +02:00
|
|
|
|
2001-01-13 23:20:08 +01:00
|
|
|
/* Parse the port name into the task name and the reg
|
|
|
|
|
name. We know by design that the port name is given
|
|
|
|
|
as two components: <func>.<port>. */
|
2000-07-30 20:25:43 +02:00
|
|
|
|
2008-02-25 04:40:54 +01:00
|
|
|
perm_string pname = (*ports_)[idx]->basename();
|
2000-07-30 20:25:43 +02:00
|
|
|
|
2001-01-13 23:20:08 +01:00
|
|
|
NetNet*tmp = scope->find_signal(pname);
|
2008-04-19 06:33:03 +02:00
|
|
|
ports[idx] = 0;
|
|
|
|
|
|
2001-01-13 23:20:08 +01:00
|
|
|
if (tmp == 0) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": internal error: function "
|
2007-06-02 05:42:12 +02:00
|
|
|
<< scope_path(scope) << " is missing port "
|
2001-01-13 23:20:08 +01:00
|
|
|
<< pname << "." << endl;
|
|
|
|
|
scope->dump(cerr);
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": Continuing..." << endl;
|
2001-01-13 23:20:08 +01:00
|
|
|
des->errors += 1;
|
2008-04-19 06:33:03 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tmp->port_type() == NetNet::NOT_A_PORT) {
|
|
|
|
|
cerr << get_fileline() << ": internal error: function "
|
|
|
|
|
<< scope_path(scope) << " port " << pname
|
|
|
|
|
<< " is a port but is not a port?" << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
scope->dump(cerr);
|
|
|
|
|
continue;
|
2001-01-13 23:20:08 +01:00
|
|
|
}
|
|
|
|
|
|
2004-06-01 01:34:36 +02:00
|
|
|
ports[idx] = tmp;
|
2008-04-19 06:33:03 +02:00
|
|
|
if (tmp->port_type() != NetNet::PINPUT) {
|
|
|
|
|
cerr << tmp->get_fileline() << ": error: function "
|
|
|
|
|
<< scope_path(scope) << " port " << pname
|
|
|
|
|
<< " is not an input port." << endl;
|
|
|
|
|
cerr << tmp->get_fileline() << ": : Function arguments "
|
|
|
|
|
<< "must be input ports." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
2000-07-30 20:25:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2004-06-01 01:34:36 +02:00
|
|
|
NetFuncDef*def = 0;
|
|
|
|
|
if (ret_sig) def = new NetFuncDef(scope, ret_sig, ports);
|
|
|
|
|
|
|
|
|
|
assert(def);
|
2008-02-28 05:54:47 +01:00
|
|
|
if (debug_elaborate)
|
|
|
|
|
cerr << get_fileline() << ": debug: "
|
|
|
|
|
<< "Attach function definition to scope "
|
|
|
|
|
<< scope_path(scope) << "." << endl;
|
|
|
|
|
|
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
|
|
|
|
|
{
|
|
|
|
|
assert(scope->type() == NetScope::TASK);
|
|
|
|
|
|
2008-02-25 04:40:54 +01:00
|
|
|
elaborate_sig_wires_(des, scope);
|
|
|
|
|
|
2000-07-30 20:25:43 +02:00
|
|
|
svector<NetNet*>ports (ports_? ports_->count() : 0);
|
|
|
|
|
for (unsigned idx = 0 ; idx < ports.count() ; idx += 1) {
|
|
|
|
|
|
2008-02-25 04:40:54 +01:00
|
|
|
perm_string port_name = (*ports_)[idx]->basename();
|
2000-07-30 20:25:43 +02:00
|
|
|
|
|
|
|
|
/* Find the signal for the port. We know by definition
|
|
|
|
|
that it is in the scope of the task, so look only in
|
|
|
|
|
the scope. */
|
2007-05-24 06:07:11 +02:00
|
|
|
NetNet*tmp = scope->find_signal(port_name);
|
2000-07-30 20:25:43 +02:00
|
|
|
|
|
|
|
|
if (tmp == 0) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": internal error: "
|
2007-05-24 06:07:11 +02:00
|
|
|
<< "Could not find port " << port_name
|
2007-06-02 05:42:12 +02:00
|
|
|
<< " in scope " << scope_path(scope) << endl;
|
2000-07-30 20:25:43 +02:00
|
|
|
scope->dump(cerr);
|
2008-02-25 04:40:54 +01:00
|
|
|
des->errors += 1;
|
2000-07-30 20:25:43 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ports[idx] = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
2007-06-02 05:42:12 +02:00
|
|
|
NetTaskDef*def = new NetTaskDef(scope, ports);
|
2000-07-30 20:25:43 +02:00
|
|
|
scope->set_task_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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
|
|
for (unsigned idx = 0 ; idx < items_->count() ; idx += 1) {
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PEventStatement::elaborate_sig(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2012-02-06 02:41:11 +01:00
|
|
|
static bool evaluate_ranges(Design*des, NetScope*scope,
|
2012-03-26 02:59:05 +02:00
|
|
|
list<netrange_t>&llist,
|
2012-04-10 23:29:28 +02:00
|
|
|
const list<pform_range_t>&rlist)
|
2012-02-06 02:41:11 +01:00
|
|
|
{
|
|
|
|
|
bool bad_msb = false, bad_lsb = false;
|
|
|
|
|
|
2012-04-10 23:29:28 +02:00
|
|
|
for (list<pform_range_t>::const_iterator cur = rlist.begin()
|
2012-02-06 02:41:11 +01:00
|
|
|
; cur != rlist.end() ; ++cur) {
|
2012-07-14 03:41:41 +02:00
|
|
|
long use_msb, use_lsb;
|
2012-02-06 02:41:11 +01:00
|
|
|
|
2012-04-10 23:29:28 +02:00
|
|
|
NetExpr*texpr = elab_and_eval(des, scope, cur->first, -1, true);
|
2012-07-14 03:41:41 +02:00
|
|
|
if (! eval_as_long(use_msb, texpr)) {
|
2012-04-10 23:29:28 +02:00
|
|
|
cerr << cur->first->get_fileline() << ": error: "
|
2012-02-06 02:41:11 +01:00
|
|
|
"Range expressions must be constant." << endl;
|
2012-04-10 23:29:28 +02:00
|
|
|
cerr << cur->first->get_fileline() << " : "
|
2012-02-06 02:41:11 +01:00
|
|
|
"This MSB expression violates the rule: "
|
2012-04-10 23:29:28 +02:00
|
|
|
<< *cur->first << endl;
|
2012-02-06 02:41:11 +01:00
|
|
|
des->errors += 1;
|
|
|
|
|
bad_msb = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete texpr;
|
|
|
|
|
|
2012-04-10 23:29:28 +02:00
|
|
|
texpr = elab_and_eval(des, scope, cur->second, -1, true);
|
2012-07-14 03:41:41 +02:00
|
|
|
if (! eval_as_long(use_lsb, texpr)) {
|
2012-04-10 23:29:28 +02:00
|
|
|
cerr << cur->second->get_fileline() << ": error: "
|
2012-02-06 02:41:11 +01:00
|
|
|
"Range expressions must be constant." << endl;
|
2012-04-10 23:29:28 +02:00
|
|
|
cerr << cur->second->get_fileline() << " : "
|
2012-02-06 02:41:11 +01:00
|
|
|
"This LSB expression violates the rule: "
|
2012-04-10 23:29:28 +02:00
|
|
|
<< *cur->second << endl;
|
2012-02-06 02:41:11 +01:00
|
|
|
des->errors += 1;
|
|
|
|
|
bad_lsb = true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete texpr;
|
|
|
|
|
|
2012-07-14 03:41:41 +02:00
|
|
|
llist.push_back(netrange_t(use_msb, use_lsb));
|
2012-02-06 02:41:11 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return bad_msb | bad_lsb;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-26 02:59:05 +02:00
|
|
|
static netstruct_t* elaborate_struct_type(Design*des, NetScope*scope,
|
|
|
|
|
struct_type_t*struct_type)
|
|
|
|
|
{
|
|
|
|
|
netstruct_t*res = new netstruct_t;
|
|
|
|
|
|
|
|
|
|
res->packed(struct_type->packed_flag);
|
|
|
|
|
|
|
|
|
|
for (list<struct_member_t*>::iterator cur = struct_type->members->begin()
|
|
|
|
|
; cur != struct_type->members->end() ; ++ cur) {
|
|
|
|
|
|
|
|
|
|
list<netrange_t>packed_dimensions;
|
|
|
|
|
|
|
|
|
|
struct_member_t*curp = *cur;
|
|
|
|
|
if (curp->range.get() && ! curp->range->empty()) {
|
|
|
|
|
bool bad_range;
|
|
|
|
|
bad_range = evaluate_ranges(des, scope, packed_dimensions, *curp->range);
|
|
|
|
|
ivl_assert(*curp, !bad_range);
|
|
|
|
|
} else {
|
|
|
|
|
packed_dimensions.push_back(netrange_t(0,0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (list<decl_assignment_t*>::iterator name = curp->names->begin()
|
|
|
|
|
; name != curp->names->end() ; ++ name) {
|
|
|
|
|
decl_assignment_t*namep = *name;
|
|
|
|
|
|
|
|
|
|
netstruct_t::member_t memb;
|
|
|
|
|
memb.name = namep->name;
|
|
|
|
|
memb.type = curp->type;
|
|
|
|
|
memb.packed_dims = packed_dimensions;
|
|
|
|
|
res->append_member(memb);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2012-08-06 01:28:40 +02:00
|
|
|
static netparray_t* elaborate_parray_type(Design*des, NetScope*scope,
|
|
|
|
|
parray_type_t*data_type)
|
2012-08-03 05:14:55 +02:00
|
|
|
{
|
|
|
|
|
|
|
|
|
|
list<netrange_t>packed_dimensions;
|
|
|
|
|
bool bad_range = evaluate_ranges(des, scope, packed_dimensions, * data_type->packed_dims);
|
2012-08-06 01:28:40 +02:00
|
|
|
ivl_assert(*data_type, !bad_range);
|
2012-08-03 05:14:55 +02:00
|
|
|
|
2012-08-06 01:28:40 +02:00
|
|
|
netparray_t*res = new netparray_t(packed_dimensions);
|
2012-08-03 05:14:55 +02:00
|
|
|
//res->set_line(*data_type);
|
|
|
|
|
|
|
|
|
|
return res;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-23 18:28:49 +02:00
|
|
|
static ivl_type_s*elaborate_type(Design*des, NetScope*scope,
|
|
|
|
|
data_type_t*pform_type)
|
2012-08-06 01:28:40 +02:00
|
|
|
{
|
|
|
|
|
if (struct_type_t*struct_type = dynamic_cast<struct_type_t*>(pform_type)) {
|
|
|
|
|
netstruct_t*use_type = elaborate_struct_type(des, scope, struct_type);
|
|
|
|
|
return use_type;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cerr << pform_type->get_fileline() << ": sorry: I don't know how to elaborate "
|
|
|
|
|
<< typeid(*pform_type).name() << " here." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2012-03-26 02:59:05 +02:00
|
|
|
bool test_ranges_eeq(const list<netrange_t>&lef, const list<netrange_t>&rig)
|
2012-02-06 02:41:11 +01:00
|
|
|
{
|
|
|
|
|
if (lef.size() != rig.size())
|
|
|
|
|
return false;
|
|
|
|
|
|
2012-03-26 02:59:05 +02:00
|
|
|
list<netrange_t>::const_iterator lcur = lef.begin();
|
|
|
|
|
list<netrange_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;
|
|
|
|
|
}
|
|
|
|
|
|
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.
|
|
|
|
|
*/
|
2007-05-24 06:07:11 +02:00
|
|
|
NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const
|
2000-05-02 18:27:38 +02:00
|
|
|
{
|
|
|
|
|
NetNet::Type wtype = type_;
|
2009-04-15 01:08:27 +02:00
|
|
|
bool is_implicit_scalar = false;
|
|
|
|
|
if (wtype == NetNet::IMPLICIT) {
|
2000-05-02 18:27:38 +02:00
|
|
|
wtype = NetNet::WIRE;
|
2009-04-15 01:08:27 +02:00
|
|
|
is_implicit_scalar = true;
|
|
|
|
|
}
|
|
|
|
|
if (wtype == NetNet::IMPLICIT_REG) {
|
2000-05-02 18:27:38 +02:00
|
|
|
wtype = NetNet::REG;
|
2009-04-15 01:08:27 +02:00
|
|
|
is_implicit_scalar = true;
|
|
|
|
|
}
|
2000-05-02 18:27:38 +02:00
|
|
|
|
|
|
|
|
unsigned wid = 1;
|
2012-03-26 02:59:05 +02:00
|
|
|
list<netrange_t>packed_dimensions;
|
2000-05-02 18:27:38 +02:00
|
|
|
|
2007-08-22 04:52:42 +02:00
|
|
|
des->errors += error_cnt_;
|
|
|
|
|
|
2009-04-25 04:07:48 +02:00
|
|
|
// A signal can not have the same name as a scope object.
|
|
|
|
|
const NetScope *child = scope->child(hname_t(name_));
|
|
|
|
|
if (child) {
|
|
|
|
|
cerr << get_fileline() << ": error: signal and ";
|
|
|
|
|
child->print_type(cerr);
|
|
|
|
|
cerr << " in '" << scope->fullname()
|
|
|
|
|
<< "' have the same name '" << name_ << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
2009-07-28 20:42:07 +02:00
|
|
|
}
|
|
|
|
|
// A signal can not have the same name as a genvar.
|
|
|
|
|
const LineInfo *genvar = scope->find_genvar(name_);
|
|
|
|
|
if (genvar) {
|
|
|
|
|
cerr << get_fileline() << ": error: signal and genvar in '"
|
|
|
|
|
<< scope->fullname() << "' have the same name '" << name_
|
|
|
|
|
<< "'." << endl;
|
|
|
|
|
des->errors += 1;
|
2009-04-25 04:07:48 +02:00
|
|
|
}
|
|
|
|
|
// A signal can not have the same name as a parameter.
|
|
|
|
|
const NetExpr *ex_msb, *ex_lsb;
|
2010-12-05 22:28:17 +01:00
|
|
|
const NetExpr *parm = scope->get_parameter(des, name_, ex_msb, ex_lsb);
|
2009-04-25 04:07:48 +02:00
|
|
|
if (parm) {
|
|
|
|
|
cerr << get_fileline() << ": error: signal and parameter in '"
|
|
|
|
|
<< scope->fullname() << "' have the same name '" << name_
|
|
|
|
|
<< "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
// A signal can not have the same name as a named event.
|
|
|
|
|
const NetEvent *event = scope->find_event(name_);
|
|
|
|
|
if (event) {
|
|
|
|
|
cerr << get_fileline() << ": error: signal and named event in '"
|
|
|
|
|
<< scope->fullname() << "' have the same name '" << name_
|
|
|
|
|
<< "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2007-08-22 04:52:42 +02:00
|
|
|
if (port_set_ || net_set_) {
|
2012-02-06 02:41:11 +01:00
|
|
|
bool bad_range = false;
|
2012-03-26 02:59:05 +02:00
|
|
|
list<netrange_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()) {
|
2012-02-06 02:41:11 +01:00
|
|
|
bad_range |= evaluate_ranges(des, scope, plist, port_);
|
|
|
|
|
nlist = plist;
|
2009-04-15 01:08:27 +02:00
|
|
|
/* An implicit port can have a range so note that here. */
|
|
|
|
|
is_implicit_scalar = false;
|
2007-08-22 04:52:42 +02:00
|
|
|
}
|
2012-02-06 02:41:11 +01:00
|
|
|
assert(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 */
|
2012-02-06 02:41:11 +01:00
|
|
|
if (net_set_ && !net_.empty() && !bad_range) {
|
|
|
|
|
nlist.clear();
|
|
|
|
|
bad_range |= evaluate_ranges(des, scope, nlist, net_);
|
2002-01-26 06:28:28 +01:00
|
|
|
}
|
2012-02-06 02:41:11 +01:00
|
|
|
assert(net_set_ || net_.empty());
|
|
|
|
|
|
|
|
|
|
/* If we find errors here, then give up on this signal. */
|
|
|
|
|
if (bad_range)
|
|
|
|
|
return 0;
|
2007-08-22 04:52:42 +02:00
|
|
|
|
|
|
|
|
/* We have a port size error */
|
2012-02-06 02:41:11 +01:00
|
|
|
if (port_set_ && net_set_ && !test_ranges_eeq(plist, nlist)) {
|
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()) {
|
2007-08-22 04:52:42 +02:00
|
|
|
if (!gn_io_range_error_flag) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline()
|
2008-02-25 04:40:54 +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
|
|
|
} else {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline()
|
2008-02-25 04:40:54 +01:00
|
|
|
<< ": error: 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
|
|
|
des->errors += 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
}
|
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;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
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-05-24 06:07:11 +02:00
|
|
|
return 0;
|
2000-05-02 18:27:38 +02:00
|
|
|
}
|
2007-08-22 04:52:42 +02:00
|
|
|
}
|
2000-05-02 18:27:38 +02:00
|
|
|
|
2012-02-06 02:41:11 +01:00
|
|
|
packed_dimensions = nlist;
|
2012-03-26 02:59:05 +02:00
|
|
|
wid = netrange_width(packed_dimensions);
|
2000-05-02 18:27:38 +02:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2002-05-23 05:08:50 +02:00
|
|
|
unsigned nattrib = 0;
|
|
|
|
|
attrib_list_t*attrib_list = evaluate_attributes(attributes, nattrib,
|
|
|
|
|
des, scope);
|
|
|
|
|
|
2007-01-16 06:44:14 +01:00
|
|
|
|
2012-05-26 01:32:12 +02:00
|
|
|
list<netrange_t>unpacked_dimensions;
|
2012-07-14 03:41:41 +02:00
|
|
|
netdarray_t*netarray = 0;
|
2000-05-02 18:27:38 +02:00
|
|
|
|
2012-05-26 00:58:29 +02:00
|
|
|
for (list<pform_range_t>::const_iterator cur = unpacked_.begin()
|
|
|
|
|
; cur != unpacked_.end() ; ++cur) {
|
|
|
|
|
PExpr*use_lidx = cur->first;
|
|
|
|
|
PExpr*use_ridx = cur->second;
|
2012-07-14 03:41:41 +02:00
|
|
|
|
|
|
|
|
// Special case: If we encounter an undefined
|
|
|
|
|
// dimensions, then turn this into a dynamic array and
|
|
|
|
|
// put all the packed dimensions there.
|
|
|
|
|
if (use_lidx==0 && use_ridx==0) {
|
2012-09-15 20:27:03 +02:00
|
|
|
netvector_t*vec = new netvector_t(packed_dimensions, data_type_);
|
2012-07-14 03:41:41 +02:00
|
|
|
packed_dimensions.clear();
|
2012-09-15 20:27:03 +02:00
|
|
|
ivl_assert(*this, netarray==0);
|
|
|
|
|
netarray = new netdarray_t(vec);
|
2012-07-14 03:41:41 +02:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Cannot handle dynamic arrays of arrays yet.
|
|
|
|
|
ivl_assert(*this, netarray==0);
|
|
|
|
|
ivl_assert(*this, use_lidx && use_ridx);
|
2012-05-26 00:58:29 +02:00
|
|
|
|
|
|
|
|
NetExpr*lexp = elab_and_eval(des, scope, use_lidx, -1, true);
|
|
|
|
|
NetExpr*rexp = elab_and_eval(des, scope, use_ridx, -1, true);
|
2001-01-04 05:47:51 +01:00
|
|
|
|
2003-09-20 07:24:00 +02:00
|
|
|
if ((lexp == 0) || (rexp == 0)) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": internal error: There is "
|
2001-01-04 05:47:51 +01:00
|
|
|
<< "a problem evaluating indices for ``"
|
2008-02-25 04:40:54 +01:00
|
|
|
<< name_ << "''." << endl;
|
2001-01-04 05:47:51 +01:00
|
|
|
des->errors += 1;
|
2007-05-24 06:07:11 +02:00
|
|
|
return 0;
|
2001-01-04 05:47:51 +01:00
|
|
|
}
|
|
|
|
|
|
2008-02-28 00:01:09 +01:00
|
|
|
bool const_flag = true;
|
|
|
|
|
verinum lval, rval;
|
|
|
|
|
const_flag &= get_const_argument(lexp, lval);
|
|
|
|
|
const_flag &= get_const_argument(rexp, rval);
|
|
|
|
|
delete rexp;
|
|
|
|
|
delete lexp;
|
2003-09-20 07:24:00 +02:00
|
|
|
|
2012-05-26 00:58:29 +02:00
|
|
|
long index_l, index_r;
|
|
|
|
|
if (! const_flag) {
|
2008-10-04 16:30:34 +02:00
|
|
|
cerr << get_fileline() << ": error: The indices "
|
2007-01-16 06:44:14 +01:00
|
|
|
<< "are not constant for array ``"
|
2008-02-25 04:40:54 +01:00
|
|
|
<< name_ << "''." << endl;
|
2003-09-20 07:24:00 +02:00
|
|
|
des->errors += 1;
|
2008-10-04 16:30:34 +02:00
|
|
|
/* Attempt to recover from error, */
|
2012-05-26 00:58:29 +02:00
|
|
|
index_l = 0;
|
|
|
|
|
index_r = 0;
|
2008-10-04 16:30:34 +02:00
|
|
|
} else {
|
2012-05-26 00:58:29 +02:00
|
|
|
index_l = lval.as_long();
|
|
|
|
|
index_r = rval.as_long();
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-26 01:32:12 +02:00
|
|
|
unpacked_dimensions.push_back(netrange_t(index_l, index_r));
|
2007-01-16 06:44:14 +01:00
|
|
|
}
|
2005-02-13 02:15:07 +01:00
|
|
|
|
2012-02-06 02:41:11 +01:00
|
|
|
if (data_type_ == IVL_VT_REAL && !packed_dimensions.empty()) {
|
2010-11-19 05:58:01 +01:00
|
|
|
cerr << get_fileline() << ": error: real ";
|
|
|
|
|
if (wtype == NetNet::REG) cerr << "variable";
|
|
|
|
|
else cerr << "net";
|
2011-03-03 05:23:02 +01:00
|
|
|
cerr << " '" << name_
|
2012-02-06 02:41:11 +01:00
|
|
|
<< "' cannot be declared as a vector, found a range "
|
|
|
|
|
<< packed_dimensions << "." << endl;
|
2010-11-19 05:58:01 +01:00
|
|
|
des->errors += 1;
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
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) {
|
|
|
|
|
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;
|
2005-02-13 02:15:07 +01:00
|
|
|
|
2004-12-11 03:31:25 +01:00
|
|
|
if (debug_elaborate) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": debug: "
|
2010-11-19 05:58:01 +01:00
|
|
|
<< "Generate a SUPPLY pull for the ";
|
|
|
|
|
if (wtype == NetNet::SUPPLY0) cerr << "supply0";
|
|
|
|
|
else cerr << "supply1";
|
|
|
|
|
cerr << " net." << endl;
|
2004-12-11 03:31:25 +01:00
|
|
|
}
|
2007-01-16 06:44:14 +01:00
|
|
|
}
|
2004-12-11 03:31:25 +01:00
|
|
|
|
2011-12-11 19:28:04 +01:00
|
|
|
|
|
|
|
|
NetNet*sig = 0;
|
|
|
|
|
|
|
|
|
|
// If this is a struct type, then build the net with the
|
|
|
|
|
// struct type.
|
2012-08-03 05:14:55 +02:00
|
|
|
if (struct_type_t*struct_type = dynamic_cast<struct_type_t*>(set_data_type_)) {
|
|
|
|
|
netstruct_t*use_type = elaborate_struct_type(des, scope, struct_type);
|
2011-12-11 19:28:04 +01:00
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << get_fileline() << ": debug: Create signal " << wtype;
|
|
|
|
|
if (use_type->packed())
|
|
|
|
|
cerr << " " << use_type->packed_width() << " bit packed struct ";
|
|
|
|
|
else
|
|
|
|
|
cerr << " struct <> ";
|
|
|
|
|
cerr << name_;
|
|
|
|
|
cerr << " in scope " << scope_path(scope) << endl;
|
2008-08-08 22:57:26 +02:00
|
|
|
}
|
2002-05-23 05:08:50 +02:00
|
|
|
|
2011-12-11 19:28:04 +01:00
|
|
|
sig = new NetNet(scope, name_, wtype, use_type);
|
|
|
|
|
|
2012-08-03 05:14:55 +02:00
|
|
|
} else if (enum_type_t*enum_type = dynamic_cast<enum_type_t*>(set_data_type_)) {
|
|
|
|
|
list<named_pexpr_t>::const_iterator sample_name = enum_type->names->begin();
|
2012-07-14 03:41:41 +02:00
|
|
|
netenum_t*use_enum = scope->enumeration_for_name(sample_name->name);
|
|
|
|
|
|
|
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << get_fileline() << ": debug: Create signal " << wtype
|
|
|
|
|
<< " enumeration "
|
2012-08-20 02:27:48 +02:00
|
|
|
<< name_ << " in scope " << scope_path(scope)
|
|
|
|
|
<< " with packed_dimensions=" << packed_dimensions
|
|
|
|
|
<< " and packed_width=" << use_enum->packed_width() << endl;
|
2012-07-14 03:41:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sig = new NetNet(scope, name_, wtype, packed_dimensions, unpacked_dimensions, use_enum);
|
|
|
|
|
|
2012-08-03 05:14:55 +02:00
|
|
|
|
2012-07-14 03:41:41 +02:00
|
|
|
} else if (netarray) {
|
|
|
|
|
|
|
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << get_fileline() << ": debug: Create signal " << wtype
|
|
|
|
|
<< " dynamic array "
|
|
|
|
|
<< name_ << " in scope " << scope_path(scope) << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ivl_assert(*this, packed_dimensions.empty());
|
|
|
|
|
ivl_assert(*this, unpacked_dimensions.empty());
|
|
|
|
|
sig = new NetNet(scope, name_, wtype, netarray);
|
|
|
|
|
|
2012-08-03 05:14:55 +02:00
|
|
|
} else if (parray_type_t*parray_type = dynamic_cast<parray_type_t*>(set_data_type_)) {
|
2012-08-06 01:28:40 +02:00
|
|
|
// The pform gives us a parray_type_t for packed arrays
|
|
|
|
|
// that show up in type definitions. This can be handled
|
|
|
|
|
// a lot like packed dimensions from other means.
|
|
|
|
|
|
|
|
|
|
// The trick here is that the parray type has an
|
|
|
|
|
// arbitrary sub-type, and not just a scalar bit...
|
|
|
|
|
netparray_t*use_type = elaborate_parray_type(des, scope, parray_type);
|
|
|
|
|
// Should not be getting packed dimensions other then
|
|
|
|
|
// through the parray type declaration.
|
|
|
|
|
ivl_assert(*this, packed_dimensions.empty());
|
2012-08-03 05:14:55 +02:00
|
|
|
|
2012-08-06 01:28:40 +02:00
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << get_fileline() << ": debug: Create signal " << wtype
|
|
|
|
|
<< " parray=" << use_type->packed_dimensions()
|
|
|
|
|
<< " " << name_ << unpacked_dimensions
|
|
|
|
|
<< " in scope " << scope_path(scope) << endl;
|
|
|
|
|
}
|
|
|
|
|
|
2012-09-23 18:28:49 +02:00
|
|
|
ivl_type_s*base_type = elaborate_type(des, scope, parray_type->base_type);
|
2012-08-03 05:14:55 +02:00
|
|
|
#if 0
|
2012-08-06 01:28:40 +02:00
|
|
|
cerr << get_fileline() << ": sorry: Packed array of "
|
|
|
|
|
<< typeid(*parray_type->base_type).name()
|
|
|
|
|
<< " not supported." << endl;
|
2012-08-03 05:14:55 +02:00
|
|
|
des->errors += 1;
|
|
|
|
|
#endif
|
2012-08-06 01:28:40 +02:00
|
|
|
sig = new NetNet(scope, name_, wtype, use_type->packed_dimensions(), unpacked_dimensions, base_type);
|
|
|
|
|
|
2012-08-03 05:14:55 +02:00
|
|
|
|
2011-12-11 19:28:04 +01:00
|
|
|
} else {
|
|
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << get_fileline() << ": debug: Create signal " << wtype;
|
|
|
|
|
if (!get_scalar()) {
|
2012-02-06 02:41:11 +01:00
|
|
|
cerr << " " << packed_dimensions;
|
2011-12-11 19:28:04 +01:00
|
|
|
}
|
2012-05-26 00:58:29 +02:00
|
|
|
cerr << " " << name_ << unpacked_dimensions;
|
2011-12-11 19:28:04 +01:00
|
|
|
cerr << " in scope " << scope_path(scope) << endl;
|
|
|
|
|
}
|
2007-04-02 03:12:34 +02:00
|
|
|
|
2012-09-15 19:27:43 +02:00
|
|
|
ivl_variable_type_t use_data_type = data_type_;
|
|
|
|
|
if (use_data_type == IVL_VT_NO_TYPE) {
|
|
|
|
|
use_data_type = IVL_VT_LOGIC;
|
|
|
|
|
if (debug_elaborate) {
|
|
|
|
|
cerr << get_fileline() << ": debug: "
|
|
|
|
|
<< "Signal " << name_
|
|
|
|
|
<< " in scope " << scope_path(scope)
|
|
|
|
|
<< " defaults to data type " << use_data_type << endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
2007-01-29 03:07:34 +01:00
|
|
|
|
2012-09-15 19:27:43 +02:00
|
|
|
netvector_t*vec = new netvector_t(packed_dimensions, use_data_type);
|
2012-09-16 02:16:05 +02:00
|
|
|
vec->set_signed(get_signed());
|
|
|
|
|
vec->set_isint(get_isint());
|
|
|
|
|
if (is_implicit_scalar) vec->set_scalar(true);
|
|
|
|
|
else vec->set_scalar(get_scalar());
|
2012-09-15 19:27:43 +02:00
|
|
|
packed_dimensions.clear();
|
|
|
|
|
sig = new NetNet(scope, name_, wtype, packed_dimensions, unpacked_dimensions, vec);
|
2009-03-11 17:18:30 +01:00
|
|
|
|
2007-01-29 03:07:34 +01:00
|
|
|
}
|
|
|
|
|
|
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_);
|
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
|
|
|
|
|
|
|
|
return sig;
|
2000-05-02 18:27:38 +02:00
|
|
|
}
|