2000-03-08 05:36:53 +01:00
|
|
|
/*
|
2012-03-03 03:34:43 +01:00
|
|
|
* Copyright (c) 2000-2012 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"
|
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"
|
2000-04-09 19:44:30 +02:00
|
|
|
# include "PEvent.h"
|
2000-03-08 05:36:53 +01:00
|
|
|
# include "PExpr.h"
|
|
|
|
|
# include "PGate.h"
|
2006-04-10 02:37:42 +02:00
|
|
|
# include "PGenerate.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"
|
2010-11-03 04:16:42 +01:00
|
|
|
# include "netenum.h"
|
2003-06-20 02:53:19 +02:00
|
|
|
# include "util.h"
|
2000-03-11 04:25:51 +01:00
|
|
|
# include <typeinfo>
|
2010-05-31 22:12:06 +02:00
|
|
|
# include <cassert>
|
2008-05-14 06:22:52 +02:00
|
|
|
# include "ivl_assert.h"
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2008-09-17 22:25:59 +02:00
|
|
|
typedef map<perm_string,LexicalScope::param_expr_t>::const_iterator mparm_it_t;
|
|
|
|
|
|
2011-03-03 05:23:02 +01:00
|
|
|
static void collect_parm_item_(Design*des, NetScope*scope, perm_string name,
|
2012-05-07 00:11:26 +02:00
|
|
|
const LexicalScope::param_expr_t&cur,
|
2012-06-04 21:43:33 +02:00
|
|
|
bool is_annotatable,
|
|
|
|
|
bool local_flag)
|
2008-02-05 22:37:33 +01:00
|
|
|
{
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-04 21:43:33 +02:00
|
|
|
|
2012-05-07 00:11:26 +02:00
|
|
|
scope->set_parameter(name, is_annotatable, cur.expr, cur.type, cur.msb,
|
2012-06-04 21:43:33 +02:00
|
|
|
cur.lsb, cur.signed_flag, local_flag, range_list, cur);
|
2008-02-05 22:37:33 +01:00
|
|
|
}
|
|
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
static void collect_scope_parameters_(Design*des, NetScope*scope,
|
2008-09-17 22:25:59 +02:00
|
|
|
const map<perm_string,LexicalScope::param_expr_t>¶meters)
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
|
2009-07-28 20:42:07 +02:00
|
|
|
// A parameter can not have the same name as a genvar.
|
|
|
|
|
if (scope->find_genvar((*cur).first)) {
|
|
|
|
|
cerr << cur->second.get_fileline()
|
|
|
|
|
<< ": error: parameter and genvar in '"
|
|
|
|
|
<< scope->fullname() << "' have the same name '"
|
|
|
|
|
<< (*cur).first << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-04 21:43:33 +02:00
|
|
|
collect_parm_item_(des, scope, (*cur).first, (*cur).second, false, false);
|
2008-09-17 22:25:59 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
static void collect_scope_localparams_(Design*des, NetScope*scope,
|
2008-09-17 22:25:59 +02:00
|
|
|
const map<perm_string,LexicalScope::param_expr_t>&localparams)
|
|
|
|
|
{
|
|
|
|
|
for (mparm_it_t cur = localparams.begin()
|
2010-10-23 23:57:59 +02:00
|
|
|
; cur != localparams.end() ; ++ cur ) {
|
2008-09-17 22:25:59 +02:00
|
|
|
|
2009-07-28 20:42:07 +02:00
|
|
|
// A localparam can not have the same name as a genvar.
|
|
|
|
|
if (scope->find_genvar((*cur).first)) {
|
|
|
|
|
cerr << cur->second.get_fileline()
|
|
|
|
|
<< ": error: localparam and genvar in '"
|
|
|
|
|
<< scope->fullname() << "' have the same name '"
|
|
|
|
|
<< (*cur).first << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-04 21:43:33 +02:00
|
|
|
collect_parm_item_(des, scope, (*cur).first, (*cur).second, false, true);
|
2012-05-07 00:11:26 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void collect_scope_specparams_(Design*des, NetScope*scope,
|
|
|
|
|
const map<perm_string,LexicalScope::param_expr_t>&specparams)
|
|
|
|
|
{
|
|
|
|
|
for (mparm_it_t cur = specparams.begin()
|
|
|
|
|
; cur != specparams.end() ; ++ cur ) {
|
|
|
|
|
|
|
|
|
|
// A specparam can not have the same name as a genvar.
|
|
|
|
|
if (scope->find_genvar((*cur).first)) {
|
|
|
|
|
cerr << cur->second.get_fileline()
|
|
|
|
|
<< ": error: specparam and genvar in '"
|
|
|
|
|
<< scope->fullname() << "' have the same name '"
|
|
|
|
|
<< (*cur).first << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-04 21:43:33 +02:00
|
|
|
collect_parm_item_(des, scope, (*cur).first, (*cur).second, true, false);
|
2008-09-17 22:25:59 +02: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;
|
2012-03-03 03:34:43 +01:00
|
|
|
assert(enum_type->range->size() == 1);
|
2012-04-10 23:29:28 +02:00
|
|
|
pform_range_t&range = enum_type->range->front();
|
|
|
|
|
NetExpr*msb_ex = elab_and_eval(des, scope, range.first, -1);
|
|
|
|
|
NetExpr*lsb_ex = elab_and_eval(des, scope, range.second, -1);
|
2010-11-04 04:11:19 +01:00
|
|
|
|
|
|
|
|
long msb = 0;
|
|
|
|
|
rc_flag = eval_as_long(msb, msb_ex);
|
|
|
|
|
assert(rc_flag);
|
|
|
|
|
long lsb = 0;
|
|
|
|
|
rc_flag = eval_as_long(lsb, lsb_ex);
|
|
|
|
|
assert(rc_flag);
|
|
|
|
|
|
2010-11-21 00:09:32 +01:00
|
|
|
netenum_t*use_enum = new netenum_t(enum_type->base_type, enum_type->signed_flag,
|
|
|
|
|
msb, lsb, enum_type->names->size());
|
2010-11-03 04:16:42 +01:00
|
|
|
|
2011-09-01 23:29:40 +02:00
|
|
|
use_enum->set_line(enum_type->li);
|
2010-11-03 04:16:42 +01:00
|
|
|
scope->add_enumeration_set(use_enum);
|
2010-10-31 19:26:09 +01:00
|
|
|
|
2010-11-13 03:47:06 +01:00
|
|
|
verinum cur_value (0);
|
|
|
|
|
verinum one_value (1);
|
2010-11-21 00:09:32 +01:00
|
|
|
size_t name_idx = 0;
|
2011-07-19 04:33:03 +02:00
|
|
|
// Find the minimum and maximum allowed enumeration values.
|
|
|
|
|
verinum min_value (0);
|
|
|
|
|
verinum max_value (0);
|
|
|
|
|
if (enum_type->signed_flag) {
|
|
|
|
|
min_value = v_not((pow(verinum(2),
|
2012-08-20 02:27:48 +02:00
|
|
|
verinum(use_enum->packed_width()-1)))) +
|
2011-07-19 04:33:03 +02:00
|
|
|
one_value;
|
2012-08-20 02:27:48 +02:00
|
|
|
max_value = pow(verinum(2), verinum(use_enum->packed_width()-1)) -
|
2011-07-19 04:33:03 +02:00
|
|
|
one_value;
|
|
|
|
|
} else {
|
2012-08-20 02:27:48 +02:00
|
|
|
max_value = pow(verinum(2), verinum(use_enum->packed_width())) -
|
2011-07-19 04:33:03 +02:00
|
|
|
one_value;
|
|
|
|
|
}
|
|
|
|
|
min_value.has_sign(true);
|
|
|
|
|
max_value.has_sign(enum_type->signed_flag);
|
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) {
|
2010-10-31 19:26:09 +01:00
|
|
|
|
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);
|
2010-11-13 03:47:06 +01:00
|
|
|
NetEConst*val_const = dynamic_cast<NetEConst*> (val);
|
|
|
|
|
if (val_const == 0) {
|
2011-09-01 23:29:40 +02:00
|
|
|
cerr << use_enum->get_fileline()
|
|
|
|
|
<< ": error: Enumeration expression is not "
|
2011-07-19 04:33:03 +02:00
|
|
|
"constant." << endl;
|
2010-11-13 03:47:06 +01:00
|
|
|
des->errors += 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
cur_value = val_const->value();
|
|
|
|
|
|
2011-07-19 04:33:03 +02:00
|
|
|
if (enum_type->base_type==IVL_VT_BOOL &&
|
|
|
|
|
! cur_value.is_defined()) {
|
2011-09-01 23:29:40 +02:00
|
|
|
cerr << use_enum->get_fileline()
|
|
|
|
|
<< ": error: Enumeration name " << cur->name
|
2011-07-19 04:33:03 +02:00
|
|
|
<< " cannot have an undefined value." << endl;
|
2010-11-13 03:47:06 +01:00
|
|
|
des->errors += 1;
|
2011-07-19 04:33:03 +02:00
|
|
|
continue;
|
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
|
2011-07-19 04:33:03 +02:00
|
|
|
<< " cannot have an undefined inferred value." << endl;
|
2010-11-13 03:47:06 +01:00
|
|
|
des->errors += 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
2011-07-19 04:33:03 +02:00
|
|
|
// The enumeration value must fit into the enumeration bits.
|
|
|
|
|
if ((cur_value > max_value) ||
|
|
|
|
|
(cur_value.has_sign() && (cur_value < min_value))) {
|
2011-09-01 23:29:40 +02:00
|
|
|
cerr << use_enum->get_fileline()
|
|
|
|
|
<< ": error: Enumeration name " << cur->name
|
2011-07-19 04:33:03 +02:00
|
|
|
<< " cannot have a value equal to " << cur_value
|
|
|
|
|
<< "." << endl;
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2010-11-07 18:58:00 +01:00
|
|
|
// The values are explicitly sized to the width of the
|
|
|
|
|
// base type of the enumeration.
|
2011-07-19 04:33:03 +02:00
|
|
|
verinum tmp_val (0);
|
2012-09-24 19:26:58 +02:00
|
|
|
if (cur_value.len() < (unsigned long)use_enum->packed_width()) {
|
2011-07-19 04:33:03 +02:00
|
|
|
// Pad the current value if it is narrower than the final
|
|
|
|
|
// width of the enum.
|
2012-08-20 02:27:48 +02:00
|
|
|
tmp_val = pad_to_width (cur_value, use_enum->packed_width());
|
2011-07-19 04:33:03 +02:00
|
|
|
tmp_val.has_len(true);
|
|
|
|
|
} else {
|
|
|
|
|
// Truncate an oversized value. We report out of bound
|
|
|
|
|
// values above. This may create duplicates.
|
2012-08-20 02:27:48 +02:00
|
|
|
tmp_val = verinum(cur_value, use_enum->packed_width());
|
2011-07-19 04:33:03 +02:00
|
|
|
}
|
2010-11-10 06:05:47 +01:00
|
|
|
tmp_val.has_sign(enum_type->signed_flag);
|
2010-11-07 18:58:00 +01:00
|
|
|
|
2010-11-21 00:09:32 +01:00
|
|
|
rc_flag = use_enum->insert_name(name_idx, cur->name, tmp_val);
|
2010-11-04 04:11:19 +01:00
|
|
|
rc_flag &= scope->add_enumeration_name(use_enum, cur->name);
|
|
|
|
|
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.
|
|
|
|
|
if (cur_value.is_defined())
|
|
|
|
|
cur_value = cur_value + one_value;
|
2010-10-31 19:26:09 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void elaborate_scope_enumerations(Design*des, NetScope*scope,
|
2010-11-04 04:11:19 +01:00
|
|
|
const list<enum_type_t*>&enum_types)
|
2010-10-31 19:26:09 +01:00
|
|
|
{
|
2010-11-04 04:11:19 +01:00
|
|
|
for (list<enum_type_t*>::const_iterator cur = enum_types.begin()
|
|
|
|
|
; cur != enum_types.end() ; ++ cur) {
|
2010-10-31 19:26:09 +01:00
|
|
|
elaborate_scope_enumeration(des, scope, *cur);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-17 22:25:59 +02:00
|
|
|
static void replace_scope_parameters_(NetScope*scope, const LineInfo&loc,
|
|
|
|
|
const Module::replace_t&replacements)
|
|
|
|
|
{
|
|
|
|
|
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
|
|
|
}
|
|
|
|
|
assert(val);
|
|
|
|
|
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;
|
|
|
|
|
}
|
2010-12-05 22:28:17 +01:00
|
|
|
bool flag = scope->replace_parameter((*cur).first, val,
|
|
|
|
|
scope->parent());
|
2008-09-17 22:25:59 +02:00
|
|
|
if (! flag) {
|
|
|
|
|
cerr << val->get_fileline() << ": warning: parameter "
|
|
|
|
|
<< (*cur).first << " not found in "
|
|
|
|
|
<< scope_path(scope) << "." << endl;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
hname_t use_name( (*cur).first );
|
2009-04-25 04:07:48 +02:00
|
|
|
// A task can not have the same name as another scope object.
|
|
|
|
|
const NetScope *child = scope->child(use_name);
|
|
|
|
|
if (child) {
|
|
|
|
|
cerr << cur->second->get_fileline() << ": error: task and ";
|
|
|
|
|
child->print_type(cerr);
|
|
|
|
|
cerr << " in '" << scope->fullname()
|
|
|
|
|
<< "' have the same name '" << use_name << "'." << endl;
|
2008-06-19 06:54:58 +02:00
|
|
|
des->errors += 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2009-04-25 04:07:48 +02:00
|
|
|
|
2009-07-28 20:42:07 +02:00
|
|
|
// A task can not have the same name as a genvar.
|
|
|
|
|
if (scope->find_genvar((*cur).first)) {
|
|
|
|
|
cerr << cur->second->get_fileline()
|
|
|
|
|
<< ": error: task and genvar in '"
|
|
|
|
|
<< scope->fullname() << "' have the same name '"
|
|
|
|
|
<< (*cur).first << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 04:07:48 +02:00
|
|
|
// A task 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, (*cur).first,
|
|
|
|
|
ex_msb, ex_lsb);
|
2009-04-25 04:07:48 +02:00
|
|
|
if (parm) {
|
|
|
|
|
cerr << cur->second->get_fileline()
|
|
|
|
|
<< ": error: task and parameter in '"
|
|
|
|
|
<< scope->fullname() << "' have the same name '"
|
|
|
|
|
<< (*cur).first << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-19 06:54:58 +02:00
|
|
|
NetScope*task_scope = new NetScope(scope, use_name,
|
|
|
|
|
NetScope::TASK);
|
2008-08-20 03:39:49 +02:00
|
|
|
task_scope->is_auto((*cur).second->is_auto());
|
2008-06-19 06:54:58 +02:00
|
|
|
task_scope->set_line((*cur).second);
|
|
|
|
|
|
|
|
|
|
if (debug_scopes)
|
|
|
|
|
cerr << cur->second->get_fileline() << ": debug: "
|
|
|
|
|
<< "Elaborate task scope " << scope_path(task_scope) << endl;
|
|
|
|
|
(*cur).second->elaborate_scope(des, task_scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
hname_t use_name( (*cur).first );
|
2009-04-25 04:07:48 +02:00
|
|
|
// A function can not have the same name as another scope object.
|
|
|
|
|
const NetScope *child = scope->child(use_name);
|
|
|
|
|
if (child) {
|
|
|
|
|
cerr << cur->second->get_fileline()
|
|
|
|
|
<< ": error: function and ";
|
|
|
|
|
child->print_type(cerr);
|
|
|
|
|
cerr << " in '" << scope->fullname()
|
|
|
|
|
<< "' have the same name '" << use_name << "'." << endl;
|
2008-06-19 06:54:58 +02:00
|
|
|
des->errors += 1;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2009-04-25 04:07:48 +02:00
|
|
|
|
2009-07-28 20:42:07 +02:00
|
|
|
// A function can not have the same name as a genvar.
|
|
|
|
|
if (scope->find_genvar((*cur).first)) {
|
|
|
|
|
cerr << cur->second->get_fileline()
|
|
|
|
|
<< ": error: function and genvar in '"
|
|
|
|
|
<< scope->fullname() << "' have the same name '"
|
|
|
|
|
<< (*cur).first << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 04:07:48 +02:00
|
|
|
// A function 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, (*cur).first,
|
|
|
|
|
ex_msb, ex_lsb);
|
2009-04-25 04:07:48 +02:00
|
|
|
if (parm) {
|
|
|
|
|
cerr << cur->second->get_fileline()
|
|
|
|
|
<< ": error: function and parameter in '"
|
|
|
|
|
<< scope->fullname() << "' have the same name '"
|
|
|
|
|
<< (*cur).first << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-19 06:54:58 +02:00
|
|
|
NetScope*func_scope = new NetScope(scope, use_name,
|
|
|
|
|
NetScope::FUNC);
|
2008-08-20 03:39:49 +02:00
|
|
|
func_scope->is_auto((*cur).second->is_auto());
|
2008-06-19 06:54:58 +02:00
|
|
|
func_scope->set_line((*cur).second);
|
|
|
|
|
|
|
|
|
|
if (debug_scopes)
|
|
|
|
|
cerr << cur->second->get_fileline() << ": debug: "
|
|
|
|
|
<< "Elaborate function scope " << scope_path(func_scope) << endl;
|
|
|
|
|
(*cur).second->elaborate_scope(des, func_scope);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
{ }
|
|
|
|
|
|
|
|
|
|
void elaborate_runrun()
|
|
|
|
|
{
|
|
|
|
|
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_;
|
|
|
|
|
};
|
|
|
|
|
|
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) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": debug: Elaborate scope "
|
2007-06-02 05:42:12 +02:00
|
|
|
<< scope_path(scope) << "." << endl;
|
2004-09-05 19:44:41 +02:00
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
collect_scope_parameters_(des, scope, parameters);
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
collect_scope_localparams_(des, scope, localparams);
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2012-05-07 00:11:26 +02:00
|
|
|
collect_scope_specparams_(des, scope, specparams);
|
|
|
|
|
|
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
|
|
|
|
2008-09-17 22:25:59 +02:00
|
|
|
replace_scope_parameters_(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);
|
|
|
|
|
|
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
|
|
|
|
|
// we cannot do that until defparams are run, so push it off
|
|
|
|
|
// into an elaborate work item.
|
|
|
|
|
if (debug_scopes)
|
|
|
|
|
cerr << get_fileline() << ": debug: "
|
|
|
|
|
<< "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;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* This is the elaborate scope method for a generate loop.
|
|
|
|
|
*/
|
|
|
|
|
bool PGenerate::generate_scope_loop_(Design*des, NetScope*container)
|
|
|
|
|
{
|
2008-05-06 04:46:30 +02:00
|
|
|
// Check that the loop_index variable was declared in a
|
|
|
|
|
// genvar statement.
|
2010-05-13 03:53:56 +02:00
|
|
|
NetScope*cscope = container;
|
|
|
|
|
while (cscope && !cscope->find_genvar(loop_index))
|
|
|
|
|
cscope = cscope->parent();
|
|
|
|
|
if (!cscope) {
|
2009-07-28 20:42:07 +02:00
|
|
|
cerr << get_fileline() << ": error: genvar is missing for "
|
|
|
|
|
"generate \"loop\" variable '" << loop_index << "'."
|
|
|
|
|
<< endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2008-05-06 04:46:30 +02:00
|
|
|
|
2006-04-10 02:37:42 +02:00
|
|
|
// We're going to need a genvar...
|
|
|
|
|
int genvar;
|
|
|
|
|
|
|
|
|
|
// 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);
|
2006-04-10 02:37:42 +02:00
|
|
|
NetEConst*init = dynamic_cast<NetEConst*> (init_ex);
|
|
|
|
|
if (init == 0) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
2006-04-10 02:37:42 +02:00
|
|
|
<< " init expression: " << *loop_init << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 04:07:48 +02:00
|
|
|
// Check the generate block name.
|
|
|
|
|
|
|
|
|
|
// A generate "loop" can not have the same name as another scope object.
|
|
|
|
|
const NetScope *child = container->child(hname_t(scope_name));
|
|
|
|
|
if (child) {
|
|
|
|
|
cerr << get_fileline() << ": error: generate \"loop\" and ";
|
|
|
|
|
child->print_type(cerr);
|
|
|
|
|
cerr << " in '" << container->fullname()
|
|
|
|
|
<< "' have the same name '" << scope_name << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2009-07-28 20:42:07 +02:00
|
|
|
|
|
|
|
|
// A generate "loop" can not have the same name as a genvar.
|
|
|
|
|
if (container->find_genvar(scope_name)) {
|
|
|
|
|
cerr << get_fileline() << ": error: generate \"loop\" and "
|
|
|
|
|
"genvar in '" << container->fullname()
|
|
|
|
|
<< "' have the same name '" << scope_name << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 04:07:48 +02:00
|
|
|
// A generate "loop" can not have the same name as a named event.
|
|
|
|
|
const NetEvent *event = container->find_event(scope_name);
|
|
|
|
|
if (event) {
|
|
|
|
|
cerr << get_fileline() << ": error: generate \"loop\" and "
|
|
|
|
|
"named event in '" << container->fullname()
|
|
|
|
|
<< "' have the same name '" << scope_name << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A generate "loop" can not have the same name as a parameter.
|
|
|
|
|
const NetExpr*tmsb;
|
|
|
|
|
const NetExpr*tlsb;
|
2010-12-05 22:28:17 +01:00
|
|
|
const NetExpr*texpr = container->get_parameter(des, scope_name,
|
|
|
|
|
tmsb, tlsb);
|
2009-04-25 04:07:48 +02:00
|
|
|
if (texpr != 0) {
|
|
|
|
|
cerr << get_fileline() << ": error: generate \"loop\" and "
|
|
|
|
|
"parameter in '" << container->fullname()
|
|
|
|
|
<< "' have the same name '" << scope_name << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-28 20:42:07 +02:00
|
|
|
// These have all been checked so we just need to skip the actual
|
|
|
|
|
// generation for these name conflicts. Not skipping these two will
|
|
|
|
|
// cause the compiler to have problems (assert, inf. loop, etc.).
|
2010-12-05 22:28:17 +01:00
|
|
|
if (container->get_parameter(des, loop_index, tmsb, tlsb)) return false;
|
2009-07-28 20:42:07 +02:00
|
|
|
if (container->find_event(loop_index)) return false;
|
2008-05-06 04:46:30 +02:00
|
|
|
|
2006-04-10 02:37:42 +02:00
|
|
|
genvar = init->value().as_long();
|
|
|
|
|
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;
|
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);
|
2006-04-12 07:05:03 +02:00
|
|
|
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;
|
|
|
|
|
}
|
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);
|
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: "
|
2006-04-10 02:37:42 +02:00
|
|
|
<< "Create generated scope " << use_name << endl;
|
|
|
|
|
|
|
|
|
|
NetScope*scope = new NetScope(container, use_name,
|
|
|
|
|
NetScope::GENBLOCK);
|
2008-04-30 03:58:25 +02:00
|
|
|
scope->set_line(get_file(), get_lineno());
|
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.
|
|
|
|
|
{
|
|
|
|
|
verinum genvar_verinum(genvar);
|
|
|
|
|
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: "
|
2007-03-05 06:59:10 +01:00
|
|
|
<< "Create implicit localparam "
|
|
|
|
|
<< 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) {
|
|
|
|
|
cerr << get_fileline() << ": error: Cannot evaluate genvar"
|
|
|
|
|
<< " step expression: " << *loop_step << endl;
|
|
|
|
|
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
|
|
|
|
2006-04-12 07:05:03 +02:00
|
|
|
genvar = step->value().as_long();
|
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;
|
2006-06-02 06:48:49 +02:00
|
|
|
test_ex = elab_and_eval(des, container, loop_test, -1);
|
2006-04-12 07:05:03 +02:00
|
|
|
test = dynamic_cast<NetEConst*>(test_ex);
|
|
|
|
|
assert(test);
|
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);
|
2007-06-22 04:04:48 +02:00
|
|
|
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);
|
2009-04-25 04:07:48 +02:00
|
|
|
// A generate "if" can not have the same name as another scope object.
|
|
|
|
|
const NetScope *child = container->child(use_name);
|
|
|
|
|
if (child) {
|
|
|
|
|
cerr << get_fileline() << ": error: generate \"if\" and ";
|
|
|
|
|
child->print_type(cerr);
|
|
|
|
|
cerr << " in '" << container->fullname()
|
|
|
|
|
<< "' have the same name '" << use_name << "'." << endl;
|
2007-11-17 21:17:56 +01:00
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2008-11-28 04:45:22 +01:00
|
|
|
|
2009-07-28 20:42:07 +02:00
|
|
|
// A generate "if" can not have the same name as a genvar.
|
|
|
|
|
if (container->find_genvar(scope_name)) {
|
|
|
|
|
cerr << get_fileline() << ": error: generate \"if\" and "
|
|
|
|
|
"genvar in '" << container->fullname()
|
|
|
|
|
<< "' have the same name '" << scope_name << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 04:07:48 +02:00
|
|
|
// A generate "if" can not have the same name as a named event.
|
|
|
|
|
const NetEvent *event = container->find_event(scope_name);
|
|
|
|
|
if (event) {
|
|
|
|
|
cerr << get_fileline() << ": error: generate \"if\" and "
|
|
|
|
|
"named event in '" << container->fullname()
|
|
|
|
|
<< "' have the same name '" << use_name << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A generate "if" 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 = container->get_parameter(des, scope_name,
|
|
|
|
|
ex_msb, ex_lsb);
|
2009-04-25 04:07:48 +02:00
|
|
|
if (parm) {
|
|
|
|
|
cerr << get_fileline() << ": error: generate \"if\" and "
|
|
|
|
|
"parameter in '" << container->fullname()
|
|
|
|
|
<< "' have the same name '" << use_name << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
|
|
|
2008-11-28 04:45:22 +01:00
|
|
|
probe_for_direct_nesting_();
|
|
|
|
|
if (direct_nested_) {
|
|
|
|
|
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());
|
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;
|
|
|
|
|
assert( item->scheme_type == PGenerate::GS_CASE_ITEM );
|
|
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
|
case_value_co = 0;
|
|
|
|
|
|
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);
|
2009-04-25 04:07:48 +02:00
|
|
|
// A generate "case" can not have the same name as another scope object.
|
|
|
|
|
const NetScope *child = container->child(use_name);
|
|
|
|
|
if (child) {
|
|
|
|
|
cerr << get_fileline() << ": error: generate \"case\" and ";
|
|
|
|
|
child->print_type(cerr);
|
|
|
|
|
cerr << " in '" << container->fullname()
|
|
|
|
|
<< "' have the same name '" << use_name << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-28 20:42:07 +02:00
|
|
|
// A generate "case" can not have the same name as a genvar.
|
|
|
|
|
if (container->find_genvar(item->scope_name)) {
|
|
|
|
|
cerr << get_fileline() << ": error: generate \"case\" and "
|
|
|
|
|
"genvar in '" << container->fullname()
|
|
|
|
|
<< "' have the same name '" << use_name << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 04:07:48 +02:00
|
|
|
// A generate "case" can not have the same name as a named event.
|
|
|
|
|
const NetEvent *event = container->find_event(item->scope_name);
|
|
|
|
|
if (event) {
|
|
|
|
|
cerr << get_fileline() << ": error: generate \"case\" and "
|
|
|
|
|
"named event in '" << container->fullname()
|
|
|
|
|
<< "' have the same name '" << use_name << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A generate "case" 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 = container->get_parameter(des, item->scope_name,
|
|
|
|
|
ex_msb, ex_lsb);
|
2009-04-25 04:07:48 +02:00
|
|
|
if (parm) {
|
|
|
|
|
cerr << get_fileline() << ": error: generate \"case\" and "
|
|
|
|
|
"parameter in '" << container->fullname()
|
|
|
|
|
<< "' have the same name '" << use_name << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
2008-09-04 02:59:39 +02:00
|
|
|
|
2008-11-28 04:45:22 +01:00
|
|
|
item->probe_for_direct_nesting_();
|
|
|
|
|
if (item->direct_nested_) {
|
|
|
|
|
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());
|
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);
|
2009-07-28 20:42:07 +02:00
|
|
|
// A generate "block" can not have the same name as another scope
|
|
|
|
|
// object.
|
2009-04-25 04:07:48 +02:00
|
|
|
const NetScope *child = container->child(use_name);
|
|
|
|
|
if (child) {
|
|
|
|
|
cerr << get_fileline() << ": error: generate \"block\" and ";
|
|
|
|
|
child->print_type(cerr);
|
|
|
|
|
cerr << " in '" << container->fullname()
|
|
|
|
|
<< "' have the same name '" << use_name << "'." << endl;
|
2008-11-15 03:35:39 +01:00
|
|
|
des->errors += 1;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2009-04-25 04:07:48 +02:00
|
|
|
|
2009-07-28 20:42:07 +02:00
|
|
|
// A generate "block" can not have the same name as a genvar.
|
|
|
|
|
if (container->find_genvar(scope_name)) {
|
|
|
|
|
cerr << get_fileline() << ": error: generate \"block\" and "
|
|
|
|
|
"genvar in '" << container->fullname()
|
|
|
|
|
<< "' have the same name '" << scope_name << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 04:07:48 +02:00
|
|
|
// A generate "block" can not have the same name as a named event.
|
|
|
|
|
const NetEvent *event = container->find_event(scope_name);
|
|
|
|
|
if (event) {
|
|
|
|
|
cerr << get_fileline() << ": error: generate \"block\" and "
|
|
|
|
|
"named event in '" << container->fullname()
|
|
|
|
|
<< "' have the same name '" << use_name << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// A generate "block" 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 = container->get_parameter(des, scope_name,
|
|
|
|
|
ex_msb, ex_lsb);
|
2009-04-25 04:07:48 +02:00
|
|
|
if (parm) {
|
|
|
|
|
cerr << get_fileline() << ": error: generate \"block\" and "
|
|
|
|
|
"parameter in '" << container->fullname()
|
|
|
|
|
<< "' have the same name '" << use_name << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2008-11-15 03:35:39 +01:00
|
|
|
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());
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2012-06-11 20:48:37 +02:00
|
|
|
// Scan the localparams in this scope, 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.
|
|
|
|
|
collect_scope_localparams_(des, scope, localparams);
|
|
|
|
|
|
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
|
|
|
{ }
|
|
|
|
|
~delayed_elaborate_scope_mod_instances() { }
|
|
|
|
|
|
|
|
|
|
virtual void elaborate_runrun();
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
assert(get_name() != "");
|
|
|
|
|
|
2009-04-25 04:07:48 +02:00
|
|
|
// A module instance can not have the same name as another scope object.
|
|
|
|
|
const NetScope *child = sc->child(hname_t(get_name()));
|
|
|
|
|
if (child) {
|
|
|
|
|
cerr << get_fileline() << ": error: module <" << mod->mod_name()
|
|
|
|
|
<< "> instance and ";
|
|
|
|
|
child->print_type(cerr);
|
|
|
|
|
cerr << " in '" << sc->fullname()
|
|
|
|
|
<< "' have the same name '" << get_name() << "'." << endl;
|
2000-03-08 05:36:53 +01:00
|
|
|
des->errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2009-07-28 20:42:07 +02:00
|
|
|
// A module instance can not have the same name as a genvar.
|
|
|
|
|
if (sc->find_genvar(get_name())) {
|
|
|
|
|
cerr << get_fileline() << ": error: module <" << mod->mod_name()
|
|
|
|
|
<< "> instance and genvar in '" << sc->fullname()
|
|
|
|
|
<< "' have the same name '" << get_name() << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 04:07:48 +02:00
|
|
|
// A module instance 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 = sc->get_parameter(des, get_name(), ex_msb, ex_lsb);
|
2009-04-25 04:07:48 +02:00
|
|
|
if (parm) {
|
|
|
|
|
cerr << get_fileline() << ": error: module <" << mod->mod_name()
|
|
|
|
|
<< "> instance and parameter in '" << sc->fullname()
|
|
|
|
|
<< "' have the same name '" << get_name() << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
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
|
|
|
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": error: You cannot 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;
|
|
|
|
|
}
|
|
|
|
|
|
2008-06-25 07:03:28 +02:00
|
|
|
if (msb_ || lsb_) {
|
|
|
|
|
// 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
|
|
|
|
|
{
|
2011-03-27 12:08:33 +02:00
|
|
|
NetExpr*mse = msb_ ? elab_and_eval(des, sc, msb_, -1, true) : 0;
|
|
|
|
|
NetExpr*lse = lsb_ ? elab_and_eval(des, sc, lsb_, -1, true) : 0;
|
2006-03-30 03:49:07 +02:00
|
|
|
NetEConst*msb = dynamic_cast<NetEConst*> (mse);
|
|
|
|
|
NetEConst*lsb = dynamic_cast<NetEConst*> (lse);
|
2004-09-05 19:44:41 +02:00
|
|
|
|
|
|
|
|
assert( (msb == 0) || (lsb != 0) );
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2004-09-05 19:44:41 +02:00
|
|
|
long instance_low = 0;
|
|
|
|
|
long instance_high = 0;
|
|
|
|
|
long instance_count = 1;
|
|
|
|
|
bool instance_array = false;
|
2000-03-08 05:36:53 +01:00
|
|
|
|
2004-09-05 19:44:41 +02:00
|
|
|
if (msb) {
|
|
|
|
|
instance_array = true;
|
2006-03-30 03:49:07 +02:00
|
|
|
instance_high = msb->value().as_long();
|
|
|
|
|
instance_low = lsb->value().as_long();
|
2004-09-05 19:44:41 +02:00
|
|
|
if (instance_high > instance_low)
|
|
|
|
|
instance_count = instance_high - instance_low + 1;
|
|
|
|
|
else
|
|
|
|
|
instance_count = instance_low - instance_high + 1;
|
2006-03-30 03:49:07 +02:00
|
|
|
|
|
|
|
|
delete mse;
|
|
|
|
|
delete lse;
|
2000-03-08 05:36:53 +01:00
|
|
|
}
|
|
|
|
|
|
2004-09-05 19:44:41 +02:00
|
|
|
NetScope::scope_vec_t instances (instance_count);
|
|
|
|
|
if (debug_scopes) {
|
2007-12-20 18:31:01 +01:00
|
|
|
cerr << get_fileline() << ": debug: Create " << instance_count
|
2004-09-05 19:44:41 +02:00
|
|
|
<< " instances of " << get_name()
|
|
|
|
|
<< "." << endl;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// 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
|
|
|
|
|
|
|
|
if (instance_array) {
|
|
|
|
|
int instance_idx = idx;
|
|
|
|
|
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.
|
2012-05-14 02:48:47 +02:00
|
|
|
NetScope*my_scope = new NetScope(sc, use_name, NetScope::MODULE,
|
|
|
|
|
bound_type_? true : false,
|
|
|
|
|
mod->program_block);
|
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());
|
|
|
|
|
|
|
|
|
|
instances[idx] = my_scope;
|
|
|
|
|
|
|
|
|
|
// Set time units and precision.
|
|
|
|
|
my_scope->time_unit(mod->time_unit);
|
|
|
|
|
my_scope->time_precision(mod->time_precision);
|
2009-04-14 03:06:17 +02:00
|
|
|
my_scope->time_from_timescale(mod->time_from_timescale);
|
2004-09-05 19:44:41 +02:00
|
|
|
des->set_precision(mod->time_precision);
|
|
|
|
|
|
|
|
|
|
// 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_) {
|
|
|
|
|
assert(parms_ == 0);
|
|
|
|
|
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;
|
|
|
|
|
if (cur == mod->param_names.end())
|
|
|
|
|
break;
|
|
|
|
|
|
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_) {
|
|
|
|
|
assert(overrides_ == 0);
|
2008-10-13 18:51:05 +02:00
|
|
|
for (unsigned jdx = 0 ; jdx < nparms_ ; jdx += 1)
|
|
|
|
|
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
|
|
|
}
|
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
|
|
|
*/
|
|
|
|
|
void PEvent::elaborate_scope(Design*des, NetScope*scope) const
|
|
|
|
|
{
|
2009-04-25 04:07:48 +02:00
|
|
|
// A named event can not have the same name as another scope object.
|
|
|
|
|
const NetScope *child = scope->child(hname_t(name_));
|
|
|
|
|
if (child) {
|
|
|
|
|
cerr << get_fileline() << ": error: named event 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 named event can not have the same name as a genvar.
|
|
|
|
|
if (scope->find_genvar(name_)) {
|
|
|
|
|
cerr << get_fileline() << ": error: named event and "
|
|
|
|
|
<< "genvar in '" << scope->fullname()
|
|
|
|
|
<< "' have the same name '" << name_ << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 04:07:48 +02:00
|
|
|
// A named event 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: named event and "
|
|
|
|
|
<< "parameter in '" << scope->fullname()
|
|
|
|
|
<< "' have the same name '" << name_ << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2000-04-09 19:44:30 +02:00
|
|
|
NetEvent*ev = new NetEvent(name_);
|
|
|
|
|
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
|
|
|
|
|
{
|
2003-06-16 02:34:08 +02:00
|
|
|
assert(scope->type() == NetScope::FUNC);
|
|
|
|
|
|
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);
|
|
|
|
|
|
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
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
collect_scope_parameters_(des, scope, parameters);
|
2008-09-17 22:25:59 +02:00
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
collect_scope_localparams_(des, scope, localparams);
|
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
|
|
|
|
|
{
|
2000-07-30 20:25:43 +02:00
|
|
|
assert(scope->type() == NetScope::TASK);
|
2001-10-09 04:01:04 +02:00
|
|
|
|
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
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
collect_scope_parameters_(des, scope, parameters);
|
2008-09-17 22:25:59 +02:00
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
collect_scope_localparams_(des, scope, localparams);
|
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());
|
2009-04-25 04:07:48 +02:00
|
|
|
// A named block can not have the same name as another scope
|
|
|
|
|
// object.
|
|
|
|
|
const NetScope *child = scope->child(use_name);
|
|
|
|
|
if (child) {
|
|
|
|
|
cerr << get_fileline() << ": error: named block and ";
|
|
|
|
|
child->print_type(cerr);
|
|
|
|
|
cerr << " in '" << scope->fullname()
|
|
|
|
|
<< "' have the same name '" << use_name << "'." << endl;
|
2007-11-17 21:17:56 +01:00
|
|
|
des->errors += 1;
|
|
|
|
|
return;
|
|
|
|
|
}
|
2009-04-25 04:07:48 +02:00
|
|
|
|
2009-07-28 20:42:07 +02:00
|
|
|
// A named block can not have the same name as a genvar.
|
|
|
|
|
if (scope->find_genvar(pscope_name())) {
|
|
|
|
|
cerr << get_fileline() << ": error: named block and "
|
|
|
|
|
"genvar in '" << scope->fullname()
|
|
|
|
|
<< "' have the same name '" << use_name << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
2009-04-25 04:07:48 +02:00
|
|
|
// A named block 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, pscope_name(),
|
|
|
|
|
ex_msb, ex_lsb);
|
2009-04-25 04:07:48 +02:00
|
|
|
if (parm) {
|
|
|
|
|
cerr << get_fileline() << ": error: named block and "
|
|
|
|
|
"parameter in '" << scope->fullname()
|
|
|
|
|
<< "' have the same name '" << use_name << "'." << endl;
|
|
|
|
|
des->errors += 1;
|
|
|
|
|
}
|
|
|
|
|
|
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());
|
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
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
collect_scope_parameters_(des, my_scope, parameters);
|
2008-09-17 22:25:59 +02:00
|
|
|
|
2010-12-05 22:28:17 +01:00
|
|
|
collect_scope_localparams_(des, my_scope, localparams);
|
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
|
|
|
|
|
{
|
|
|
|
|
assert(items_);
|
|
|
|
|
for (unsigned idx = 0 ; idx < (*items_).count() ; idx += 1) {
|
|
|
|
|
assert( (*items_)[idx] );
|
|
|
|
|
|
|
|
|
|
if (Statement*sp = (*items_)[idx]->stat)
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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);
|
|
|
|
|
}
|