2000-03-08 05:36:53 +01:00
|
|
|
/*
|
2025-06-22 01:57:04 +02:00
|
|
|
* Copyright (c) 2000-2025 Stephen Williams (steve@icarus.com)
|
2013-04-09 03:35:37 +02:00
|
|
|
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
|
2000-03-08 05:36:53 +01: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-03-08 05:36:53 +01:00
|
|
|
*/
|
|
|
|
|
|
2003-03-06 01:28:41 +01:00
|
|
|
# include "config.h"
|
|
|
|
|
# include "compiler.h"
|
2006-03-30 03:49:07 +02:00
|
|
|
# include "netmisc.h"
|
2022-03-15 08:24:33 +01:00
|
|
|
# include "netvector.h"
|
|
|
|
|
# include "netparray.h"
|
2008-01-05 00:23:47 +01:00
|
|
|
# include <cstring>
|
2001-07-25 05:10:48 +02:00
|
|
|
# include <iostream>
|
2008-05-19 17:26:56 +02:00
|
|
|
# include <cstdlib>
|
2010-05-31 22:12:06 +02:00
|
|
|
# include <cstdio>
|
2001-07-25 05:10:48 +02:00
|
|
|
|
2000-03-08 05:36:53 +01:00
|
|
|
/*
|
|
|
|
|
* Elaboration happens in two passes, generally. The first scans the
|
|
|
|
|
* pform to generate the NetScope tree and attach it to the Design
|
|
|
|
|
* object. The methods in this source file implement the elaboration
|
|
|
|
|
* of the scopes.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
# include "Module.h"
|
2012-11-12 02:42:31 +01:00
|
|
|
# include "PClass.h"
|
2000-03-08 05:36:53 +01:00
|
|
|
# include "PExpr.h"
|
2012-11-12 02:42:31 +01:00
|
|
|
# include "PEvent.h"
|
|
|
|
|
# include "PClass.h"
|
2000-03-08 05:36:53 +01:00
|
|
|
# include "PGate.h"
|
2006-04-10 02:37:42 +02:00
|
|
|
# include "PGenerate.h"
|
2013-02-17 23:42:07 +01:00
|
|
|
# include "PPackage.h"
|
2000-03-08 05:36:53 +01:00
|
|
|
# include "PTask.h"
|
2000-07-30 20:25:43 +02:00
|
|
|
# include "PWire.h"
|
2000-03-11 04:25:51 +01:00
|
|
|
# include "Statement.h"
|
2008-10-22 07:15:49 +02:00
|
|
|
# include "AStatement.h"
|
2000-03-08 05:36:53 +01:00
|
|
|
# include "netlist.h"
|
2012-11-12 02:42:31 +01:00
|
|
|
# include "netclass.h"
|
2010-11-03 04:16:42 +01:00
|
|
|
# include "netenum.h"
|
2022-01-18 23:43:59 +01:00
|
|
|
# include "netqueue.h"
|
2013-12-15 22:55:26 +01:00
|
|
|
# include "parse_api.h"
|
2003-06-20 02:53:19 +02:00
|
|
|
# include "util.h"
|
2000-03-11 04:25:51 +01:00
|
|
|
# include <typeinfo>
|
2008-05-14 06:22:52 +02:00
|
|
|
# include "ivl_assert.h"
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2021-11-04 17:12:04 +01:00
|
|
|
using namespace std;
|
2016-07-22 23:48:20 +02:00
|
|
|
|
2025-10-23 18:58:49 +02:00
|
|
|
void set_scope_timescale(Design*des, NetScope*scope, const PScope*pscope)
|
2016-07-22 23:48:20 +02:00
|
|
|
{
|
|
|
|
|
scope->time_unit(pscope->time_unit);
|
|
|
|
|
scope->time_precision(pscope->time_precision);
|
2017-11-05 18:50:05 +01:00
|
|
|
scope->time_from_timescale(pscope->has_explicit_timescale());
|
2016-07-22 23:48:20 +02:00
|
|
|
des->set_precision(pscope->time_precision);
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-27 01:29:46 +02:00
|
|
|
typedef map<perm_string,LexicalScope::param_expr_t*>::const_iterator mparm_it_t;
|
2008-09-17 22:25:59 +02:00
|
|
|
|
2020-12-25 03:12:06 +01:00
|
|
|
static void collect_parm_item(Design*des, NetScope*scope, perm_string name,
|
|
|
|
|
const LexicalScope::param_expr_t&cur,
|
2022-02-09 22:30:12 +01:00
|
|
|
bool is_annotatable)
|
2008-02-05 22:37:33 +01:00
|
|
|
{
|
2020-12-25 03:12:06 +01:00
|
|
|
if (debug_scopes) {
|
|
|
|
|
cerr << cur.get_fileline() << ": " << __func__ << ": "
|
|
|
|
|
<< "parameter " << name << " ";
|
|
|
|
|
if (cur.data_type)
|
|
|
|
|
cerr << *cur.data_type;
|
|
|
|
|
else
|
|
|
|
|
cerr << "(nil type)";
|
|
|
|
|
ivl_assert(cur, cur.expr);
|
|
|
|
|
cerr << " = " << *cur.expr << "; ";
|
|
|
|
|
if (cur.range)
|
|
|
|
|
cerr << "with ranges ";
|
|
|
|
|
else
|
|
|
|
|
cerr << "without ranges ";
|
|
|
|
|
cerr << "; in scope " << scope_path(scope) << endl;
|
|
|
|
|
}
|
|
|
|
|
|
2008-05-14 06:22:52 +02:00
|
|
|
NetScope::range_t*range_list = 0;
|
2008-09-17 22:25:59 +02:00
|
|
|
for (LexicalScope::range_t*range = cur.range ; range ; range = range->next) {
|
2008-05-14 06:22:52 +02:00
|
|
|
NetScope::range_t*tmp = new NetScope::range_t;
|
|
|
|
|
tmp->exclude_flag = range->exclude_flag;
|
|
|
|
|
tmp->low_open_flag = range->low_open_flag;
|
|
|
|
|
tmp->high_open_flag = range->high_open_flag;
|
|
|
|
|
|
|
|
|
|
if (range->low_expr) {
|
|
|
|
|
tmp->low_expr = elab_and_eval(des, scope, range->low_expr, -1);
|
|
|
|
|
ivl_assert(*range->low_expr, tmp->low_expr);
|
2008-05-20 06:55:53 +02:00
|
|
|
} else {
|
|
|
|
|
tmp->low_expr = 0;
|
2008-05-14 06:22:52 +02:00
|
|
|
}
|
|
|
|
|
|
2008-06-06 06:49:49 +02:00
|
|
|
if (range->high_expr && range->high_expr==range->low_expr) {
|
|
|
|
|
// Detect the special case of a "point"
|
|
|
|
|
// range. These are called out by setting the high
|
|
|
|
|
// and low expression ranges to the same
|
|
|
|
|
// expression. The exclude_flags should be false
|
|
|
|
|
// in this case
|
|
|
|
|
ivl_assert(*range->high_expr, tmp->low_open_flag==false && tmp->high_open_flag==false);
|
|
|
|
|
tmp->high_expr = tmp->low_expr;
|
|
|
|
|
|
|
|
|
|
} else if (range->high_expr) {
|
2008-05-14 06:22:52 +02:00
|
|
|
tmp->high_expr = elab_and_eval(des, scope, range->high_expr, -1);
|
|
|
|
|
ivl_assert(*range->high_expr, tmp->high_expr);
|
2008-05-20 06:55:53 +02:00
|
|
|
} else {
|
|
|
|
|
tmp->high_expr = 0;
|
2008-05-14 06:22:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
tmp->next = range_list;
|
|
|
|
|
range_list = tmp;
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-25 03:12:06 +01:00
|
|
|
// The type of the parameter, if unspecified in the source, will come
|
|
|
|
|
// from the type of the value assigned to it. Therefore, if the type is
|
|
|
|
|
// not yet known, don't try to guess here, put the type guess off. Also
|
|
|
|
|
// don't try to elaborate it here, because there may be references to
|
|
|
|
|
// other parameters still being located during scope elaboration.
|
2021-12-20 17:00:24 +01:00
|
|
|
scope->set_parameter(name, is_annotatable, cur, range_list);
|
2008-02-05 22:37:33 +01:00
|
|
|
}
|
|
|
|
|
|
2020-12-25 03:12:06 +01:00
|
|
|
static void collect_scope_parameters(Design*des, NetScope*scope,
|
2019-09-27 01:29:46 +02:00
|
|
|
const map<perm_string,LexicalScope::param_expr_t*>¶meters)
|
2008-09-17 22:25:59 +02:00
|
|
|
{
|
2020-12-25 03:12:06 +01:00
|
|
|
if (debug_scopes) {
|
|
|
|
|
cerr << scope->get_fileline() << ": " << __func__ << ": "
|
|
|
|
|
<< "collect parameters for " << scope_path(scope) << "." << endl;
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-17 22:25:59 +02:00
|
|
|
for (mparm_it_t cur = parameters.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; cur != parameters.end() ; ++ cur ) {
|
2008-09-17 22:25:59 +02:00
|
|
|
|
2022-02-09 22:30:12 +01:00
|
|
|
collect_parm_item(des, scope, cur->first, *(cur->second), false);
|
2012-05-07 00:11:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-25 03:12:06 +01:00
|
|
|
static void collect_scope_specparams(Design*des, NetScope*scope,
|
2019-09-27 01:29:46 +02:00
|
|
|
const map<perm_string,LexicalScope::param_expr_t*>&specparams)
|
2012-05-07 00:11:26 +02:00
|
|
|
{
|
2020-12-25 03:12:06 +01:00
|
|
|
if (debug_scopes) {
|
|
|
|
|
cerr << scope->get_fileline() << ": " << __func__ << ": "
|
|
|
|
|
<< "collect specparams for " << scope_path(scope) << "." << endl;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-07 00:11:26 +02:00
|
|
|
for (mparm_it_t cur = specparams.begin()
|
|
|
|
|
; cur != specparams.end() ; ++ cur ) {
|
|
|
|
|
|
2022-02-09 22:30:12 +01:00
|
|
|
collect_parm_item(des, scope, cur->first, *(cur->second), true);
|
2008-09-17 22:25:59 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-12 19:38:00 +01:00
|
|
|
static void collect_scope_signals(NetScope*scope,
|
|
|
|
|
const map<perm_string,PWire*>&wires)
|
|
|
|
|
{
|
|
|
|
|
for (map<perm_string,PWire*>::const_iterator cur = wires.begin()
|
|
|
|
|
; cur != wires.end() ; ++ cur ) {
|
|
|
|
|
|
|
|
|
|
PWire*wire = (*cur).second;
|
|
|
|
|
if (debug_scopes) {
|
|
|
|
|
cerr << wire->get_fileline() << ": " << __func__ << ": "
|
|
|
|
|
<< "adding placeholder for signal '" << wire->basename()
|
|
|
|
|
<< "' in scope '" << scope_path(scope) << "'." << endl;
|
|
|
|
|
}
|
|
|
|
|
scope->add_signal_placeholder(wire);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-12-15 22:55:26 +01:00
|
|
|
/*
|
2017-10-21 16:04:25 +02:00
|
|
|
* Elaborate the enumeration into the given scope.
|
2013-12-15 22:55:26 +01:00
|
|
|
*/
|
2010-10-31 19:26:09 +01:00
|
|
|
static void elaborate_scope_enumeration(Design*des, NetScope*scope,
|
2010-11-04 04:11:19 +01:00
|
|
|
enum_type_t*enum_type)
|
2010-10-31 19:26:09 +01:00
|
|
|
{
|
2010-11-04 04:11:19 +01:00
|
|
|
bool rc_flag;
|
2022-01-08 10:01:23 +01:00
|
|
|
|
2022-04-28 11:26:20 +02:00
|
|
|
enum_type->elaborate_type(des, scope);
|
2010-11-04 04:11:19 +01:00
|
|
|
|
2022-04-28 11:26:20 +02:00
|
|
|
netenum_t *use_enum = scope->enumeration_for_key(enum_type);
|
2013-12-05 00:25:14 +01:00
|
|
|
|
2010-11-21 00:09:32 +01:00
|
|
|
size_t name_idx = 0;
|
2014-10-31 03:53:39 +01:00
|
|
|
// Find the enumeration width.
|
|
|
|
|
long raw_width = use_enum->packed_width();
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*use_enum, raw_width > 0);
|
2014-10-31 03:53:39 +01:00
|
|
|
unsigned enum_width = (unsigned)raw_width;
|
2022-03-15 08:24:33 +01:00
|
|
|
bool is_signed = use_enum->get_signed();
|
2014-11-02 20:44:37 +01:00
|
|
|
// Define the default start value and the increment value to be the
|
|
|
|
|
// correct type for this enumeration.
|
|
|
|
|
verinum cur_value ((uint64_t)0, enum_width);
|
2022-03-15 08:24:33 +01:00
|
|
|
cur_value.has_sign(is_signed);
|
2014-11-02 20:44:37 +01:00
|
|
|
verinum one_value ((uint64_t)1, enum_width);
|
2022-03-15 08:24:33 +01:00
|
|
|
one_value.has_sign(is_signed);
|
2014-11-02 20:44:37 +01:00
|
|
|
// Find the maximum allowed enumeration value.
|
2011-07-19 04:33:03 +02:00
|
|
|
verinum max_value (0);
|
2022-03-15 08:24:33 +01:00
|
|
|
if (is_signed) {
|
2014-10-31 03:53:39 +01:00
|
|
|
max_value = pow(verinum(2), verinum(enum_width-1)) - one_value;
|
2011-07-19 04:33:03 +02:00
|
|
|
} else {
|
2014-10-31 03:53:39 +01:00
|
|
|
max_value = pow(verinum(2), verinum(enum_width)) - one_value;
|
2011-07-19 04:33:03 +02:00
|
|
|
}
|
2022-03-15 08:24:33 +01:00
|
|
|
max_value.has_sign(is_signed);
|
2014-12-07 13:10:15 +01:00
|
|
|
// Variable to indicate when a defined value wraps.
|
|
|
|
|
bool implicit_wrapped = false;
|
2014-11-02 20:44:37 +01:00
|
|
|
// Process the enumeration definition.
|
2010-11-13 03:47:06 +01:00
|
|
|
for (list<named_pexpr_t>::const_iterator cur = enum_type->names->begin()
|
2010-11-21 00:09:32 +01:00
|
|
|
; cur != enum_type->names->end() ; ++ cur, name_idx += 1) {
|
2014-11-02 20:44:37 +01:00
|
|
|
// Check to see if the enumeration name has a value given.
|
2010-11-13 03:47:06 +01:00
|
|
|
if (cur->parm) {
|
|
|
|
|
// There is an explicit value. elaborate/evaluate
|
|
|
|
|
// the value and assign it to the enumeration name.
|
2011-07-19 04:33:03 +02:00
|
|
|
NetExpr*val = elab_and_eval(des, scope, cur->parm, -1);
|
2025-10-21 07:45:05 +02:00
|
|
|
const NetEConst*val_const = dynamic_cast<NetEConst*> (val);
|
2010-11-13 03:47:06 +01:00
|
|
|
if (val_const == 0) {
|
2011-09-01 23:29:40 +02:00
|
|
|
cerr << use_enum->get_fileline()
|
2014-11-02 20:44:37 +01:00
|
|
|
<< ": error: Enumeration expression for "
|
2014-11-04 21:09:48 +01:00
|
|
|
<< cur->name <<" is not an integer constant."
|
2014-11-04 04:41:29 +01:00
|
|
|
<< endl;
|
2010-11-13 03:47:06 +01:00
|
|
|
des->errors += 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
cur_value = val_const->value();
|
2014-12-07 13:10:15 +01:00
|
|
|
// Clear the implicit wrapped flag if a parameter is given.
|
|
|
|
|
implicit_wrapped = false;
|
2010-11-13 03:47:06 +01:00
|
|
|
|
2014-11-02 20:44:37 +01:00
|
|
|
// A 2-state value can not have a constant with X/Z bits.
|
2022-03-15 08:24:33 +01:00
|
|
|
if (use_enum->base_type() == IVL_VT_BOOL &&
|
2011-07-19 04:33:03 +02:00
|
|
|
! cur_value.is_defined()) {
|
2011-09-01 23:29:40 +02:00
|
|
|
cerr << use_enum->get_fileline()
|
|
|
|
|
<< ": error: Enumeration name " << cur->name
|
2014-11-02 20:44:37 +01:00
|
|
|
<< " can not have an undefined value." << endl;
|
2010-11-13 03:47:06 +01:00
|
|
|
des->errors += 1;
|
2014-11-02 20:44:37 +01:00
|
|
|
}
|
2014-11-04 21:09:48 +01:00
|
|
|
// If this is a literal constant and it has a defined
|
|
|
|
|
// width then the width must match the enumeration width.
|
2025-10-21 07:45:05 +02:00
|
|
|
if (const PENumber *tmp = dynamic_cast<PENumber*>(cur->parm)) {
|
2014-11-04 21:09:48 +01:00
|
|
|
if (tmp->value().has_len() &&
|
|
|
|
|
(tmp->value().len() != enum_width)) {
|
|
|
|
|
cerr << use_enum->get_fileline()
|
|
|
|
|
<< ": error: Enumeration name " << cur->name
|
|
|
|
|
<< " has an incorrectly sized constant."
|
|
|
|
|
<< endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
2010-11-13 03:47:06 +01:00
|
|
|
}
|
|
|
|
|
|
2014-11-02 20:44:37 +01:00
|
|
|
// If we are padding/truncating a negative value for an
|
2014-11-03 05:25:35 +01:00
|
|
|
// unsigned enumeration that is an error or if the new
|
|
|
|
|
// value does not have a defined width.
|
|
|
|
|
if (((cur_value.len() != enum_width) ||
|
|
|
|
|
! cur_value.has_len()) &&
|
2022-03-15 08:24:33 +01:00
|
|
|
! is_signed && cur_value.is_negative()) {
|
2014-11-02 20:44:37 +01:00
|
|
|
cerr << use_enum->get_fileline()
|
|
|
|
|
<< ": error: Enumeration name " << cur->name
|
|
|
|
|
<< " has a negative value." << endl;
|
2010-11-13 03:47:06 +01:00
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-02 20:44:37 +01:00
|
|
|
// Narrower values need to be padded to the width of the
|
|
|
|
|
// enumeration and defined to have the specified width.
|
|
|
|
|
if (cur_value.len() < enum_width) {
|
|
|
|
|
cur_value = pad_to_width(cur_value, enum_width);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Some wider values can be truncated.
|
|
|
|
|
if (cur_value.len() > enum_width) {
|
|
|
|
|
unsigned check_width = enum_width - 1;
|
|
|
|
|
// Check that the upper bits match the MSB
|
|
|
|
|
for (unsigned idx = enum_width;
|
|
|
|
|
idx < cur_value.len();
|
|
|
|
|
idx += 1) {
|
|
|
|
|
if (cur_value[idx] != cur_value[check_width]) {
|
|
|
|
|
// If this is an unsigned enumeration
|
|
|
|
|
// then zero padding is okay.
|
2022-03-15 08:24:33 +01:00
|
|
|
if (!is_signed &&
|
2014-11-02 20:44:37 +01:00
|
|
|
(idx == enum_width) &&
|
|
|
|
|
(cur_value[idx] == verinum::V0)) {
|
|
|
|
|
check_width += 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (cur_value.is_defined()) {
|
|
|
|
|
cerr << use_enum->get_fileline()
|
|
|
|
|
<< ": error: Enumeration name "
|
|
|
|
|
<< cur->name
|
|
|
|
|
<< " has a value that is too "
|
|
|
|
|
<< ((cur_value > max_value) ?
|
|
|
|
|
"large" : "small")
|
|
|
|
|
<< " " << cur_value << "."
|
|
|
|
|
<< endl;
|
|
|
|
|
} else {
|
|
|
|
|
cerr << use_enum->get_fileline()
|
|
|
|
|
<< ": error: Enumeration name "
|
|
|
|
|
<< cur->name
|
|
|
|
|
<< " has trimmed bits that do "
|
|
|
|
|
<< "not match the enumeration "
|
|
|
|
|
<< "MSB: " << cur_value << "."
|
|
|
|
|
<< endl;
|
|
|
|
|
}
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// If this is an unsigned value then make sure
|
|
|
|
|
// The upper bits are not 1.
|
|
|
|
|
if (! cur_value.has_sign() &&
|
|
|
|
|
(cur_value[enum_width] == verinum::V1)) {
|
|
|
|
|
cerr << use_enum->get_fileline()
|
|
|
|
|
<< ": error: Enumeration name "
|
|
|
|
|
<< cur->name
|
|
|
|
|
<< " has a value that is too large: "
|
|
|
|
|
<< cur_value << "." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
cur_value = verinum(cur_value, enum_width);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// At this point the value has the correct size and needs
|
|
|
|
|
// to have the correct sign attribute set.
|
|
|
|
|
cur_value.has_len(true);
|
2022-03-15 08:24:33 +01:00
|
|
|
cur_value.has_sign(is_signed);
|
2014-11-02 20:44:37 +01:00
|
|
|
|
2010-11-13 03:47:06 +01:00
|
|
|
} else if (! cur_value.is_defined()) {
|
2011-09-01 23:29:40 +02:00
|
|
|
cerr << use_enum->get_fileline()
|
|
|
|
|
<< ": error: Enumeration name " << cur->name
|
2014-11-02 20:44:37 +01:00
|
|
|
<< " has an undefined inferred value." << endl;
|
2010-11-13 03:47:06 +01:00
|
|
|
des->errors += 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2014-12-07 13:10:15 +01:00
|
|
|
// Check to see if an implicitly wrapped value is used.
|
|
|
|
|
if (implicit_wrapped) {
|
2011-09-01 23:29:40 +02:00
|
|
|
cerr << use_enum->get_fileline()
|
|
|
|
|
<< ": error: Enumeration name " << cur->name
|
2014-11-02 20:44:37 +01:00
|
|
|
<< " has an inferred value that overflowed." << endl;
|
2011-07-19 04:33:03 +02:00
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2011-09-30 04:34:23 +02:00
|
|
|
// The enumeration value must be unique.
|
|
|
|
|
perm_string dup_name = use_enum->find_value(cur_value);
|
|
|
|
|
if (dup_name) {
|
|
|
|
|
cerr << use_enum->get_fileline()
|
|
|
|
|
<< ": error: Enumeration name "
|
|
|
|
|
<< cur->name << " and " << dup_name
|
|
|
|
|
<< " have the same value: " << cur_value << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2014-11-02 20:44:37 +01:00
|
|
|
rc_flag = use_enum->insert_name(name_idx, cur->name, cur_value);
|
2017-10-21 16:04:25 +02:00
|
|
|
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
|
2013-12-15 22:55:26 +01:00
|
|
|
|
2010-11-04 04:11:19 +01:00
|
|
|
if (! rc_flag) {
|
2011-09-01 23:29:40 +02:00
|
|
|
cerr << use_enum->get_fileline()
|
|
|
|
|
<< ": error: Duplicate enumeration name "
|
2011-07-19 04:33:03 +02:00
|
|
|
<< cur->name << endl;
|
2010-10-31 19:26:09 +01:00
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
2010-11-13 03:47:06 +01:00
|
|
|
|
|
|
|
|
// In case the next name has an implicit value,
|
|
|
|
|
// increment the current value by one.
|
2014-11-02 20:44:37 +01:00
|
|
|
if (cur_value.is_defined()) {
|
2014-12-07 13:10:15 +01:00
|
|
|
if (cur_value == max_value) implicit_wrapped = true;
|
2010-11-13 03:47:06 +01:00
|
|
|
cur_value = cur_value + one_value;
|
2014-11-02 20:44:37 +01:00
|
|
|
}
|
2010-10-31 19:26:09 +01:00
|
|
|
}
|
2013-04-15 03:03:21 +02:00
|
|
|
|
|
|
|
|
use_enum->insert_name_close();
|
2010-10-31 19:26:09 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void elaborate_scope_enumerations(Design*des, NetScope*scope,
|
2022-01-22 11:30:48 +01:00
|
|
|
const vector<enum_type_t*>&enum_types)
|
2010-10-31 19:26:09 +01:00
|
|
|
{
|
2020-12-25 03:12:06 +01:00
|
|
|
if (debug_scopes) {
|
|
|
|
|
cerr << scope->get_fileline() << ": " << __func__ << ": "
|
|
|
|
|
<< "Elaborate " << enum_types.size() << " enumerations"
|
|
|
|
|
<< " in scope " << scope_path(scope) << "."
|
|
|
|
|
<< endl;
|
|
|
|
|
}
|
|
|
|
|
|
2022-01-22 11:30:48 +01:00
|
|
|
for (vector<enum_type_t*>::const_iterator cur = enum_types.begin()
|
2010-11-04 04:11:19 +01:00
|
|
|
; cur != enum_types.end() ; ++ cur) {
|
2013-12-05 00:25:14 +01:00
|
|
|
enum_type_t*curp = *cur;
|
|
|
|
|
elaborate_scope_enumeration(des, scope, curp);
|
2010-10-31 19:26:09 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-24 22:42:28 +02:00
|
|
|
/*
|
|
|
|
|
* If the pclass includes an implicit and explicit constructor, then
|
|
|
|
|
* merge the implicit constructor into the explicit constructor as
|
|
|
|
|
* statements in the beginning.
|
|
|
|
|
*
|
|
|
|
|
* This is not necessary for proper functionality, it is an
|
|
|
|
|
* optimization, so we can easily give up if it doesn't seem like it
|
|
|
|
|
* will obviously work.
|
|
|
|
|
*/
|
|
|
|
|
static void blend_class_constructors(PClass*pclass)
|
|
|
|
|
{
|
|
|
|
|
perm_string new1 = perm_string::literal("new");
|
|
|
|
|
perm_string new2 = perm_string::literal("new@");
|
|
|
|
|
|
2013-11-05 03:04:19 +01:00
|
|
|
PFunction*use_new;
|
|
|
|
|
PFunction*use_new2;
|
|
|
|
|
|
|
|
|
|
// Locate the explicit constructor.
|
2013-06-24 22:42:28 +02:00
|
|
|
map<perm_string,PFunction*>::iterator iter_new = pclass->funcs.find(new1);
|
|
|
|
|
if (iter_new == pclass->funcs.end())
|
2013-11-05 03:04:19 +01:00
|
|
|
use_new = 0;
|
|
|
|
|
else
|
|
|
|
|
use_new = iter_new->second;
|
|
|
|
|
|
|
|
|
|
// Locate the implicit constructor.
|
|
|
|
|
map<perm_string,PFunction*>::iterator iter_new2 = pclass->funcs.find(new2);
|
|
|
|
|
if (iter_new2 == pclass->funcs.end())
|
|
|
|
|
use_new2 = 0;
|
|
|
|
|
else
|
|
|
|
|
use_new2 = iter_new2->second;
|
|
|
|
|
|
|
|
|
|
// If there are no constructors, then we are done.
|
|
|
|
|
if (use_new==0 && use_new2==0)
|
2013-06-24 22:42:28 +02:00
|
|
|
return;
|
|
|
|
|
|
2013-11-04 00:20:30 +01:00
|
|
|
// While we're here, look for a super.new() call. If we find
|
|
|
|
|
// it, strip it out of the constructor and set it aside for
|
|
|
|
|
// when we actually call the chained constructor.
|
2022-12-28 08:59:39 +01:00
|
|
|
PChainConstructor*chain_new = use_new? use_new->extract_chain_constructor() : NULL;
|
2013-11-10 04:45:03 +01:00
|
|
|
|
|
|
|
|
// If we do not have an explicit constructor chain, but there
|
|
|
|
|
// is a parent class, then create an implicit chain.
|
2022-03-24 11:05:33 +01:00
|
|
|
if (chain_new==0 && pclass->type->base_type) {
|
2013-11-10 17:21:22 +01:00
|
|
|
chain_new = new PChainConstructor(pclass->type->base_args);
|
2013-11-10 04:45:03 +01:00
|
|
|
chain_new->set_line(*pclass);
|
|
|
|
|
}
|
2013-11-05 03:04:19 +01:00
|
|
|
|
2013-11-10 04:45:03 +01:00
|
|
|
// If there are both an implicit and explicit constructor,
|
|
|
|
|
// then blend the implicit constructor into the explicit
|
|
|
|
|
// constructor. This eases the task for the elaborator later.
|
2013-11-05 03:04:19 +01:00
|
|
|
if (use_new && use_new2) {
|
|
|
|
|
// These constructors must be methods of the same class.
|
|
|
|
|
ivl_assert(*use_new, use_new->method_of() == use_new2->method_of());
|
|
|
|
|
|
|
|
|
|
Statement*def_new = use_new->get_statement();
|
|
|
|
|
Statement*def_new2 = use_new2->get_statement();
|
|
|
|
|
|
|
|
|
|
// It is possible, i.e. recovering from a parse error,
|
|
|
|
|
// for the statement from the constructor to be
|
|
|
|
|
// missing. In that case, create an empty one.
|
|
|
|
|
if (def_new==0) {
|
|
|
|
|
def_new = new PBlock(PBlock::BL_SEQ);
|
|
|
|
|
use_new->set_statement(def_new);
|
|
|
|
|
}
|
2013-06-24 22:42:28 +02:00
|
|
|
|
2013-11-10 04:45:03 +01:00
|
|
|
if (def_new2) use_new->push_statement_front(def_new2);
|
2013-06-24 22:42:28 +02:00
|
|
|
|
2013-11-05 03:04:19 +01:00
|
|
|
// Now the implicit initializations are all built into
|
|
|
|
|
// the constructor. Delete the "new@" constructor.
|
|
|
|
|
pclass->funcs.erase(iter_new2);
|
|
|
|
|
delete use_new2;
|
|
|
|
|
use_new2 = 0;
|
|
|
|
|
}
|
2013-06-24 22:42:28 +02:00
|
|
|
|
2013-11-10 04:45:03 +01:00
|
|
|
if (chain_new) {
|
|
|
|
|
if (use_new2) {
|
|
|
|
|
use_new2->push_statement_front(chain_new);
|
|
|
|
|
} else {
|
|
|
|
|
use_new->push_statement_front(chain_new);
|
|
|
|
|
}
|
|
|
|
|
}
|
2013-06-24 22:42:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void elaborate_scope_class(Design*des, NetScope*scope, PClass*pclass)
|
2012-11-12 02:42:31 +01:00
|
|
|
{
|
2012-11-25 19:13:05 +01:00
|
|
|
class_type_t*use_type = pclass->type;
|
|
|
|
|
|
2013-03-15 04:08:32 +01:00
|
|
|
if (debug_scopes) {
|
2013-04-29 01:28:24 +02:00
|
|
|
cerr << pclass->get_fileline() <<": elaborate_scope_class: "
|
2019-09-30 03:27:27 +02:00
|
|
|
<< "Elaborate scope class " << pclass->pscope_name()
|
|
|
|
|
<< " within scope " << scope_path(scope)
|
|
|
|
|
<< endl;
|
2013-03-15 04:08:32 +01:00
|
|
|
}
|
|
|
|
|
|
2013-10-31 02:35:00 +01:00
|
|
|
|
2022-03-19 21:15:53 +01:00
|
|
|
const netclass_t*use_base_class = 0;
|
|
|
|
|
if (use_type->base_type) {
|
|
|
|
|
ivl_type_t base_type = use_type->base_type->elaborate_type(des, scope);
|
|
|
|
|
use_base_class = dynamic_cast<const netclass_t *>(base_type);
|
|
|
|
|
if (!use_base_class) {
|
2013-10-31 02:35:00 +01:00
|
|
|
cerr << pclass->get_fileline() << ": error: "
|
2022-03-19 21:15:53 +01:00
|
|
|
<< "Base type of " << use_type->name
|
|
|
|
|
<< " is not a class." << endl;
|
2013-10-31 02:35:00 +01:00
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2013-11-10 04:45:03 +01:00
|
|
|
netclass_t*use_class = new netclass_t(use_type->name, use_base_class);
|
2013-10-31 02:35:00 +01:00
|
|
|
|
2019-12-22 11:38:40 +01:00
|
|
|
NetScope*class_scope = new NetScope(scope, hname_t(pclass->pscope_name()),
|
2017-10-21 16:04:25 +02:00
|
|
|
NetScope::CLASS, scope->unit());
|
2013-04-30 20:51:16 +02:00
|
|
|
class_scope->set_line(pclass);
|
2013-03-15 04:08:32 +01:00
|
|
|
class_scope->set_class_def(use_class);
|
|
|
|
|
use_class->set_class_scope(class_scope);
|
2014-09-02 18:22:41 +02:00
|
|
|
use_class->set_definition_scope(scope);
|
2022-09-19 20:23:02 +02:00
|
|
|
use_class->set_virtual(use_type->virtual_class);
|
2016-07-22 23:48:20 +02:00
|
|
|
set_scope_timescale(des, class_scope, pclass);
|
2013-03-15 04:08:32 +01:00
|
|
|
|
2019-12-22 18:29:23 +01:00
|
|
|
class_scope->add_typedefs(&pclass->typedefs);
|
|
|
|
|
|
2022-02-05 11:29:27 +01:00
|
|
|
collect_scope_parameters(des, class_scope, pclass->parameters);
|
|
|
|
|
|
2024-02-12 19:38:00 +01:00
|
|
|
collect_scope_signals(class_scope, pclass->wires);
|
|
|
|
|
|
2019-09-30 03:27:27 +02:00
|
|
|
// Elaborate enum types declared in the class. We need these
|
|
|
|
|
// now because enumeration constants can be used during scope
|
|
|
|
|
// elaboration.
|
|
|
|
|
if (debug_scopes) {
|
|
|
|
|
cerr << pclass->get_fileline() << ": elaborate_scope_class: "
|
|
|
|
|
<< "Elaborate " << pclass->enum_sets.size() << " enumerations"
|
|
|
|
|
<< " in class " << scope_path(class_scope)
|
|
|
|
|
<< ", scope=" << scope_path(scope) << "."
|
|
|
|
|
<< endl;
|
|
|
|
|
}
|
|
|
|
|
elaborate_scope_enumerations(des, class_scope, pclass->enum_sets);
|
|
|
|
|
|
2013-03-02 23:51:44 +01:00
|
|
|
for (map<perm_string,PTask*>::iterator cur = pclass->tasks.begin()
|
|
|
|
|
; cur != pclass->tasks.end() ; ++cur) {
|
2013-03-15 04:08:32 +01:00
|
|
|
|
|
|
|
|
hname_t use_name (cur->first);
|
|
|
|
|
NetScope*method_scope = new NetScope(class_scope, use_name, NetScope::TASK);
|
2022-12-19 01:11:54 +01:00
|
|
|
|
2013-03-15 04:08:32 +01:00
|
|
|
// Task methods are always automatic...
|
2022-12-19 01:11:54 +01:00
|
|
|
if (!cur->second->is_auto()) {
|
|
|
|
|
cerr << "error: Lifetime of method `"
|
|
|
|
|
<< scope_path(method_scope)
|
|
|
|
|
<< "` must not be static" << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
2013-03-15 04:08:32 +01:00
|
|
|
method_scope->is_auto(true);
|
|
|
|
|
method_scope->set_line(cur->second);
|
2019-09-27 00:35:57 +02:00
|
|
|
method_scope->add_imports(&cur->second->explicit_imports);
|
2013-03-15 04:08:32 +01:00
|
|
|
|
|
|
|
|
if (debug_scopes) {
|
2013-04-29 01:28:24 +02:00
|
|
|
cerr << cur->second->get_fileline() << ": elaborate_scope_class: "
|
2013-03-15 04:08:32 +01:00
|
|
|
<< "Elaborate method (task) scope "
|
|
|
|
|
<< scope_path(method_scope) << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cur->second->elaborate_scope(des, method_scope);
|
2013-03-02 23:51:44 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (map<perm_string,PFunction*>::iterator cur = pclass->funcs.begin()
|
|
|
|
|
; cur != pclass->funcs.end() ; ++cur) {
|
2013-03-15 04:08:32 +01:00
|
|
|
|
|
|
|
|
hname_t use_name (cur->first);
|
|
|
|
|
NetScope*method_scope = new NetScope(class_scope, use_name, NetScope::FUNC);
|
2022-12-19 01:11:54 +01:00
|
|
|
|
2013-03-15 04:08:32 +01:00
|
|
|
// Function methods are always automatic...
|
2022-12-19 01:11:54 +01:00
|
|
|
if (!cur->second->is_auto()) {
|
|
|
|
|
cerr << "error: Lifetime of method `"
|
|
|
|
|
<< scope_path(method_scope)
|
|
|
|
|
<< "` must not be static" << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
2013-03-15 04:08:32 +01:00
|
|
|
method_scope->is_auto(true);
|
|
|
|
|
method_scope->set_line(cur->second);
|
2019-09-27 00:35:57 +02:00
|
|
|
method_scope->add_imports(&cur->second->explicit_imports);
|
2013-03-15 04:08:32 +01:00
|
|
|
|
|
|
|
|
if (debug_scopes) {
|
2013-04-29 01:28:24 +02:00
|
|
|
cerr << cur->second->get_fileline() << ": elaborate_scope_class: "
|
2013-03-15 04:08:32 +01:00
|
|
|
<< "Elaborate method (function) scope "
|
|
|
|
|
<< scope_path(method_scope) << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cur->second->elaborate_scope(des, method_scope);
|
2013-03-02 23:51:44 +01:00
|
|
|
}
|
|
|
|
|
|
2017-10-21 16:04:25 +02:00
|
|
|
scope->add_class(use_class);
|
2012-11-12 02:42:31 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void elaborate_scope_classes(Design*des, NetScope*scope,
|
2013-04-29 01:28:24 +02:00
|
|
|
const vector<PClass*>&classes)
|
2012-11-12 02:42:31 +01:00
|
|
|
{
|
2020-12-25 03:12:06 +01:00
|
|
|
if (debug_scopes) {
|
|
|
|
|
cerr << scope->get_fileline() << ": " << __func__ << ": "
|
|
|
|
|
<< "Elaborate " << classes.size() << " classes"
|
|
|
|
|
<< " in scope " << scope_path(scope) << "."
|
|
|
|
|
<< endl;
|
|
|
|
|
}
|
|
|
|
|
|
2013-06-24 22:42:28 +02:00
|
|
|
for (size_t idx = 0 ; idx < classes.size() ; idx += 1) {
|
|
|
|
|
blend_class_constructors(classes[idx]);
|
2013-04-29 01:28:24 +02:00
|
|
|
elaborate_scope_class(des, scope, classes[idx]);
|
2013-06-24 22:42:28 +02:00
|
|
|
}
|
2012-11-12 02:42:31 +01:00
|
|
|
}
|
|
|
|
|
|
2022-02-01 10:18:26 +01:00
|
|
|
static void replace_scope_parameters(Design *des, NetScope*scope, const LineInfo&loc,
|
2020-12-25 03:12:06 +01:00
|
|
|
const Module::replace_t&replacements)
|
2008-09-17 22:25:59 +02:00
|
|
|
{
|
2020-12-25 03:12:06 +01:00
|
|
|
if (debug_scopes) {
|
|
|
|
|
cerr << scope->get_fileline() << ": " << __func__ << ": "
|
|
|
|
|
<< "Replace scope parameters for " << scope_path(scope) << "." << endl;
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-17 22:25:59 +02:00
|
|
|
for (Module::replace_t::const_iterator cur = replacements.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; cur != replacements.end() ; ++ cur ) {
|
2008-09-17 22:25:59 +02:00
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
PExpr*val = (*cur).second;
|
2008-09-17 22:25:59 +02:00
|
|
|
if (val == 0) {
|
|
|
|
|
cerr << loc.get_fileline() << ": internal error: "
|
|
|
|
|
<< "Missing expression in parameter replacement for "
|
2009-10-14 02:43:00 +02:00
|
|
|
<< (*cur).first << endl;;
|
2008-09-17 22:25:59 +02:00
|
|
|
}
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(loc, val);
|
2008-09-17 22:25:59 +02:00
|
|
|
if (debug_scopes) {
|
|
|
|
|
cerr << loc.get_fileline() << ": debug: "
|
|
|
|
|
<< "Replace " << (*cur).first
|
|
|
|
|
<< " with expression " << *val
|
|
|
|
|
<< " from " << val->get_fileline() << "." << endl;
|
|
|
|
|
cerr << loc.get_fileline() << ": : "
|
|
|
|
|
<< "Type=" << val->expr_type() << endl;
|
|
|
|
|
}
|
2022-02-01 10:18:26 +01:00
|
|
|
scope->replace_parameter(des, (*cur).first, val, scope->parent());
|
2008-09-17 22:25:59 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void elaborate_scope_events_(Design*des, NetScope*scope,
|
|
|
|
|
const map<perm_string,PEvent*>&events)
|
|
|
|
|
{
|
|
|
|
|
for (map<perm_string,PEvent*>::const_iterator et = events.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; et != events.end() ; ++ et ) {
|
2008-09-17 22:25:59 +02:00
|
|
|
|
|
|
|
|
(*et).second->elaborate_scope(des, scope);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2014-10-01 01:06:32 +02:00
|
|
|
static void elaborate_scope_task(Design*des, NetScope*scope, PTask*task)
|
|
|
|
|
{
|
|
|
|
|
hname_t use_name( task->pscope_name() );
|
|
|
|
|
|
|
|
|
|
NetScope*task_scope = new NetScope(scope, use_name, NetScope::TASK);
|
|
|
|
|
task_scope->is_auto(task->is_auto());
|
|
|
|
|
task_scope->set_line(task);
|
2019-09-27 00:35:57 +02:00
|
|
|
task_scope->add_imports(&task->explicit_imports);
|
2014-10-01 01:06:32 +02:00
|
|
|
|
|
|
|
|
if (debug_scopes) {
|
|
|
|
|
cerr << task->get_fileline() << ": elaborate_scope_task: "
|
|
|
|
|
<< "Elaborate task scope " << scope_path(task_scope) << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
task->elaborate_scope(des, task_scope);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-19 06:54:58 +02:00
|
|
|
static void elaborate_scope_tasks(Design*des, NetScope*scope,
|
|
|
|
|
const map<perm_string,PTask*>&tasks)
|
|
|
|
|
{
|
|
|
|
|
typedef map<perm_string,PTask*>::const_iterator tasks_it_t;
|
|
|
|
|
|
|
|
|
|
for (tasks_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
|
|
|
|
2014-10-01 01:06:32 +02:00
|
|
|
elaborate_scope_task(des, scope, cur->second);
|
|
|
|
|
}
|
2008-06-19 06:54:58 +02:00
|
|
|
|
2014-10-01 01:06:32 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void elaborate_scope_func(Design*des, NetScope*scope, PFunction*task)
|
|
|
|
|
{
|
|
|
|
|
hname_t use_name( task->pscope_name() );
|
|
|
|
|
|
|
|
|
|
NetScope*task_scope = new NetScope(scope, use_name, NetScope::FUNC);
|
|
|
|
|
task_scope->is_auto(task->is_auto());
|
|
|
|
|
task_scope->set_line(task);
|
2019-09-27 00:35:57 +02:00
|
|
|
task_scope->add_imports(&task->explicit_imports);
|
2008-06-19 06:54:58 +02:00
|
|
|
|
2014-10-01 01:06:32 +02:00
|
|
|
if (debug_scopes) {
|
|
|
|
|
cerr << task->get_fileline() << ": elaborate_scope_func: "
|
2022-02-27 17:56:30 +01:00
|
|
|
<< "Elaborate function scope " << scope_path(task_scope)
|
|
|
|
|
<< endl;
|
2008-06-19 06:54:58 +02:00
|
|
|
}
|
|
|
|
|
|
2014-10-01 01:06:32 +02:00
|
|
|
task->elaborate_scope(des, task_scope);
|
2008-06-19 06:54:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void elaborate_scope_funcs(Design*des, NetScope*scope,
|
|
|
|
|
const map<perm_string,PFunction*>&funcs)
|
|
|
|
|
{
|
|
|
|
|
typedef map<perm_string,PFunction*>::const_iterator funcs_it_t;
|
|
|
|
|
|
|
|
|
|
for (funcs_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
|
|
|
|
2014-10-01 01:06:32 +02:00
|
|
|
elaborate_scope_func(des, scope, cur->second);
|
2008-06-19 06:54:58 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-28 20:06:14 +02:00
|
|
|
class generate_schemes_work_item_t : public elaborator_work_item_t {
|
|
|
|
|
public:
|
2008-10-13 18:51:05 +02:00
|
|
|
generate_schemes_work_item_t(Design*des__, NetScope*scope, Module*mod)
|
|
|
|
|
: elaborator_work_item_t(des__), scope_(scope), mod_(mod)
|
2008-06-28 20:06:14 +02:00
|
|
|
{ }
|
|
|
|
|
|
2025-10-21 07:45:05 +02:00
|
|
|
void elaborate_runrun() override
|
2008-06-28 20:06:14 +02:00
|
|
|
{
|
|
|
|
|
if (debug_scopes)
|
|
|
|
|
cerr << mod_->get_fileline() << ": debug: "
|
|
|
|
|
<< "Processing generate schemes for "
|
|
|
|
|
<< scope_path(scope_) << endl;
|
|
|
|
|
|
|
|
|
|
// Generate schemes can create new scopes in the form of
|
|
|
|
|
// generated code. Scan the generate schemes, and *generate*
|
|
|
|
|
// new scopes, which is slightly different from simple
|
|
|
|
|
// elaboration.
|
|
|
|
|
typedef list<PGenerate*>::const_iterator generate_it_t;
|
|
|
|
|
for (generate_it_t cur = mod_->generate_schemes.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; cur != mod_->generate_schemes.end() ; ++ cur ) {
|
2008-06-28 20:06:14 +02:00
|
|
|
(*cur) -> generate_scope(des, scope_);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
// The scope_ is the scope that contains the generate scheme
|
|
|
|
|
// we are to work on. the mod_ is the Module definition for
|
|
|
|
|
// that scope, and contains the parsed generate schemes.
|
|
|
|
|
NetScope*scope_;
|
|
|
|
|
Module*mod_;
|
|
|
|
|
};
|
|
|
|
|
|
2013-02-17 23:42:07 +01:00
|
|
|
bool PPackage::elaborate_scope(Design*des, NetScope*scope)
|
|
|
|
|
{
|
|
|
|
|
if (debug_scopes) {
|
2014-10-11 03:53:53 +02:00
|
|
|
cerr << get_fileline() << ": PPackage::elaborate_scope: "
|
|
|
|
|
<< "Elaborate package " << scope_path(scope) << "." << endl;
|
2013-02-17 23:42:07 +01:00
|
|
|
}
|
|
|
|
|
|
2019-12-22 18:29:23 +01:00
|
|
|
scope->add_typedefs(&typedefs);
|
|
|
|
|
|
2020-12-25 03:12:06 +01:00
|
|
|
collect_scope_parameters(des, scope, parameters);
|
2019-09-30 03:27:27 +02:00
|
|
|
|
2024-02-12 19:38:00 +01:00
|
|
|
collect_scope_signals(scope, wires);
|
|
|
|
|
|
2019-09-30 03:27:27 +02:00
|
|
|
if (debug_scopes) {
|
|
|
|
|
cerr << get_fileline() << ": PPackage::elaborate_scope: "
|
|
|
|
|
<< "Elaborate " << enum_sets.size() << " enumerations"
|
|
|
|
|
<< " in package scope " << scope_path(scope) << "."
|
|
|
|
|
<< endl;
|
|
|
|
|
}
|
2014-08-28 22:01:17 +02:00
|
|
|
elaborate_scope_enumerations(des, scope, enum_sets);
|
2019-09-30 03:27:27 +02:00
|
|
|
|
2014-10-11 03:53:53 +02:00
|
|
|
elaborate_scope_classes(des, scope, classes_lexical);
|
2013-04-07 02:38:36 +02:00
|
|
|
elaborate_scope_funcs(des, scope, funcs);
|
|
|
|
|
elaborate_scope_tasks(des, scope, tasks);
|
2019-09-28 22:00:17 +02:00
|
|
|
elaborate_scope_events_(des, scope, events);
|
2013-02-17 23:42:07 +01:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2006-03-30 03:49:07 +02:00
|
|
|
bool Module::elaborate_scope(Design*des, NetScope*scope,
|
2008-06-28 18:30:09 +02:00
|
|
|
const replace_t&replacements)
|
2000-03-08 05:36:53 +01:00
|
|
|
{
|
2004-09-05 19:44:41 +02:00
|
|
|
if (debug_scopes) {
|
2014-10-11 03:53:53 +02:00
|
|
|
cerr << get_fileline() << ": Module::elaborate_scope: "
|
|
|
|
|
<< "Elaborate " << scope_path(scope) << "." << endl;
|
2004-09-05 19:44:41 +02:00
|
|
|
}
|
|
|
|
|
|
2019-12-22 18:29:23 +01:00
|
|
|
scope->add_typedefs(&typedefs);
|
|
|
|
|
|
2009-07-28 20:42:07 +02:00
|
|
|
// Add the genvars to the scope.
|
|
|
|
|
typedef map<perm_string,LineInfo*>::const_iterator genvar_it_t;
|
2010-10-23 23:57:59 +02:00
|
|
|
for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); ++ cur ) {
|
2009-07-28 20:42:07 +02:00
|
|
|
scope->add_genvar((*cur).first, (*cur).second);
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
// Scan the parameters in the module, and store the information
|
|
|
|
|
// needed to evaluate the parameter expressions. The expressions
|
|
|
|
|
// will be evaluated later, once all parameter overrides for this
|
|
|
|
|
// module have been done.
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2020-12-25 03:12:06 +01:00
|
|
|
collect_scope_parameters(des, scope, parameters);
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2020-12-25 03:12:06 +01:00
|
|
|
collect_scope_specparams(des, scope, specparams);
|
2012-05-07 00:11:26 +02:00
|
|
|
|
2024-02-12 19:38:00 +01:00
|
|
|
collect_scope_signals(scope, wires);
|
|
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
// Run parameter replacements that were collected from the
|
|
|
|
|
// containing scope and meant for me.
|
2000-03-12 18:09:40 +01:00
|
|
|
|
2022-02-01 10:18:26 +01:00
|
|
|
replace_scope_parameters(des, scope, *this, replacements);
|
2000-03-12 18:09:40 +01:00
|
|
|
|
2010-10-31 19:26:09 +01:00
|
|
|
elaborate_scope_enumerations(des, scope, enum_sets);
|
|
|
|
|
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, classes.size() == classes_lexical.size());
|
2013-04-29 01:28:24 +02:00
|
|
|
elaborate_scope_classes(des, scope, classes_lexical);
|
2012-11-12 02:42:31 +01:00
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
// Run through the defparams for this module and save the result
|
|
|
|
|
// in a table for later final override.
|
2011-03-03 05:23:02 +01:00
|
|
|
|
2008-08-10 01:45:20 +02:00
|
|
|
typedef list<Module::named_expr_t>::const_iterator defparms_iter_t;
|
|
|
|
|
for (defparms_iter_t cur = defparms.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; cur != defparms.end() ; ++ cur ) {
|
2010-12-05 22:28:17 +01:00
|
|
|
scope->defparams.push_back(make_pair(cur->first, cur->second));
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
2003-06-20 02:53:19 +02:00
|
|
|
// Evaluate the attributes. Evaluate them in the scope of the
|
|
|
|
|
// module that the attribute is attached to. Is this correct?
|
|
|
|
|
unsigned nattr;
|
|
|
|
|
attrib_list_t*attr = evaluate_attributes(attributes, nattr, des, scope);
|
|
|
|
|
|
|
|
|
|
for (unsigned idx = 0 ; idx < nattr ; idx += 1)
|
|
|
|
|
scope->attribute(attr[idx].key, attr[idx].val);
|
|
|
|
|
|
|
|
|
|
delete[]attr;
|
|
|
|
|
|
2008-06-28 20:06:14 +02:00
|
|
|
// Generate schemes need to have their scopes elaborated, but
|
2014-11-02 20:44:37 +01:00
|
|
|
// we can not do that until defparams are run, so push it off
|
2008-06-28 20:06:14 +02:00
|
|
|
// into an elaborate work item.
|
|
|
|
|
if (debug_scopes)
|
2020-12-25 03:12:06 +01:00
|
|
|
cerr << get_fileline() << ": " << __func__ << ": "
|
2008-06-28 20:06:14 +02:00
|
|
|
<< "Schedule generates within " << scope_path(scope)
|
|
|
|
|
<< " for elaboration after defparams." << endl;
|
2006-04-10 02:37:42 +02:00
|
|
|
|
2008-06-28 20:06:14 +02:00
|
|
|
des->elaboration_work_list.push_back(new generate_schemes_work_item_t(des, scope, this));
|
2000-03-08 05:36:53 +01:00
|
|
|
|
|
|
|
|
// Tasks introduce new scopes, so scan the tasks in this
|
|
|
|
|
// module. Create a scope for the task and pass that to the
|
|
|
|
|
// elaborate_scope method of the PTask for detailed
|
|
|
|
|
// processing.
|
|
|
|
|
|
2010-11-01 22:37:06 +01:00
|
|
|
elaborate_scope_tasks(des, scope, tasks);
|
2000-03-08 05:36:53 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
// Functions are very similar to tasks, at least from the
|
|
|
|
|
// perspective of scopes. So handle them exactly the same
|
|
|
|
|
// way.
|
|
|
|
|
|
2010-11-01 22:37:06 +01:00
|
|
|
elaborate_scope_funcs(des, scope, funcs);
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2012-05-10 04:35:11 +02:00
|
|
|
// Look for implicit modules and implicit gates for them.
|
|
|
|
|
|
|
|
|
|
for (map<perm_string,Module*>::iterator cur = nested_modules.begin()
|
|
|
|
|
; cur != nested_modules.end() ; ++cur) {
|
|
|
|
|
// Skip modules that must be explicitly instantiated.
|
|
|
|
|
if (cur->second->port_count() > 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
PGModule*nested_gate = new PGModule(cur->second, cur->second->mod_name());
|
|
|
|
|
nested_gate->set_line(*cur->second);
|
|
|
|
|
gates_.push_back(nested_gate);
|
|
|
|
|
}
|
|
|
|
|
|
2000-03-08 05:36:53 +01:00
|
|
|
// Gates include modules, which might introduce new scopes, so
|
|
|
|
|
// scan all of them to create those scopes.
|
|
|
|
|
|
|
|
|
|
typedef list<PGate*>::const_iterator gates_it_t;
|
|
|
|
|
for (gates_it_t cur = gates_.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; cur != gates_.end() ; ++ cur ) {
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2000-03-11 04:25:51 +01:00
|
|
|
(*cur) -> elaborate_scope(des, scope);
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-03-11 04:25:51 +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 ) {
|
2000-03-11 04:25:51 +01:00
|
|
|
|
|
|
|
|
(*cur) -> statement() -> elaborate_scope(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-09 19:44:30 +02:00
|
|
|
// Scan through all the named events in this scope. We do not
|
2007-03-22 17:08:14 +01:00
|
|
|
// need anything more than the current scope to do this
|
2000-04-09 19:44:30 +02:00
|
|
|
// elaboration, so do it now. This allows for normal
|
|
|
|
|
// elaboration to reference these events.
|
|
|
|
|
|
2008-09-17 22:25:59 +02:00
|
|
|
elaborate_scope_events_(des, scope, events);
|
2000-04-09 19:44:30 +02:00
|
|
|
|
2009-05-21 23:41:58 +02:00
|
|
|
scope->is_cell(is_cell);
|
|
|
|
|
|
2000-03-08 05:36:53 +01:00
|
|
|
return des->errors == 0;
|
|
|
|
|
}
|
|
|
|
|
|
2006-04-10 02:37:42 +02:00
|
|
|
bool PGenerate::generate_scope(Design*des, NetScope*container)
|
|
|
|
|
{
|
|
|
|
|
switch (scheme_type) {
|
|
|
|
|
case GS_LOOP:
|
|
|
|
|
return generate_scope_loop_(des, container);
|
|
|
|
|
|
2007-06-22 04:04:48 +02:00
|
|
|
case GS_CONDIT:
|
|
|
|
|
return generate_scope_condit_(des, container, false);
|
|
|
|
|
|
|
|
|
|
case GS_ELSE:
|
|
|
|
|
return generate_scope_condit_(des, container, true);
|
|
|
|
|
|
2008-02-10 07:19:42 +01:00
|
|
|
case GS_CASE:
|
|
|
|
|
return generate_scope_case_(des, container);
|
2008-11-15 03:35:39 +01:00
|
|
|
|
|
|
|
|
case GS_NBLOCK:
|
|
|
|
|
return generate_scope_nblock_(des, container);
|
2008-02-10 07:19:42 +01:00
|
|
|
|
|
|
|
|
case GS_CASE_ITEM:
|
|
|
|
|
cerr << get_fileline() << ": internal error: "
|
|
|
|
|
<< "Case item outside of a case generate scheme?" << endl;
|
|
|
|
|
return false;
|
|
|
|
|
|
2006-04-10 02:37:42 +02:00
|
|
|
default:
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": sorry: Generate of this sort"
|
2006-04-10 02:37:42 +02:00
|
|
|
<< " is not supported yet!" << endl;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2021-12-13 22:20:09 +01:00
|
|
|
void PGenerate::check_for_valid_genvar_value_(long value)
|
|
|
|
|
{
|
|
|
|
|
if (generation_flag < GN_VER2005 && value < 0) {
|
|
|
|
|
cerr << get_fileline() << ": warning: A negative value (" << value
|
|
|
|
|
<< ") has been assigned to genvar '" << loop_index << "'."
|
|
|
|
|
<< endl;
|
|
|
|
|
cerr << get_fileline() << ": : This is illegal in "
|
|
|
|
|
"Verilog-2001. Use at least -g2005 to remove this warning."
|
|
|
|
|
<< endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2006-04-10 02:37:42 +02:00
|
|
|
/*
|
|
|
|
|
* This is the elaborate scope method for a generate loop.
|
|
|
|
|
*/
|
|
|
|
|
bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
|
|
|
|
{
|
2020-01-31 21:29:22 +01:00
|
|
|
if (!local_index) {
|
|
|
|
|
// Check that the loop_index variable was declared in a
|
|
|
|
|
// genvar statement.
|
|
|
|
|
NetScope*cscope = container;
|
2021-08-04 15:35:38 +02:00
|
|
|
while (cscope && !cscope->find_genvar(loop_index)) {
|
|
|
|
|
if (cscope->symbol_exists(loop_index)) {
|
|
|
|
|
cerr << get_fileline() << ": error: "
|
2025-06-22 01:57:04 +02:00
|
|
|
<< "generate \"loop\" variable '" << loop_index
|
2021-08-04 15:35:38 +02:00
|
|
|
<< "' is not a genvar in this scope." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2020-01-31 21:29:22 +01:00
|
|
|
cscope = cscope->parent();
|
2021-08-04 15:35:38 +02:00
|
|
|
}
|
2020-01-31 21:29:22 +01:00
|
|
|
if (!cscope) {
|
|
|
|
|
cerr << get_fileline() << ": error: genvar is missing for "
|
|
|
|
|
"generate \"loop\" variable '" << loop_index << "'."
|
|
|
|
|
<< endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2009-07-28 20:42:07 +02:00
|
|
|
}
|
2008-05-06 04:46:30 +02:00
|
|
|
|
2006-04-10 02:37:42 +02:00
|
|
|
// We're going to need a genvar...
|
2021-12-13 21:28:41 +01:00
|
|
|
long genvar;
|
2006-04-10 02:37:42 +02:00
|
|
|
|
|
|
|
|
// The initial value for the genvar does not need (nor can it
|
|
|
|
|
// use) the genvar itself, so we can evaluate this expression
|
2008-01-29 21:19:59 +01:00
|
|
|
// the same way any other parameter value is evaluated.
|
2011-03-27 12:08:33 +02:00
|
|
|
NetExpr*init_ex = elab_and_eval(des, container, loop_init, -1, true);
|
2025-10-21 07:45:05 +02:00
|
|
|
const NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
|
2006-04-10 02:37:42 +02:00
|
|
|
if (init == 0) {
|
2025-06-22 01:57:04 +02:00
|
|
|
cerr << get_fileline() << ": error: "
|
|
|
|
|
"Cannot evaluate generate \"loop\" initialization "
|
|
|
|
|
"expression: " << *loop_init << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
if (! init->value().is_defined()) {
|
|
|
|
|
cerr << get_fileline() << ": error: "
|
|
|
|
|
<< "Generate \"loop\" initialization expression cannot have "
|
|
|
|
|
"undefined bits. given (" << *loop_init << ")." << endl;
|
2006-04-10 02:37:42 +02:00
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
genvar = init->value().as_long();
|
2021-12-13 22:20:09 +01:00
|
|
|
check_for_valid_genvar_value_(genvar);
|
2006-04-10 02:37:42 +02:00
|
|
|
delete init_ex;
|
|
|
|
|
|
2008-02-10 07:19:42 +01:00
|
|
|
if (debug_scopes)
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": debug: genvar init = " << genvar << endl;
|
2025-06-22 01:57:04 +02:00
|
|
|
|
2006-04-10 02:37:42 +02:00
|
|
|
container->genvar_tmp = loop_index;
|
2007-11-17 21:53:45 +01:00
|
|
|
container->genvar_tmp_val = genvar;
|
2011-03-27 12:08:33 +02:00
|
|
|
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1, true);
|
2025-10-21 07:45:05 +02:00
|
|
|
const NetEConst*test = dynamic_cast<NetEConst*>(test_ex);
|
2008-08-07 00:46:43 +02:00
|
|
|
if (test == 0) {
|
2025-06-22 01:57:04 +02:00
|
|
|
cerr << get_fileline() << ": error: Cannot evaluate generate \"loop\" "
|
|
|
|
|
"conditional expression: " << *loop_test << endl;
|
2008-08-07 00:46:43 +02:00
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2025-06-22 01:57:04 +02:00
|
|
|
if (! test->value().is_defined()) {
|
|
|
|
|
cerr << get_fileline() << ": error: "
|
|
|
|
|
"Generate \"loop\" conditional expression cannot have "
|
|
|
|
|
"undefined bits. given (" << *loop_test << ")." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
unsigned long loop_count = 1;
|
2006-04-12 07:05:03 +02:00
|
|
|
while (test->value().as_long()) {
|
2006-04-10 02:37:42 +02:00
|
|
|
|
|
|
|
|
// The actual name of the scope includes the genvar so
|
|
|
|
|
// that each instance has a unique name in the
|
|
|
|
|
// container. The format of using [] is part of the
|
|
|
|
|
// Verilog standard.
|
2007-06-02 05:42:12 +02:00
|
|
|
hname_t use_name (scope_name, genvar);
|
2025-06-22 01:57:04 +02:00
|
|
|
if (container->child(use_name)) {
|
|
|
|
|
cerr << get_fileline() << ": error: "
|
|
|
|
|
"Trying to create a duplicate generate scope named \""
|
|
|
|
|
<< use_name << "\"." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2009-04-25 04:07:48 +02:00
|
|
|
|
2008-02-10 07:19:42 +01:00
|
|
|
if (debug_scopes)
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": debug: "
|
2025-06-22 01:57:04 +02:00
|
|
|
"Create generated scope " << use_name << endl;
|
2006-04-10 02:37:42 +02:00
|
|
|
|
|
|
|
|
NetScope*scope = new NetScope(container, use_name,
|
|
|
|
|
NetScope::GENBLOCK);
|
2008-04-30 03:58:25 +02:00
|
|
|
scope->set_line(get_file(), get_lineno());
|
2019-09-27 00:35:57 +02:00
|
|
|
scope->add_imports(&explicit_imports);
|
2006-04-10 02:37:42 +02:00
|
|
|
|
|
|
|
|
// Set in the scope a localparam for the value of the
|
|
|
|
|
// genvar within this instance of the generate
|
|
|
|
|
// block. Code within this scope thus has access to the
|
|
|
|
|
// genvar as a constant.
|
|
|
|
|
{
|
2020-10-01 12:33:24 +02:00
|
|
|
verinum genvar_verinum;
|
|
|
|
|
if (gn_strict_expr_width_flag)
|
|
|
|
|
genvar_verinum = verinum(genvar, integer_width);
|
|
|
|
|
else
|
|
|
|
|
genvar_verinum = verinum(genvar);
|
2006-04-10 02:37:42 +02:00
|
|
|
genvar_verinum.has_sign(true);
|
|
|
|
|
NetEConstParam*gp = new NetEConstParam(scope,
|
|
|
|
|
loop_index,
|
|
|
|
|
genvar_verinum);
|
2008-05-06 04:46:30 +02:00
|
|
|
// The file and line information should really come
|
|
|
|
|
// from the genvar statement, not the for loop.
|
2012-05-07 14:01:12 +02:00
|
|
|
scope->set_parameter(loop_index, gp, *this);
|
2008-02-10 07:19:42 +01:00
|
|
|
if (debug_scopes)
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": debug: "
|
2025-06-22 01:57:04 +02:00
|
|
|
"Create implicit localparam "
|
2007-03-05 06:59:10 +01:00
|
|
|
<< loop_index << " = " << genvar_verinum << endl;
|
2006-04-10 02:37:42 +02:00
|
|
|
}
|
|
|
|
|
|
2007-06-22 04:04:48 +02:00
|
|
|
elaborate_subscope_(des, scope);
|
2006-04-10 02:37:42 +02:00
|
|
|
|
|
|
|
|
// Calculate the step for the loop variable.
|
2011-03-27 12:08:33 +02:00
|
|
|
NetExpr*step_ex = elab_and_eval(des, container, loop_step, -1, true);
|
2006-04-12 07:05:03 +02:00
|
|
|
NetEConst*step = dynamic_cast<NetEConst*>(step_ex);
|
2008-08-07 00:46:43 +02:00
|
|
|
if (step == 0) {
|
2025-06-22 01:57:04 +02:00
|
|
|
cerr << get_fileline() << ": error: Cannot evaluate generate "
|
|
|
|
|
"\"loop\" increment expression: " << *loop_step << endl;
|
2008-08-07 00:46:43 +02:00
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2008-02-10 07:19:42 +01:00
|
|
|
if (debug_scopes)
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": debug: genvar step from "
|
2006-04-12 07:05:03 +02:00
|
|
|
<< genvar << " to " << step->value().as_long() << endl;
|
2006-04-10 02:37:42 +02:00
|
|
|
|
2025-06-22 01:57:04 +02:00
|
|
|
if (! step->value().is_defined()) {
|
|
|
|
|
cerr << get_fileline() << ": error: "
|
|
|
|
|
"Generate \"loop\" increment expression cannot have "
|
|
|
|
|
"undefined bits, given (" << *loop_step << ")." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
long next_genvar;
|
|
|
|
|
next_genvar = step->value().as_long();
|
|
|
|
|
if (next_genvar == genvar) {
|
|
|
|
|
cerr << get_fileline() << ": error: "
|
|
|
|
|
<< "The generate \"loop\" is not incrementing. The "
|
|
|
|
|
"previous and next genvar values are ("
|
|
|
|
|
<< genvar << ")." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
genvar = next_genvar;
|
2021-12-13 22:20:09 +01:00
|
|
|
check_for_valid_genvar_value_(genvar);
|
2006-04-10 02:37:42 +02:00
|
|
|
container->genvar_tmp_val = genvar;
|
|
|
|
|
delete step;
|
2006-04-12 07:05:03 +02:00
|
|
|
delete test_ex;
|
2017-02-11 20:47:01 +01:00
|
|
|
test_ex = elab_and_eval(des, container, loop_test, -1, true);
|
2006-04-12 07:05:03 +02:00
|
|
|
test = dynamic_cast<NetEConst*>(test_ex);
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, test);
|
2025-06-22 01:57:04 +02:00
|
|
|
if (! test->value().is_defined()) {
|
|
|
|
|
cerr << get_fileline() << ": error: "
|
|
|
|
|
"The generate \"loop\" conditional expression cannot have "
|
|
|
|
|
"undefined bits. given (" << *loop_test << ")." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If there are half a million iterations this is likely an infinite loop!
|
|
|
|
|
if (loop_count > 500000) {
|
|
|
|
|
cerr << get_fileline() << ": error: "
|
|
|
|
|
<< "Probable infinite loop detected in generate \"loop\". "
|
|
|
|
|
"It has run for " << loop_count
|
|
|
|
|
<< " iterations." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
++loop_count;
|
2006-04-10 02:37:42 +02:00
|
|
|
}
|
|
|
|
|
|
2006-04-12 07:05:03 +02:00
|
|
|
// Clear the genvar_tmp field in the scope to reflect that the
|
2009-07-28 20:42:07 +02:00
|
|
|
// genvar is no longer valid for evaluating expressions.
|
2006-04-10 02:37:42 +02:00
|
|
|
container->genvar_tmp = perm_string();
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2007-06-22 04:04:48 +02:00
|
|
|
bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else_flag)
|
|
|
|
|
{
|
2011-03-27 12:08:33 +02:00
|
|
|
NetExpr*test_ex = elab_and_eval(des, container, loop_test, -1, true);
|
2025-10-21 07:45:05 +02:00
|
|
|
const NetEConst*test = dynamic_cast<NetEConst*> (test_ex);
|
2008-08-07 00:46:43 +02:00
|
|
|
if (test == 0) {
|
|
|
|
|
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
|
|
|
|
<< " conditional expression: " << *loop_test << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2007-06-22 04:04:48 +02:00
|
|
|
|
|
|
|
|
// If the condition evaluates as false, then do not create the
|
|
|
|
|
// scope.
|
2008-01-05 04:21:26 +01:00
|
|
|
if ( (test->value().as_long() == 0 && !else_flag)
|
|
|
|
|
|| (test->value().as_long() != 0 && else_flag) ) {
|
2008-02-10 07:19:42 +01:00
|
|
|
if (debug_scopes)
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": debug: Generate condition "
|
2007-06-22 04:04:48 +02:00
|
|
|
<< (else_flag? "(else)" : "(if)")
|
|
|
|
|
<< " value=" << test->value() << ": skip generation"
|
|
|
|
|
<< endl;
|
|
|
|
|
delete test_ex;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
hname_t use_name (scope_name);
|
2008-02-10 07:19:42 +01:00
|
|
|
if (debug_scopes)
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": debug: Generate condition "
|
2007-06-22 04:04:48 +02:00
|
|
|
<< (else_flag? "(else)" : "(if)")
|
|
|
|
|
<< " value=" << test->value() << ": Generate scope="
|
|
|
|
|
<< use_name << endl;
|
|
|
|
|
|
2021-08-03 22:29:46 +02:00
|
|
|
if (directly_nested) {
|
2008-11-28 04:45:22 +01:00
|
|
|
if (debug_scopes)
|
|
|
|
|
cerr << get_fileline() << ": debug: Generate condition "
|
|
|
|
|
<< (else_flag? "(else)" : "(if)")
|
|
|
|
|
<< " detected direct nesting." << endl;
|
|
|
|
|
elaborate_subscope_direct_(des, container);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// If this is not directly nested, then generate a scope
|
|
|
|
|
// for myself. That is what I will pass to the subscope.
|
|
|
|
|
NetScope*scope = new NetScope(container, use_name, NetScope::GENBLOCK);
|
2008-04-30 03:58:25 +02:00
|
|
|
scope->set_line(get_file(), get_lineno());
|
2019-09-27 00:35:57 +02:00
|
|
|
scope->add_imports(&explicit_imports);
|
2007-06-22 04:04:48 +02:00
|
|
|
|
|
|
|
|
elaborate_subscope_(des, scope);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2008-02-10 07:19:42 +01:00
|
|
|
bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
|
|
|
|
{
|
2011-03-27 12:08:33 +02:00
|
|
|
NetExpr*case_value_ex = elab_and_eval(des, container, loop_test, -1, true);
|
2008-02-10 07:19:42 +01:00
|
|
|
NetEConst*case_value_co = dynamic_cast<NetEConst*>(case_value_ex);
|
2008-08-07 00:46:43 +02:00
|
|
|
if (case_value_co == 0) {
|
|
|
|
|
cerr << get_fileline() << ": error: Cannot evaluate genvar case"
|
|
|
|
|
<< " expression: " << *loop_test << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2008-02-10 07:19:42 +01:00
|
|
|
|
|
|
|
|
if (debug_scopes)
|
|
|
|
|
cerr << get_fileline() << ": debug: Generate case "
|
|
|
|
|
<< "switch value=" << case_value_co->value() << endl;
|
|
|
|
|
|
|
|
|
|
PGenerate*default_item = 0;
|
|
|
|
|
|
|
|
|
|
typedef list<PGenerate*>::const_iterator generator_it_t;
|
2008-06-18 06:45:37 +02:00
|
|
|
generator_it_t cur = generate_schemes.begin();
|
|
|
|
|
while (cur != generate_schemes.end()) {
|
2008-02-10 07:19:42 +01:00
|
|
|
PGenerate*item = *cur;
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*item, item->scheme_type == PGenerate::GS_CASE_ITEM);
|
2008-02-10 07:19:42 +01:00
|
|
|
|
|
|
|
|
// Detect that the item is a default.
|
2008-11-28 04:45:22 +01:00
|
|
|
if (item->item_test.size() == 0) {
|
2008-02-10 07:19:42 +01:00
|
|
|
default_item = item;
|
2010-10-23 23:57:59 +02:00
|
|
|
++ cur;
|
2008-02-10 07:19:42 +01:00
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-28 04:45:22 +01:00
|
|
|
bool match_flag = false;
|
|
|
|
|
for (unsigned idx = 0 ; idx < item->item_test.size() && !match_flag ; idx +=1 ) {
|
2011-03-27 12:08:33 +02:00
|
|
|
NetExpr*item_value_ex = elab_and_eval(des, container,
|
|
|
|
|
item->item_test[idx],
|
|
|
|
|
-1, true);
|
2008-11-28 04:45:22 +01:00
|
|
|
NetEConst*item_value_co = dynamic_cast<NetEConst*>(item_value_ex);
|
2009-03-03 05:32:13 +01:00
|
|
|
if (item_value_co == 0) {
|
|
|
|
|
cerr << get_fileline() << ": error: Cannot evaluate "
|
|
|
|
|
<< " genvar case item expression: "
|
|
|
|
|
<< *item->item_test[idx] << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2008-02-10 07:19:42 +01:00
|
|
|
|
2008-11-28 05:14:27 +01:00
|
|
|
if (debug_scopes)
|
|
|
|
|
cerr << get_fileline() << ": debug: Generate case "
|
|
|
|
|
<< "item value=" << item_value_co->value() << endl;
|
|
|
|
|
|
2008-11-28 04:45:22 +01:00
|
|
|
if (case_value_co->value() == item_value_co->value())
|
|
|
|
|
match_flag = true;
|
2008-02-10 07:19:42 +01:00
|
|
|
delete item_value_co;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-28 04:45:22 +01:00
|
|
|
// If we stumble on the item that matches, then break out now.
|
|
|
|
|
if (match_flag)
|
|
|
|
|
break;
|
|
|
|
|
|
2010-10-23 23:57:59 +02:00
|
|
|
++ cur;
|
2008-02-10 07:19:42 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
delete case_value_co;
|
|
|
|
|
|
2008-06-18 06:45:37 +02:00
|
|
|
PGenerate*item = (cur == generate_schemes.end())? default_item : *cur;
|
2008-02-10 07:19:42 +01:00
|
|
|
if (item == 0) {
|
|
|
|
|
cerr << get_fileline() << ": debug: "
|
|
|
|
|
<< "No generate items found" << endl;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (debug_scopes)
|
|
|
|
|
cerr << get_fileline() << ": debug: "
|
|
|
|
|
<< "Generate case matches item at "
|
|
|
|
|
<< item->get_fileline() << endl;
|
|
|
|
|
|
2008-09-04 18:41:51 +02:00
|
|
|
// The name of the scope to generate, whatever that item is.
|
2008-09-04 02:59:39 +02:00
|
|
|
hname_t use_name (item->scope_name);
|
|
|
|
|
|
2021-08-03 22:29:46 +02:00
|
|
|
if (item->directly_nested) {
|
2008-11-28 04:45:22 +01:00
|
|
|
if (debug_scopes)
|
|
|
|
|
cerr << get_fileline() << ": debug: Generate case item " << scope_name
|
|
|
|
|
<< " detected direct nesting." << endl;
|
|
|
|
|
item->elaborate_subscope_direct_(des, container);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2012-05-01 01:00:25 +02:00
|
|
|
if (debug_scopes) {
|
|
|
|
|
cerr << get_fileline() << ": PGenerate::generate_scope_case_: "
|
|
|
|
|
<< "Generate subscope " << use_name
|
|
|
|
|
<< " and elaborate." << endl;
|
|
|
|
|
}
|
|
|
|
|
|
2008-02-10 07:19:42 +01:00
|
|
|
NetScope*scope = new NetScope(container, use_name,
|
|
|
|
|
NetScope::GENBLOCK);
|
2008-04-30 03:58:25 +02:00
|
|
|
scope->set_line(get_file(), get_lineno());
|
2019-09-27 00:35:57 +02:00
|
|
|
scope->add_imports(&explicit_imports);
|
2019-09-22 00:09:48 +02:00
|
|
|
|
2008-02-10 07:19:42 +01:00
|
|
|
item->elaborate_subscope_(des, scope);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-15 03:35:39 +01:00
|
|
|
bool PGenerate::generate_scope_nblock_(Design*des, NetScope*container)
|
|
|
|
|
{
|
|
|
|
|
hname_t use_name (scope_name);
|
|
|
|
|
if (debug_scopes)
|
|
|
|
|
cerr << get_fileline() << ": debug: Generate named block "
|
|
|
|
|
<< ": Generate scope=" << use_name << endl;
|
|
|
|
|
|
|
|
|
|
NetScope*scope = new NetScope(container, use_name,
|
|
|
|
|
NetScope::GENBLOCK);
|
|
|
|
|
scope->set_line(get_file(), get_lineno());
|
2019-09-27 00:35:57 +02:00
|
|
|
scope->add_imports(&explicit_imports);
|
2008-11-15 03:35:39 +01:00
|
|
|
|
|
|
|
|
elaborate_subscope_(des, scope);
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-28 04:45:22 +01:00
|
|
|
void PGenerate::elaborate_subscope_direct_(Design*des, NetScope*scope)
|
|
|
|
|
{
|
|
|
|
|
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 ) {
|
2012-05-01 01:00:25 +02:00
|
|
|
PGenerate*curp = *cur;
|
|
|
|
|
if (debug_scopes) {
|
|
|
|
|
cerr << get_fileline() << ": elaborate_subscope_direct_: "
|
|
|
|
|
<< "Elaborate direct subscope " << curp->scope_name
|
|
|
|
|
<< " within scope " << scope_name << endl;
|
|
|
|
|
}
|
|
|
|
|
curp -> generate_scope(des, scope);
|
2008-11-28 04:45:22 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2007-06-22 04:04:48 +02:00
|
|
|
void PGenerate::elaborate_subscope_(Design*des, NetScope*scope)
|
|
|
|
|
{
|
2019-12-22 18:29:23 +01:00
|
|
|
scope->add_typedefs(&typedefs);
|
|
|
|
|
|
2009-08-22 14:57:40 +02:00
|
|
|
// Add the genvars to this scope.
|
|
|
|
|
typedef map<perm_string,LineInfo*>::const_iterator genvar_it_t;
|
2010-10-23 23:57:59 +02:00
|
|
|
for (genvar_it_t cur = genvars.begin(); cur != genvars.end(); ++ cur ) {
|
2009-08-22 14:57:40 +02:00
|
|
|
scope->add_genvar((*cur).first, (*cur).second);
|
|
|
|
|
}
|
|
|
|
|
|
2022-02-09 22:30:12 +01:00
|
|
|
// Scan the parameters in this scope, and store the information
|
2012-06-11 20:48:37 +02:00
|
|
|
// needed to evaluate the parameter expressions. The expressions
|
|
|
|
|
// will be evaluated later, once all parameter overrides for this
|
|
|
|
|
// module have been done.
|
2022-02-09 22:30:12 +01:00
|
|
|
collect_scope_parameters(des, scope, parameters);
|
2012-06-11 20:48:37 +02:00
|
|
|
|
2024-02-12 19:38:00 +01:00
|
|
|
collect_scope_signals(scope, wires);
|
|
|
|
|
|
2012-08-16 01:07:50 +02:00
|
|
|
// Run through the defparams for this scope and save the result
|
|
|
|
|
// in a table for later final override.
|
|
|
|
|
|
|
|
|
|
typedef list<PGenerate::named_expr_t>::const_iterator defparms_iter_t;
|
|
|
|
|
for (defparms_iter_t cur = defparms.begin()
|
|
|
|
|
; cur != defparms.end() ; ++ cur ) {
|
|
|
|
|
scope->defparams.push_back(make_pair(cur->first, cur->second));
|
|
|
|
|
}
|
|
|
|
|
|
2007-10-28 13:07:25 +01:00
|
|
|
// Scan the generated scope for nested generate schemes,
|
|
|
|
|
// and *generate* new scopes, which is slightly different
|
|
|
|
|
// from simple elaboration.
|
|
|
|
|
|
|
|
|
|
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) -> generate_scope(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-17 22:25:59 +02:00
|
|
|
// Scan through all the task and function declarations in this
|
|
|
|
|
// scope.
|
2010-11-01 22:37:06 +01:00
|
|
|
elaborate_scope_tasks(des, scope, tasks);
|
|
|
|
|
elaborate_scope_funcs(des, scope, funcs);
|
2008-06-19 06:54:58 +02:00
|
|
|
|
2007-06-22 04:04:48 +02:00
|
|
|
// Scan the generated scope for gates that may create
|
|
|
|
|
// their own scopes.
|
|
|
|
|
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-06-22 04:04:48 +02:00
|
|
|
(*cur) ->elaborate_scope(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-18 06:45:37 +02: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-06-18 06:45:37 +02:00
|
|
|
(*cur) -> statement() -> elaborate_scope(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-17 22:25:59 +02:00
|
|
|
// Scan through all the named events in this scope.
|
|
|
|
|
elaborate_scope_events_(des, scope, events);
|
|
|
|
|
|
2008-11-28 04:45:22 +01:00
|
|
|
if (debug_scopes)
|
|
|
|
|
cerr << get_fileline() << ": debug: Generated scope " << scope_path(scope)
|
2012-05-01 01:00:25 +02:00
|
|
|
<< " for generate block " << scope_name << endl;
|
2008-11-28 04:45:22 +01:00
|
|
|
|
2007-06-22 04:04:48 +02:00
|
|
|
// Save the scope that we created, for future use.
|
|
|
|
|
scope_list_.push_back(scope);
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-25 07:03:28 +02:00
|
|
|
class delayed_elaborate_scope_mod_instances : public elaborator_work_item_t {
|
|
|
|
|
|
|
|
|
|
public:
|
2008-10-13 18:51:05 +02:00
|
|
|
delayed_elaborate_scope_mod_instances(Design*des__,
|
2008-06-25 07:03:28 +02:00
|
|
|
const PGModule*obj,
|
|
|
|
|
Module*mod,
|
|
|
|
|
NetScope*sc)
|
2008-10-13 18:51:05 +02:00
|
|
|
: elaborator_work_item_t(des__), obj_(obj), mod_(mod), sc_(sc)
|
2008-06-25 07:03:28 +02:00
|
|
|
{ }
|
2025-10-21 07:45:05 +02:00
|
|
|
~delayed_elaborate_scope_mod_instances() override { }
|
2008-06-25 07:03:28 +02:00
|
|
|
|
2025-10-21 07:45:05 +02:00
|
|
|
virtual void elaborate_runrun() override;
|
2008-06-25 07:03:28 +02:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
const PGModule*obj_;
|
|
|
|
|
Module*mod_;
|
|
|
|
|
NetScope*sc_;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
void delayed_elaborate_scope_mod_instances::elaborate_runrun()
|
|
|
|
|
{
|
2008-06-26 07:02:22 +02:00
|
|
|
if (debug_scopes)
|
|
|
|
|
cerr << obj_->get_fileline() << ": debug: "
|
|
|
|
|
<< "Resume scope elaboration of instances of "
|
|
|
|
|
<< mod_->mod_name() << "." << endl;
|
|
|
|
|
|
2008-06-25 07:03:28 +02:00
|
|
|
obj_->elaborate_scope_mod_instances_(des, mod_, sc_);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Here we handle the elaborate scope of a module instance. The caller
|
|
|
|
|
* has already figured out that this "gate" is a module, and has found
|
|
|
|
|
* the module definition. The "sc" argument is the scope that will
|
|
|
|
|
* contain this instance.
|
|
|
|
|
*/
|
2000-03-08 05:36:53 +01:00
|
|
|
void PGModule::elaborate_scope_mod_(Design*des, Module*mod, NetScope*sc) const
|
|
|
|
|
{
|
2001-04-29 01:18:08 +02:00
|
|
|
if (get_name() == "") {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": error: Instantiation of module "
|
2001-10-20 07:21:51 +02:00
|
|
|
<< mod->mod_name() << " requires an instance name." << endl;
|
2001-04-29 01:18:08 +02:00
|
|
|
des->errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2000-03-08 05:36:53 +01:00
|
|
|
// Missing module instance names have already been rejected.
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, get_name() != "");
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2000-12-16 02:45:47 +01:00
|
|
|
// check for recursive instantiation by scanning the current
|
|
|
|
|
// scope and its parents. Look for a module instantiation of
|
|
|
|
|
// the same module, but farther up in the scope.
|
2009-04-08 03:31:42 +02:00
|
|
|
unsigned rl_count = 0;
|
|
|
|
|
bool in_genblk = false;
|
2000-12-16 02:45:47 +01:00
|
|
|
for (NetScope*scn = sc ; scn ; scn = scn->parent()) {
|
2009-04-08 03:31:42 +02:00
|
|
|
// We need to know if we are inside a generate block to allow
|
|
|
|
|
// recursive instances.
|
|
|
|
|
if (scn->type() == NetScope::GENBLOCK) {
|
|
|
|
|
in_genblk = true;
|
2000-12-16 02:45:47 +01:00
|
|
|
continue;
|
2009-04-08 03:31:42 +02:00
|
|
|
}
|
2000-12-16 02:45:47 +01:00
|
|
|
|
2012-05-14 02:48:47 +02:00
|
|
|
if (scn->type() != NetScope::MODULE) continue;
|
2009-04-08 03:31:42 +02:00
|
|
|
|
|
|
|
|
if (strcmp(mod->mod_name(), scn->module_name()) != 0) continue;
|
|
|
|
|
|
|
|
|
|
// We allow nested scopes if they are inside a generate block,
|
|
|
|
|
// but only to a certain nesting depth.
|
|
|
|
|
if (in_genblk) {
|
|
|
|
|
rl_count += 1;
|
|
|
|
|
if (rl_count > recursive_mod_limit) {
|
|
|
|
|
cerr << get_fileline() << ": error: instance "
|
|
|
|
|
<< scope_path(sc) << "." << get_name()
|
|
|
|
|
<< " of module " << mod->mod_name()
|
|
|
|
|
<< " is nested too deep." << endl;
|
|
|
|
|
cerr << get_fileline() << ": : check for "
|
|
|
|
|
"proper recursion termination or increase the "
|
|
|
|
|
"limit (" << recursive_mod_limit
|
|
|
|
|
<< ") with the -pRECURSIVE_MOD_LIMIT flag."
|
|
|
|
|
<< endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2000-12-16 02:45:47 +01:00
|
|
|
continue;
|
2009-04-08 03:31:42 +02:00
|
|
|
}
|
2000-12-16 02:45:47 +01:00
|
|
|
|
2014-11-02 20:44:37 +01:00
|
|
|
cerr << get_fileline() << ": error: You can not instantiate "
|
2001-10-20 07:21:51 +02:00
|
|
|
<< "module " << mod->mod_name() << " within itself." << endl;
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": : The offending instance is "
|
2009-04-08 03:31:42 +02:00
|
|
|
<< get_name() << " within " << scope_path(scn) << "." << endl;
|
2000-12-16 02:45:47 +01:00
|
|
|
des->errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2021-11-06 01:02:38 +01:00
|
|
|
if (is_array()) {
|
2008-06-25 07:03:28 +02:00
|
|
|
// If there are expressions to evaluate in order to know
|
|
|
|
|
// the actual number of instances that will be
|
|
|
|
|
// instantiated, then we have to delay further scope
|
|
|
|
|
// elaboration until after defparams (above me) are
|
|
|
|
|
// run. Do that by appending a work item to the
|
|
|
|
|
// elaboration work list.
|
|
|
|
|
if (debug_scopes)
|
|
|
|
|
cerr << get_fileline() << ": debug: delay elaborate_scope"
|
|
|
|
|
<< " of array of " << get_name()
|
|
|
|
|
<< " in scope " << scope_path(sc) << "." << endl;
|
|
|
|
|
|
|
|
|
|
elaborator_work_item_t*tmp
|
|
|
|
|
= new delayed_elaborate_scope_mod_instances(des, this, mod, sc);
|
|
|
|
|
des->elaboration_work_list.push_back(tmp);
|
|
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
// If there are no expressions that need to be evaluated
|
|
|
|
|
// to elaborate the scope of this next instances, then
|
|
|
|
|
// get right to it.
|
|
|
|
|
elaborate_scope_mod_instances_(des, mod, sc);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This method is called to process a module instantiation after basic
|
|
|
|
|
* sanity testing is already complete.
|
|
|
|
|
*/
|
|
|
|
|
void PGModule::elaborate_scope_mod_instances_(Design*des, Module*mod, NetScope*sc) const
|
|
|
|
|
{
|
2004-09-05 19:44:41 +02:00
|
|
|
long instance_low = 0;
|
|
|
|
|
long instance_high = 0;
|
2021-11-06 01:02:38 +01:00
|
|
|
long instance_count = calculate_array_size_(des, sc, instance_high, instance_low);
|
|
|
|
|
if (instance_count == 0)
|
|
|
|
|
return;
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2004-09-05 19:44:41 +02:00
|
|
|
NetScope::scope_vec_t instances (instance_count);
|
|
|
|
|
|
2021-11-06 01:02:38 +01:00
|
|
|
struct attrib_list_t*attrib_list;
|
|
|
|
|
unsigned attrib_list_n = 0;
|
|
|
|
|
attrib_list = evaluate_attributes(attributes, attrib_list_n, des, sc);
|
2017-03-16 15:41:10 +01:00
|
|
|
|
2004-09-05 19:44:41 +02:00
|
|
|
// Run through the module instances, and make scopes out of
|
|
|
|
|
// them. Also do parameter overrides that are done on the
|
|
|
|
|
// instantiation line.
|
|
|
|
|
for (int idx = 0 ; idx < instance_count ; idx += 1) {
|
|
|
|
|
|
2007-06-02 05:42:12 +02:00
|
|
|
hname_t use_name (get_name());
|
2004-09-05 19:44:41 +02:00
|
|
|
|
2021-11-06 01:02:38 +01:00
|
|
|
if (is_array()) {
|
2021-01-02 23:04:06 +01:00
|
|
|
int instance_idx;
|
2004-09-05 19:44:41 +02:00
|
|
|
if (instance_low < instance_high)
|
|
|
|
|
instance_idx = instance_low + idx;
|
|
|
|
|
else
|
|
|
|
|
instance_idx = instance_low - idx;
|
|
|
|
|
|
2007-06-02 05:42:12 +02:00
|
|
|
use_name = hname_t(get_name(), instance_idx);
|
2004-09-05 19:44:41 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (debug_scopes) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": debug: Module instance " << use_name
|
2007-06-02 05:42:12 +02:00
|
|
|
<< " becomes child of " << scope_path(sc)
|
2004-09-05 19:44:41 +02:00
|
|
|
<< "." << endl;
|
|
|
|
|
}
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2012-05-10 04:35:11 +02:00
|
|
|
// Create the new scope as a MODULE with my name. Note
|
|
|
|
|
// that if this is a nested module, mark it thus so that
|
|
|
|
|
// scope searches will continue into the parent scope.
|
2017-10-21 16:04:25 +02:00
|
|
|
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE, 0,
|
2012-05-14 02:48:47 +02:00
|
|
|
bound_type_? true : false,
|
2014-12-20 00:10:14 +01:00
|
|
|
mod->program_block,
|
|
|
|
|
mod->is_interface);
|
2008-04-30 03:58:25 +02:00
|
|
|
my_scope->set_line(get_file(), mod->get_file(),
|
|
|
|
|
get_lineno(), mod->get_lineno());
|
2004-09-05 19:44:41 +02:00
|
|
|
my_scope->set_module_name(mod->mod_name());
|
2019-09-27 00:35:57 +02:00
|
|
|
my_scope->add_imports(&mod->explicit_imports);
|
2004-09-05 19:44:41 +02:00
|
|
|
|
2017-03-16 15:41:10 +01:00
|
|
|
for (unsigned adx = 0 ; adx < attrib_list_n ; adx += 1)
|
|
|
|
|
my_scope->attribute(attrib_list[adx].key, attrib_list[adx].val);
|
|
|
|
|
|
2004-09-05 19:44:41 +02:00
|
|
|
instances[idx] = my_scope;
|
|
|
|
|
|
2016-07-22 23:48:20 +02:00
|
|
|
set_scope_timescale(des, my_scope, mod);
|
2004-09-05 19:44:41 +02:00
|
|
|
|
|
|
|
|
// Look for module parameter replacements. The "replace" map
|
|
|
|
|
// maps parameter name to replacement expression that is
|
|
|
|
|
// passed. It is built up by the ordered overrides or named
|
|
|
|
|
// overrides.
|
|
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
Module::replace_t replace;
|
2004-09-05 19:44:41 +02:00
|
|
|
|
|
|
|
|
// Positional parameter overrides are matched to parameter
|
|
|
|
|
// names by using the param_names list of parameter
|
|
|
|
|
// names. This is an ordered list of names so the first name
|
|
|
|
|
// is parameter 0, the second parameter 1, and so on.
|
|
|
|
|
|
|
|
|
|
if (overrides_) {
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, parms_ == 0);
|
2004-09-05 19:44:41 +02:00
|
|
|
list<perm_string>::const_iterator cur
|
|
|
|
|
= mod->param_names.begin();
|
2010-10-26 04:36:44 +02:00
|
|
|
list<PExpr*>::const_iterator jdx = overrides_->begin();
|
2004-09-05 19:44:41 +02:00
|
|
|
for (;;) {
|
2010-10-26 04:36:44 +02:00
|
|
|
if (jdx == overrides_->end())
|
2004-09-05 19:44:41 +02:00
|
|
|
break;
|
2021-01-22 08:15:13 +01:00
|
|
|
// If we reached here we have more overrides than
|
|
|
|
|
// module parameters, so print a warning.
|
|
|
|
|
if (cur == mod->param_names.end()) {
|
|
|
|
|
cerr << get_fileline() << ": warning: "
|
|
|
|
|
"ignoring "
|
|
|
|
|
<< overrides_->size() -
|
|
|
|
|
mod->param_names.size()
|
|
|
|
|
<< " extra parameter override(s) for "
|
|
|
|
|
"instance '" << use_name
|
|
|
|
|
<< "' of module '" << mod->mod_name()
|
|
|
|
|
<< "' which expects "
|
|
|
|
|
<< mod->param_names.size()
|
|
|
|
|
<< " parameter(s)." << endl;
|
2004-09-05 19:44:41 +02:00
|
|
|
break;
|
2021-01-22 08:15:13 +01:00
|
|
|
}
|
2004-09-05 19:44:41 +02:00
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
// No expression means that the parameter is not
|
|
|
|
|
// replaced at all.
|
|
|
|
|
if (*jdx)
|
|
|
|
|
replace[*cur] = *jdx;
|
2004-09-05 19:44:41 +02:00
|
|
|
|
2010-10-26 04:36:44 +02:00
|
|
|
++ jdx;
|
|
|
|
|
++ cur;
|
2004-09-05 19:44:41 +02:00
|
|
|
}
|
|
|
|
|
}
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2004-09-05 19:44:41 +02:00
|
|
|
// Named parameter overrides carry a name with each override
|
|
|
|
|
// so the mapping into the replace list is much easier.
|
|
|
|
|
if (parms_) {
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, overrides_ == 0);
|
2015-08-07 22:11:07 +02:00
|
|
|
for (unsigned jdx = 0 ; jdx < nparms_ ; jdx += 1) {
|
|
|
|
|
// No expression means that the parameter is not
|
|
|
|
|
// replaced.
|
|
|
|
|
if (parms_[jdx].parm)
|
|
|
|
|
replace[parms_[jdx].name] = parms_[jdx].parm;
|
|
|
|
|
}
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2004-09-05 19:44:41 +02:00
|
|
|
}
|
|
|
|
|
|
2006-03-30 03:49:07 +02:00
|
|
|
// This call actually arranges for the description of the
|
|
|
|
|
// module type to process this instance and handle parameters
|
|
|
|
|
// and sub-scopes that might occur. Parameters are also
|
|
|
|
|
// created in that scope, as they exist. (I'll override them
|
|
|
|
|
// later.)
|
2010-12-05 22:28:17 +01:00
|
|
|
mod->elaborate_scope(des, my_scope, replace);
|
2006-03-30 03:49:07 +02:00
|
|
|
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
2017-03-16 15:41:10 +01:00
|
|
|
delete[]attrib_list;
|
2004-09-05 19:44:41 +02:00
|
|
|
|
|
|
|
|
/* Stash the instance array of scopes into the parent
|
|
|
|
|
scope. Later elaboration passes will use this vector to
|
2008-03-07 05:37:08 +01:00
|
|
|
further elaborate the array.
|
|
|
|
|
|
|
|
|
|
Note that the array is ordered from LSB to MSB. We will use
|
|
|
|
|
that fact in the main elaborate to connect things in the
|
|
|
|
|
correct order. */
|
2004-09-05 19:44:41 +02:00
|
|
|
sc->instance_arrays[get_name()] = instances;
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
2000-04-09 19:44:30 +02:00
|
|
|
/*
|
|
|
|
|
* The isn't really able to create new scopes, but it does create the
|
|
|
|
|
* event name in the current scope, so can be done during the
|
2001-12-03 05:47:14 +01:00
|
|
|
* elaborate_scope scan. Note that the name_ of the PEvent object has
|
|
|
|
|
* no hierarchy, but neither does the NetEvent, until it is stored in
|
|
|
|
|
* the NetScope object.
|
2000-04-09 19:44:30 +02:00
|
|
|
*/
|
2019-09-27 23:08:58 +02:00
|
|
|
void PEvent::elaborate_scope(Design*, NetScope*scope) const
|
2000-04-09 19:44:30 +02:00
|
|
|
{
|
|
|
|
|
NetEvent*ev = new NetEvent(name_);
|
2024-02-18 17:47:10 +01:00
|
|
|
ev->lexical_pos(lexical_pos_);
|
2000-04-09 19:44:30 +02:00
|
|
|
ev->set_line(*this);
|
|
|
|
|
scope->add_event(ev);
|
|
|
|
|
}
|
|
|
|
|
|
2000-03-08 05:36:53 +01:00
|
|
|
void PFunction::elaborate_scope(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
2022-02-27 17:56:30 +01:00
|
|
|
ivl_assert(*this, scope->type() == NetScope::FUNC);
|
2003-06-16 02:34:08 +02:00
|
|
|
|
2011-04-05 21:43:54 +02:00
|
|
|
// Save a reference to the pform representation of the function
|
|
|
|
|
// in case we need to perform early elaboration.
|
|
|
|
|
scope->set_func_pform(this);
|
|
|
|
|
|
|
|
|
|
// Assume the function is a constant function until we
|
|
|
|
|
// find otherwise.
|
|
|
|
|
scope->is_const_func(true);
|
|
|
|
|
|
2019-12-22 18:29:23 +01:00
|
|
|
scope->add_typedefs(&typedefs);
|
|
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
// Scan the parameters in the function, and store the information
|
2011-03-03 05:23:02 +01:00
|
|
|
// needed to evaluate the parameter expressions.
|
2008-09-17 22:25:59 +02:00
|
|
|
|
2020-12-25 03:12:06 +01:00
|
|
|
collect_scope_parameters(des, scope, parameters);
|
2008-09-17 22:25:59 +02:00
|
|
|
|
2024-02-12 19:38:00 +01:00
|
|
|
collect_scope_signals(scope, wires);
|
|
|
|
|
|
2008-09-17 22:25:59 +02:00
|
|
|
// Scan through all the named events in this scope.
|
|
|
|
|
elaborate_scope_events_(des, scope, events);
|
|
|
|
|
|
2003-06-16 02:34:08 +02:00
|
|
|
if (statement_)
|
|
|
|
|
statement_->elaborate_scope(des, scope);
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void PTask::elaborate_scope(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, scope->type() == NetScope::TASK);
|
2001-10-09 04:01:04 +02:00
|
|
|
|
2019-12-22 18:29:23 +01:00
|
|
|
scope->add_typedefs(&typedefs);
|
|
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
// Scan the parameters in the task, and store the information
|
2011-03-03 05:23:02 +01:00
|
|
|
// needed to evaluate the parameter expressions.
|
2008-09-17 22:25:59 +02:00
|
|
|
|
2020-12-25 03:12:06 +01:00
|
|
|
collect_scope_parameters(des, scope, parameters);
|
2008-09-17 22:25:59 +02:00
|
|
|
|
2024-02-12 19:38:00 +01:00
|
|
|
collect_scope_signals(scope, wires);
|
|
|
|
|
|
2008-09-17 22:25:59 +02:00
|
|
|
// Scan through all the named events in this scope.
|
|
|
|
|
elaborate_scope_events_(des, scope, events);
|
|
|
|
|
|
2001-10-09 04:01:04 +02:00
|
|
|
if (statement_)
|
|
|
|
|
statement_->elaborate_scope(des, scope);
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2000-03-11 04:25:51 +01:00
|
|
|
/*
|
|
|
|
|
* The base statement does not have sub-statements and does not
|
|
|
|
|
* introduce any scope, so this is a no-op.
|
|
|
|
|
*/
|
|
|
|
|
void Statement::elaborate_scope(Design*, NetScope*) const
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* When I get a behavioral block, check to see if it has a name. If it
|
|
|
|
|
* does, then create a new scope for the statements within it,
|
|
|
|
|
* otherwise use the current scope. Use the selected scope to scan the
|
|
|
|
|
* statements that I contain.
|
|
|
|
|
*/
|
|
|
|
|
void PBlock::elaborate_scope(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
NetScope*my_scope = scope;
|
|
|
|
|
|
2008-02-16 06:20:24 +01:00
|
|
|
if (pscope_name() != 0) {
|
|
|
|
|
hname_t use_name(pscope_name());
|
2008-11-19 05:10:10 +01:00
|
|
|
if (debug_scopes)
|
|
|
|
|
cerr << get_fileline() << ": debug: "
|
|
|
|
|
<< "Elaborate block scope " << use_name
|
|
|
|
|
<< " within " << scope_path(scope) << endl;
|
|
|
|
|
|
2012-05-20 02:34:13 +02:00
|
|
|
// The scope type is begin-end or fork-join. The
|
|
|
|
|
// sub-types of fork-join are not interesting to the scope.
|
|
|
|
|
my_scope = new NetScope(scope, use_name, bl_type_!=BL_SEQ
|
2000-03-11 04:25:51 +01:00
|
|
|
? NetScope::FORK_JOIN
|
|
|
|
|
: NetScope::BEGIN_END);
|
2008-04-30 03:58:25 +02:00
|
|
|
my_scope->set_line(get_file(), get_lineno());
|
2008-11-09 01:26:55 +01:00
|
|
|
my_scope->is_auto(scope->is_auto());
|
2019-09-27 00:35:57 +02:00
|
|
|
my_scope->add_imports(&explicit_imports);
|
2019-12-22 18:29:23 +01:00
|
|
|
my_scope->add_typedefs(&typedefs);
|
2008-09-17 22:25:59 +02:00
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
// Scan the parameters in the scope, and store the information
|
2011-03-03 05:23:02 +01:00
|
|
|
// needed to evaluate the parameter expressions.
|
2008-09-17 22:25:59 +02:00
|
|
|
|
2020-12-25 03:12:06 +01:00
|
|
|
collect_scope_parameters(des, my_scope, parameters);
|
2008-09-17 22:25:59 +02:00
|
|
|
|
2024-02-12 19:38:00 +01:00
|
|
|
collect_scope_signals(my_scope, wires);
|
|
|
|
|
|
2008-09-17 22:25:59 +02:00
|
|
|
// Scan through all the named events in this scope.
|
|
|
|
|
elaborate_scope_events_(des, my_scope, events);
|
2000-03-11 04:25:51 +01:00
|
|
|
}
|
|
|
|
|
|
2011-09-17 21:10:05 +02:00
|
|
|
for (unsigned idx = 0 ; idx < list_.size() ; idx += 1)
|
2000-03-11 04:25:51 +01:00
|
|
|
list_[idx] -> elaborate_scope(des, my_scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
2003-01-27 06:09:17 +01:00
|
|
|
* The case statement itself does not introduce scope, but contains
|
2000-03-11 04:25:51 +01:00
|
|
|
* other statements that may be named blocks. So scan the case items
|
|
|
|
|
* with the elaborate_scope method.
|
|
|
|
|
*/
|
|
|
|
|
void PCase::elaborate_scope(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, items_);
|
2022-02-17 10:48:43 +01:00
|
|
|
for (unsigned idx = 0 ; idx < (*items_).size() ; idx += 1) {
|
2023-04-13 22:00:34 +02:00
|
|
|
ivl_assert(*this, (*items_)[idx]);
|
2000-03-11 04:25:51 +01:00
|
|
|
|
2025-10-21 07:45:05 +02:00
|
|
|
if (const Statement*sp = (*items_)[idx]->stat)
|
2000-03-11 04:25:51 +01:00
|
|
|
sp -> elaborate_scope(des, scope);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The conditional statement (if-else) does not introduce scope, but
|
|
|
|
|
* the statements of the clauses may, so elaborate_scope the contained
|
|
|
|
|
* statements.
|
|
|
|
|
*/
|
|
|
|
|
void PCondit::elaborate_scope(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
if (if_)
|
|
|
|
|
if_ -> elaborate_scope(des, scope);
|
|
|
|
|
|
|
|
|
|
if (else_)
|
|
|
|
|
else_ -> elaborate_scope(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Statements that contain a further statement but do not
|
|
|
|
|
* intrinsically add a scope need to elaborate_scope the contained
|
|
|
|
|
* statement.
|
|
|
|
|
*/
|
|
|
|
|
void PDelayStatement::elaborate_scope(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_ -> elaborate_scope(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
2013-09-17 05:01:06 +02:00
|
|
|
/*
|
|
|
|
|
* Statements that contain a further statement but do not
|
|
|
|
|
* intrinsically add a scope need to elaborate_scope the contained
|
|
|
|
|
* statement.
|
|
|
|
|
*/
|
|
|
|
|
void PDoWhile::elaborate_scope(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_ -> elaborate_scope(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
2000-03-11 04:25:51 +01:00
|
|
|
/*
|
|
|
|
|
* Statements that contain a further statement but do not
|
|
|
|
|
* intrinsically add a scope need to elaborate_scope the contained
|
|
|
|
|
* statement.
|
|
|
|
|
*/
|
|
|
|
|
void PEventStatement::elaborate_scope(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_ -> elaborate_scope(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
2014-08-22 00:47:46 +02:00
|
|
|
/*
|
|
|
|
|
* The standard says that we create an implicit scope for foreach
|
|
|
|
|
* loops, but that is just to hold the index variables, and we'll
|
|
|
|
|
* handle them by creating unique names. So just jump into the
|
|
|
|
|
* contained statement for scope elaboration.
|
|
|
|
|
*/
|
|
|
|
|
void PForeach::elaborate_scope(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_ -> elaborate_scope(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
2000-03-11 04:25:51 +01:00
|
|
|
/*
|
|
|
|
|
* Statements that contain a further statement but do not
|
|
|
|
|
* intrinsically add a scope need to elaborate_scope the contained
|
|
|
|
|
* statement.
|
|
|
|
|
*/
|
|
|
|
|
void PForever::elaborate_scope(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_ -> elaborate_scope(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Statements that contain a further statement but do not
|
|
|
|
|
* intrinsically add a scope need to elaborate_scope the contained
|
|
|
|
|
* statement.
|
|
|
|
|
*/
|
|
|
|
|
void PForStatement::elaborate_scope(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_ -> elaborate_scope(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Statements that contain a further statement but do not
|
|
|
|
|
* intrinsically add a scope need to elaborate_scope the contained
|
|
|
|
|
* statement.
|
|
|
|
|
*/
|
|
|
|
|
void PRepeat::elaborate_scope(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_ -> elaborate_scope(des, scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Statements that contain a further statement but do not
|
|
|
|
|
* intrinsically add a scope need to elaborate_scope the contained
|
|
|
|
|
* statement.
|
|
|
|
|
*/
|
|
|
|
|
void PWhile::elaborate_scope(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
|
|
|
|
if (statement_)
|
|
|
|
|
statement_ -> elaborate_scope(des, scope);
|
|
|
|
|
}
|