Fix detection of directly nested generate constructs.
If a generate construct is enclosed in a begin-end pair, it can't be directly nested (1364-2005 section 12.4.2).
This commit is contained in:
parent
389e2a3a94
commit
c34167b2c0
48
PGenerate.cc
48
PGenerate.cc
|
|
@ -24,8 +24,8 @@
|
|||
PGenerate::PGenerate(LexicalScope*parent, unsigned id)
|
||||
: LexicalScope(parent), id_number(id)
|
||||
{
|
||||
direct_nested_ = false;
|
||||
scheme_type = GS_NONE;
|
||||
directly_nested = false;
|
||||
local_index = false;
|
||||
loop_init = 0;
|
||||
loop_test = 0;
|
||||
|
|
@ -41,52 +41,6 @@ void PGenerate::add_gate(PGate*gate)
|
|||
gates.push_back(gate);
|
||||
}
|
||||
|
||||
void PGenerate::probe_for_direct_nesting_(void)
|
||||
{
|
||||
direct_nested_ = false;
|
||||
|
||||
ivl_assert(*this, scheme_type==GS_CASE_ITEM || scheme_type==GS_CONDIT || scheme_type==GS_ELSE);
|
||||
|
||||
// If this scheme has received an explicit name, then it
|
||||
// cannot be direct nested.
|
||||
if (scope_name[0] != '$') return;
|
||||
|
||||
if (! tasks.empty()) return;
|
||||
if (! funcs.empty()) return;
|
||||
if (! gates.empty()) return;
|
||||
if (! parameters.empty()) return;
|
||||
if (! localparams.empty()) return;
|
||||
if (! events.empty()) return;
|
||||
if (! wires.empty()) return;
|
||||
if (! genvars.empty()) return;
|
||||
if (! behaviors.empty()) return;
|
||||
if (! analog_behaviors.empty()) return;
|
||||
if (! elab_tasks.empty()) return;
|
||||
|
||||
if (generate_schemes.empty()) return;
|
||||
|
||||
switch (generate_schemes.size()) {
|
||||
case 1: {
|
||||
PGenerate*child = generate_schemes.front();
|
||||
if (child->scheme_type == GS_CONDIT)
|
||||
direct_nested_ = true;
|
||||
if (child->scheme_type == GS_CASE)
|
||||
direct_nested_ = true;
|
||||
break;
|
||||
}
|
||||
|
||||
case 2: {
|
||||
PGenerate*child1 = generate_schemes.front();
|
||||
PGenerate*child2 = generate_schemes.back();
|
||||
if (child1->scheme_type==GS_CONDIT && child2->scheme_type==GS_ELSE)
|
||||
direct_nested_ = true;
|
||||
if (child2->scheme_type==GS_CONDIT && child1->scheme_type==GS_ELSE)
|
||||
direct_nested_ = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ostream& operator << (ostream&out, PGenerate::scheme_t type)
|
||||
{
|
||||
switch (type) {
|
||||
|
|
|
|||
11
PGenerate.h
11
PGenerate.h
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef IVL_PGenerate_H
|
||||
#define IVL_PGenerate_H
|
||||
/*
|
||||
* Copyright (c) 2006-2020 Stephen Williams (steve@icarus.com)
|
||||
* Copyright (c) 2006-2021 Stephen Williams (steve@icarus.com)
|
||||
*
|
||||
* This source code is free software; you can redistribute it
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -69,6 +69,8 @@ class PGenerate : public PNamedItem, public LexicalScope {
|
|||
GS_CASE, GS_CASE_ITEM, GS_NBLOCK};
|
||||
scheme_t scheme_type;
|
||||
|
||||
bool directly_nested;
|
||||
|
||||
// generate loops have an index variable and three
|
||||
// expressions: for (index = <init>; <test>; index=<step>)
|
||||
// the index is local if it was declared in the init expression,
|
||||
|
|
@ -118,13 +120,6 @@ class PGenerate : public PNamedItem, public LexicalScope {
|
|||
bool generate_scope_case_(Design*des, NetScope*container);
|
||||
bool generate_scope_nblock_(Design*des, NetScope*container);
|
||||
|
||||
// Call probe during elaborate_scope to calculate the
|
||||
// direct_nested_ flag. It is OK to store the direct_nested_
|
||||
// information here because "direct nested" is a property of
|
||||
// the lexical generate code.
|
||||
void probe_for_direct_nesting_(void);
|
||||
bool direct_nested_;
|
||||
|
||||
// Elaborate_scope within a generated scope.
|
||||
void elaborate_subscope_(Design*des, NetScope*scope);
|
||||
void elaborate_subscope_direct_(Design*des, NetScope*scope);
|
||||
|
|
|
|||
|
|
@ -1093,8 +1093,7 @@ bool PGenerate::generate_scope_condit_(Design*des, NetScope*container, bool else
|
|||
<< " value=" << test->value() << ": Generate scope="
|
||||
<< use_name << endl;
|
||||
|
||||
probe_for_direct_nesting_();
|
||||
if (direct_nested_) {
|
||||
if (directly_nested) {
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate condition "
|
||||
<< (else_flag? "(else)" : "(if)")
|
||||
|
|
@ -1192,8 +1191,7 @@ bool PGenerate::generate_scope_case_(Design*des, NetScope*container)
|
|||
// The name of the scope to generate, whatever that item is.
|
||||
hname_t use_name (item->scope_name);
|
||||
|
||||
item->probe_for_direct_nesting_();
|
||||
if (item->direct_nested_) {
|
||||
if (item->directly_nested) {
|
||||
if (debug_scopes)
|
||||
cerr << get_fileline() << ": debug: Generate case item " << scope_name
|
||||
<< " detected direct nesting." << endl;
|
||||
|
|
|
|||
|
|
@ -430,7 +430,7 @@ bool PGModule::elaborate_sig_udp_(Design*des, NetScope*scope, PUdp*udp) const
|
|||
|
||||
bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
|
||||
{
|
||||
if (direct_nested_)
|
||||
if (directly_nested)
|
||||
return elaborate_sig_direct_(des, container);
|
||||
|
||||
bool flag = true;
|
||||
|
|
@ -449,7 +449,7 @@ bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
|
|||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; ++ cur ) {
|
||||
PGenerate*item = *cur;
|
||||
if (item->direct_nested_ || !item->scope_list_.empty()) {
|
||||
if (item->directly_nested || !item->scope_list_.empty()) {
|
||||
flag &= item->elaborate_sig(des, container);
|
||||
}
|
||||
}
|
||||
|
|
@ -497,12 +497,12 @@ bool PGenerate::elaborate_sig_direct_(Design*des, NetScope*container) const
|
|||
for (generate_it_t icur = item->generate_schemes.begin()
|
||||
; icur != item->generate_schemes.end() ; ++ icur ) {
|
||||
PGenerate*case_item = *icur;
|
||||
if (case_item->direct_nested_ || !case_item->scope_list_.empty()) {
|
||||
if (case_item->directly_nested || !case_item->scope_list_.empty()) {
|
||||
flag &= case_item->elaborate_sig(des, container);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (item->direct_nested_ || !item->scope_list_.empty()) {
|
||||
if (item->directly_nested || !item->scope_list_.empty()) {
|
||||
// Found the item, and it is direct nested.
|
||||
flag &= item->elaborate_sig(des, container);
|
||||
}
|
||||
|
|
|
|||
10
elaborate.cc
10
elaborate.cc
|
|
@ -6400,7 +6400,7 @@ void netclass_t::elaborate(Design*des, PClass*pclass)
|
|||
|
||||
bool PGenerate::elaborate(Design*des, NetScope*container) const
|
||||
{
|
||||
if (direct_nested_)
|
||||
if (directly_nested)
|
||||
return elaborate_direct_(des, container);
|
||||
|
||||
bool flag = true;
|
||||
|
|
@ -6425,7 +6425,7 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const
|
|||
for (generate_it_t cur = generate_schemes.begin()
|
||||
; cur != generate_schemes.end() ; ++ cur ) {
|
||||
PGenerate*item = *cur;
|
||||
if (item->direct_nested_ || !item->scope_list_.empty()) {
|
||||
if (item->directly_nested || !item->scope_list_.empty()) {
|
||||
flag &= item->elaborate(des, container);
|
||||
}
|
||||
}
|
||||
|
|
@ -6487,7 +6487,7 @@ bool PGenerate::elaborate_direct_(Design*des, NetScope*container) const
|
|||
cerr << get_fileline() << ": PGenerate::elaborate_direct_: "
|
||||
<< "item->scope_name=" << item->scope_name
|
||||
<< ", item->scheme_type=" << item->scheme_type
|
||||
<< ", item->direct_nested_=" << item->direct_nested_
|
||||
<< ", item->directly_nested=" << item->directly_nested
|
||||
<< ", item->scope_list_.size()=" << item->scope_list_.size()
|
||||
<< "." << endl;
|
||||
}
|
||||
|
|
@ -6500,12 +6500,12 @@ bool PGenerate::elaborate_direct_(Design*des, NetScope*container) const
|
|||
for (generate_it_t icur = item->generate_schemes.begin()
|
||||
; icur != item->generate_schemes.end() ; ++ icur ) {
|
||||
PGenerate*case_item = *icur;
|
||||
if (case_item->direct_nested_ || !case_item->scope_list_.empty()) {
|
||||
if (case_item->directly_nested || !case_item->scope_list_.empty()) {
|
||||
flag &= case_item->elaborate(des, container);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (item->direct_nested_ || !item->scope_list_.empty()) {
|
||||
if (item->directly_nested || !item->scope_list_.empty()) {
|
||||
// Found the item, and it is direct nested.
|
||||
flag &= item->elaborate(des, container);
|
||||
}
|
||||
|
|
|
|||
6
parse.y
6
parse.y
|
|
@ -5566,7 +5566,7 @@ generate_item_list
|
|||
;
|
||||
|
||||
generate_item_list_opt
|
||||
: generate_item_list
|
||||
: { pform_generate_single_item = false; } generate_item_list
|
||||
|
|
||||
;
|
||||
|
||||
|
|
@ -5577,7 +5577,9 @@ generate_item_list_opt
|
|||
only need to take note here of the scope name, if any. */
|
||||
|
||||
generate_block
|
||||
: module_item
|
||||
: { pform_generate_single_item = true; }
|
||||
module_item
|
||||
{ pform_generate_single_item = false; }
|
||||
| K_begin generate_item_list_opt K_end
|
||||
| K_begin ':' IDENTIFIER generate_item_list_opt K_end endlabel_opt
|
||||
{ pform_generate_block_name($3);
|
||||
|
|
|
|||
28
pform.cc
28
pform.cc
|
|
@ -349,6 +349,10 @@ static unsigned scope_generate_counter = 1;
|
|||
always within a module. */
|
||||
static PGenerate*pform_cur_generate = 0;
|
||||
|
||||
/* This indicates whether a new generate construct can be directly
|
||||
nested in the current generate construct. */
|
||||
bool pform_generate_single_item = false;
|
||||
|
||||
/* Blocks within the same conditional generate construct may have
|
||||
the same name. Here we collect the set of names used in each
|
||||
construct, so they can be added to the local scope without
|
||||
|
|
@ -1369,6 +1373,8 @@ void pform_startmodule(const struct vlltype&loc, const char*name,
|
|||
allow_timeunit_decl = true;
|
||||
allow_timeprec_decl = true;
|
||||
|
||||
pform_generate_single_item = false;
|
||||
|
||||
add_local_symbol(lexical_scope, lex_name, cur_module);
|
||||
|
||||
lexical_scope = cur_module;
|
||||
|
|
@ -1511,6 +1517,22 @@ void pform_genvars(const struct vlltype&li, list<perm_string>*names)
|
|||
delete names;
|
||||
}
|
||||
|
||||
static void detect_directly_nested_generate()
|
||||
{
|
||||
if (pform_cur_generate && pform_generate_single_item)
|
||||
switch (pform_cur_generate->scheme_type) {
|
||||
case PGenerate::GS_CASE_ITEM:
|
||||
// fallthrough
|
||||
case PGenerate::GS_CONDIT:
|
||||
// fallthrough
|
||||
case PGenerate::GS_ELSE:
|
||||
pform_cur_generate->directly_nested = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void pform_start_generate_for(const struct vlltype&li,
|
||||
bool local_index,
|
||||
char*ident1, PExpr*init,
|
||||
|
|
@ -1538,6 +1560,8 @@ void pform_start_generate_for(const struct vlltype&li,
|
|||
|
||||
void pform_start_generate_if(const struct vlltype&li, PExpr*test)
|
||||
{
|
||||
detect_directly_nested_generate();
|
||||
|
||||
PGenerate*gen = new PGenerate(lexical_scope, scope_generate_counter++);
|
||||
lexical_scope = gen;
|
||||
|
||||
|
|
@ -1582,6 +1606,8 @@ void pform_start_generate_else(const struct vlltype&li)
|
|||
*/
|
||||
void pform_start_generate_case(const struct vlltype&li, PExpr*expr)
|
||||
{
|
||||
detect_directly_nested_generate();
|
||||
|
||||
PGenerate*gen = new PGenerate(lexical_scope, scope_generate_counter++);
|
||||
lexical_scope = gen;
|
||||
|
||||
|
|
@ -1640,6 +1666,8 @@ void pform_generate_case_item(const struct vlltype&li, list<PExpr*>*expr_list)
|
|||
|
||||
FILE_NAME(gen, li);
|
||||
|
||||
gen->directly_nested = pform_cur_generate->directly_nested;
|
||||
|
||||
pform_cur_generate = gen;
|
||||
|
||||
pform_cur_generate->scheme_type = PGenerate::GS_CASE_ITEM;
|
||||
|
|
|
|||
7
pform.h
7
pform.h
|
|
@ -294,6 +294,13 @@ extern verinum* pform_verinum_with_size(verinum*s, verinum*val,
|
|||
*/
|
||||
extern void pform_genvars(const struct vlltype&li, list<perm_string>*names);
|
||||
|
||||
/*
|
||||
* This flag is set by the parser to indicate the current generate block
|
||||
* was not enclosed in a begin-end pair. This is a pre-requisite for
|
||||
* directly nesting generate constructs.
|
||||
*/
|
||||
extern bool pform_generate_single_item;
|
||||
|
||||
extern void pform_start_generate_for(const struct vlltype&li,
|
||||
bool local_index,
|
||||
char*ident1,
|
||||
|
|
|
|||
Loading…
Reference in New Issue