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:
Martin Whitaker 2021-08-03 21:29:46 +01:00
parent 389e2a3a94
commit c34167b2c0
8 changed files with 54 additions and 70 deletions

View File

@ -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) {

View File

@ -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);

View File

@ -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;

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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,