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)
|
PGenerate::PGenerate(LexicalScope*parent, unsigned id)
|
||||||
: LexicalScope(parent), id_number(id)
|
: LexicalScope(parent), id_number(id)
|
||||||
{
|
{
|
||||||
direct_nested_ = false;
|
|
||||||
scheme_type = GS_NONE;
|
scheme_type = GS_NONE;
|
||||||
|
directly_nested = false;
|
||||||
local_index = false;
|
local_index = false;
|
||||||
loop_init = 0;
|
loop_init = 0;
|
||||||
loop_test = 0;
|
loop_test = 0;
|
||||||
|
|
@ -41,52 +41,6 @@ void PGenerate::add_gate(PGate*gate)
|
||||||
gates.push_back(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)
|
ostream& operator << (ostream&out, PGenerate::scheme_t type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
|
|
|
||||||
11
PGenerate.h
11
PGenerate.h
|
|
@ -1,7 +1,7 @@
|
||||||
#ifndef IVL_PGenerate_H
|
#ifndef IVL_PGenerate_H
|
||||||
#define 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
|
* This source code is free software; you can redistribute it
|
||||||
* and/or modify it in source code form under the terms of the GNU
|
* 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};
|
GS_CASE, GS_CASE_ITEM, GS_NBLOCK};
|
||||||
scheme_t scheme_type;
|
scheme_t scheme_type;
|
||||||
|
|
||||||
|
bool directly_nested;
|
||||||
|
|
||||||
// generate loops have an index variable and three
|
// generate loops have an index variable and three
|
||||||
// expressions: for (index = <init>; <test>; index=<step>)
|
// expressions: for (index = <init>; <test>; index=<step>)
|
||||||
// the index is local if it was declared in the init expression,
|
// 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_case_(Design*des, NetScope*container);
|
||||||
bool generate_scope_nblock_(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.
|
// Elaborate_scope within a generated scope.
|
||||||
void elaborate_subscope_(Design*des, NetScope*scope);
|
void elaborate_subscope_(Design*des, NetScope*scope);
|
||||||
void elaborate_subscope_direct_(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="
|
<< " value=" << test->value() << ": Generate scope="
|
||||||
<< use_name << endl;
|
<< use_name << endl;
|
||||||
|
|
||||||
probe_for_direct_nesting_();
|
if (directly_nested) {
|
||||||
if (direct_nested_) {
|
|
||||||
if (debug_scopes)
|
if (debug_scopes)
|
||||||
cerr << get_fileline() << ": debug: Generate condition "
|
cerr << get_fileline() << ": debug: Generate condition "
|
||||||
<< (else_flag? "(else)" : "(if)")
|
<< (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.
|
// The name of the scope to generate, whatever that item is.
|
||||||
hname_t use_name (item->scope_name);
|
hname_t use_name (item->scope_name);
|
||||||
|
|
||||||
item->probe_for_direct_nesting_();
|
if (item->directly_nested) {
|
||||||
if (item->direct_nested_) {
|
|
||||||
if (debug_scopes)
|
if (debug_scopes)
|
||||||
cerr << get_fileline() << ": debug: Generate case item " << scope_name
|
cerr << get_fileline() << ": debug: Generate case item " << scope_name
|
||||||
<< " detected direct nesting." << endl;
|
<< " 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
|
bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
|
||||||
{
|
{
|
||||||
if (direct_nested_)
|
if (directly_nested)
|
||||||
return elaborate_sig_direct_(des, container);
|
return elaborate_sig_direct_(des, container);
|
||||||
|
|
||||||
bool flag = true;
|
bool flag = true;
|
||||||
|
|
@ -449,7 +449,7 @@ bool PGenerate::elaborate_sig(Design*des, NetScope*container) const
|
||||||
for (generate_it_t cur = generate_schemes.begin()
|
for (generate_it_t cur = generate_schemes.begin()
|
||||||
; cur != generate_schemes.end() ; ++ cur ) {
|
; cur != generate_schemes.end() ; ++ cur ) {
|
||||||
PGenerate*item = *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);
|
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()
|
for (generate_it_t icur = item->generate_schemes.begin()
|
||||||
; icur != item->generate_schemes.end() ; ++ icur ) {
|
; icur != item->generate_schemes.end() ; ++ icur ) {
|
||||||
PGenerate*case_item = *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);
|
flag &= case_item->elaborate_sig(des, container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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.
|
// Found the item, and it is direct nested.
|
||||||
flag &= item->elaborate_sig(des, container);
|
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
|
bool PGenerate::elaborate(Design*des, NetScope*container) const
|
||||||
{
|
{
|
||||||
if (direct_nested_)
|
if (directly_nested)
|
||||||
return elaborate_direct_(des, container);
|
return elaborate_direct_(des, container);
|
||||||
|
|
||||||
bool flag = true;
|
bool flag = true;
|
||||||
|
|
@ -6425,7 +6425,7 @@ bool PGenerate::elaborate(Design*des, NetScope*container) const
|
||||||
for (generate_it_t cur = generate_schemes.begin()
|
for (generate_it_t cur = generate_schemes.begin()
|
||||||
; cur != generate_schemes.end() ; ++ cur ) {
|
; cur != generate_schemes.end() ; ++ cur ) {
|
||||||
PGenerate*item = *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);
|
flag &= item->elaborate(des, container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -6487,7 +6487,7 @@ bool PGenerate::elaborate_direct_(Design*des, NetScope*container) const
|
||||||
cerr << get_fileline() << ": PGenerate::elaborate_direct_: "
|
cerr << get_fileline() << ": PGenerate::elaborate_direct_: "
|
||||||
<< "item->scope_name=" << item->scope_name
|
<< "item->scope_name=" << item->scope_name
|
||||||
<< ", item->scheme_type=" << item->scheme_type
|
<< ", 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()
|
<< ", item->scope_list_.size()=" << item->scope_list_.size()
|
||||||
<< "." << endl;
|
<< "." << endl;
|
||||||
}
|
}
|
||||||
|
|
@ -6500,12 +6500,12 @@ bool PGenerate::elaborate_direct_(Design*des, NetScope*container) const
|
||||||
for (generate_it_t icur = item->generate_schemes.begin()
|
for (generate_it_t icur = item->generate_schemes.begin()
|
||||||
; icur != item->generate_schemes.end() ; ++ icur ) {
|
; icur != item->generate_schemes.end() ; ++ icur ) {
|
||||||
PGenerate*case_item = *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);
|
flag &= case_item->elaborate(des, container);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} 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.
|
// Found the item, and it is direct nested.
|
||||||
flag &= item->elaborate(des, container);
|
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_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. */
|
only need to take note here of the scope name, if any. */
|
||||||
|
|
||||||
generate_block
|
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 generate_item_list_opt K_end
|
||||||
| K_begin ':' IDENTIFIER generate_item_list_opt K_end endlabel_opt
|
| K_begin ':' IDENTIFIER generate_item_list_opt K_end endlabel_opt
|
||||||
{ pform_generate_block_name($3);
|
{ 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. */
|
always within a module. */
|
||||||
static PGenerate*pform_cur_generate = 0;
|
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
|
/* Blocks within the same conditional generate construct may have
|
||||||
the same name. Here we collect the set of names used in each
|
the same name. Here we collect the set of names used in each
|
||||||
construct, so they can be added to the local scope without
|
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_timeunit_decl = true;
|
||||||
allow_timeprec_decl = true;
|
allow_timeprec_decl = true;
|
||||||
|
|
||||||
|
pform_generate_single_item = false;
|
||||||
|
|
||||||
add_local_symbol(lexical_scope, lex_name, cur_module);
|
add_local_symbol(lexical_scope, lex_name, cur_module);
|
||||||
|
|
||||||
lexical_scope = cur_module;
|
lexical_scope = cur_module;
|
||||||
|
|
@ -1511,6 +1517,22 @@ void pform_genvars(const struct vlltype&li, list<perm_string>*names)
|
||||||
delete 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,
|
void pform_start_generate_for(const struct vlltype&li,
|
||||||
bool local_index,
|
bool local_index,
|
||||||
char*ident1, PExpr*init,
|
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)
|
void pform_start_generate_if(const struct vlltype&li, PExpr*test)
|
||||||
{
|
{
|
||||||
|
detect_directly_nested_generate();
|
||||||
|
|
||||||
PGenerate*gen = new PGenerate(lexical_scope, scope_generate_counter++);
|
PGenerate*gen = new PGenerate(lexical_scope, scope_generate_counter++);
|
||||||
lexical_scope = gen;
|
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)
|
void pform_start_generate_case(const struct vlltype&li, PExpr*expr)
|
||||||
{
|
{
|
||||||
|
detect_directly_nested_generate();
|
||||||
|
|
||||||
PGenerate*gen = new PGenerate(lexical_scope, scope_generate_counter++);
|
PGenerate*gen = new PGenerate(lexical_scope, scope_generate_counter++);
|
||||||
lexical_scope = gen;
|
lexical_scope = gen;
|
||||||
|
|
||||||
|
|
@ -1640,6 +1666,8 @@ void pform_generate_case_item(const struct vlltype&li, list<PExpr*>*expr_list)
|
||||||
|
|
||||||
FILE_NAME(gen, li);
|
FILE_NAME(gen, li);
|
||||||
|
|
||||||
|
gen->directly_nested = pform_cur_generate->directly_nested;
|
||||||
|
|
||||||
pform_cur_generate = gen;
|
pform_cur_generate = gen;
|
||||||
|
|
||||||
pform_cur_generate->scheme_type = PGenerate::GS_CASE_ITEM;
|
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);
|
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,
|
extern void pform_start_generate_for(const struct vlltype&li,
|
||||||
bool local_index,
|
bool local_index,
|
||||||
char*ident1,
|
char*ident1,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue