Better handle nesting of scopes inside generate blocks.
Within generate schemes it is possible to have nested scopes, even more liberally then outside generate blocks. So see to it that the scopes properly stack with the generate blocks, and that wires and behaviors are put in the right scopes.
This commit is contained in:
parent
2f3627cd6d
commit
c87e629150
10
PGenerate.cc
10
PGenerate.cc
|
|
@ -27,21 +27,13 @@ PGenerate::PGenerate(unsigned id)
|
|||
: id_number(id)
|
||||
{
|
||||
parent = 0;
|
||||
lexical_scope = 0;
|
||||
}
|
||||
|
||||
PGenerate::~PGenerate()
|
||||
{
|
||||
}
|
||||
|
||||
PWire* PGenerate::get_wire(perm_string name) const
|
||||
{
|
||||
map<perm_string,PWire*>::const_iterator obj = wires.find(name);
|
||||
if (obj == wires.end())
|
||||
return 0;
|
||||
else
|
||||
return (*obj).second;
|
||||
}
|
||||
|
||||
void PGenerate::add_gate(PGate*gate)
|
||||
{
|
||||
gates.push_back(gate);
|
||||
|
|
|
|||
10
PGenerate.h
10
PGenerate.h
|
|
@ -22,6 +22,7 @@
|
|||
# include "LineInfo.h"
|
||||
# include "StringHeap.h"
|
||||
# include "HName.h"
|
||||
# include "PScope.h"
|
||||
# include <list>
|
||||
# include <map>
|
||||
# include "pform_types.h"
|
||||
|
|
@ -48,7 +49,7 @@ class PWire;
|
|||
* The parent points to the GS_CASE that contains this item.
|
||||
* the loop_test is compared with the parent->loop_test expression.
|
||||
*/
|
||||
class PGenerate : public LineInfo {
|
||||
class PGenerate : public LineInfo, public LexicalScope {
|
||||
|
||||
public:
|
||||
explicit PGenerate(unsigned id_number);
|
||||
|
|
@ -59,6 +60,10 @@ class PGenerate : public LineInfo {
|
|||
const unsigned id_number;
|
||||
perm_string scope_name;
|
||||
|
||||
// This is used during parsing to stack lexical scopes within
|
||||
// this generate scheme.
|
||||
PScope*lexical_scope;
|
||||
|
||||
enum scheme_t {GS_NONE, GS_LOOP, GS_CONDIT, GS_ELSE,
|
||||
GS_CASE, GS_CASE_ITEM};
|
||||
scheme_t scheme_type;
|
||||
|
|
@ -70,9 +75,6 @@ class PGenerate : public LineInfo {
|
|||
PExpr*loop_test;
|
||||
PExpr*loop_step;
|
||||
|
||||
map<perm_string,PWire*>wires;
|
||||
PWire* get_wire(perm_string name) const;
|
||||
|
||||
list<PGate*> gates;
|
||||
void add_gate(PGate*);
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ PScope::~PScope()
|
|||
{
|
||||
}
|
||||
|
||||
PWire* PScope::wires_find(perm_string name)
|
||||
PWire* LexicalScope::wires_find(perm_string name)
|
||||
{
|
||||
map<perm_string,PWire*>::const_iterator cur = wires.find(name);
|
||||
if (cur == wires.end())
|
||||
|
|
|
|||
21
PScope.h
21
PScope.h
|
|
@ -38,7 +38,22 @@ class NetScope;
|
|||
* NOTE: This is note the same concept as the "scope" of an elaborated
|
||||
* hierarchy. That is represented by NetScope objects after elaboration.
|
||||
*/
|
||||
class PScope {
|
||||
|
||||
class LexicalScope {
|
||||
|
||||
public:
|
||||
explicit LexicalScope() { }
|
||||
// A virtual destructor is so that dynamic_cast can work.
|
||||
virtual ~LexicalScope() { }
|
||||
|
||||
// Nets an variables (wires) in the scope
|
||||
map<perm_string,PWire*>wires;
|
||||
PWire* wires_find(perm_string name);
|
||||
|
||||
private:
|
||||
};
|
||||
|
||||
class PScope : public LexicalScope {
|
||||
|
||||
public:
|
||||
// When created, a scope has a name and a parent. The name is
|
||||
|
|
@ -56,10 +71,6 @@ class PScope {
|
|||
perm_string pscope_name() const { return name_; }
|
||||
PScope* pscope_parent() { return parent_; }
|
||||
|
||||
// Nets an variables (wires) in the scope
|
||||
map<perm_string,PWire*>wires;
|
||||
PWire* wires_find(perm_string name);
|
||||
|
||||
// Named events in the scope.
|
||||
map<perm_string,PEvent*>events;
|
||||
|
||||
|
|
|
|||
118
pform.cc
118
pform.cc
|
|
@ -93,48 +93,64 @@ static PScope* lexical_scope = 0;
|
|||
|
||||
void pform_pop_scope()
|
||||
{
|
||||
lexical_scope = lexical_scope->pscope_parent();
|
||||
if (pform_cur_generate) {
|
||||
assert(pform_cur_generate->lexical_scope);
|
||||
PScope*cur = pform_cur_generate->lexical_scope;
|
||||
pform_cur_generate->lexical_scope = cur->pscope_parent();
|
||||
} else {
|
||||
assert(lexical_scope);
|
||||
lexical_scope = lexical_scope->pscope_parent();
|
||||
}
|
||||
}
|
||||
|
||||
PTask* pform_push_task_scope(char*name)
|
||||
{
|
||||
perm_string task_name = lex_strings.make(name);
|
||||
PTask*task = new PTask(task_name, pform_cur_module);
|
||||
|
||||
// Add the task to the current module
|
||||
if (pform_cur_generate)
|
||||
PTask*task;
|
||||
if (pform_cur_generate) {
|
||||
task = new PTask(task_name, pform_cur_generate->lexical_scope);
|
||||
pform_cur_generate->tasks[task->pscope_name()] = task;
|
||||
else
|
||||
pform_cur_generate->lexical_scope = task;
|
||||
} else {
|
||||
task = new PTask(task_name, lexical_scope);
|
||||
pform_cur_module->tasks[task->pscope_name()] = task;
|
||||
lexical_scope = task;
|
||||
}
|
||||
|
||||
// Make this the current lexical scope
|
||||
lexical_scope = task;
|
||||
return task;
|
||||
}
|
||||
|
||||
PFunction* pform_push_function_scope(char*name)
|
||||
{
|
||||
perm_string func_name = lex_strings.make(name);
|
||||
PFunction*func = new PFunction(func_name, lexical_scope);
|
||||
|
||||
// Add the task to the current module
|
||||
if (pform_cur_generate)
|
||||
PFunction*func;
|
||||
if (pform_cur_generate) {
|
||||
func = new PFunction(func_name, pform_cur_generate->lexical_scope);
|
||||
pform_cur_generate->funcs[func->pscope_name()] = func;
|
||||
else
|
||||
pform_cur_generate->lexical_scope = func;
|
||||
} else {
|
||||
func = new PFunction(func_name, lexical_scope);
|
||||
pform_cur_module->funcs[func->pscope_name()] = func;
|
||||
lexical_scope = func;
|
||||
}
|
||||
|
||||
// Make this the current lexical scope
|
||||
lexical_scope = func;
|
||||
return func;
|
||||
}
|
||||
|
||||
PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
|
||||
{
|
||||
perm_string block_name = lex_strings.make(name);
|
||||
PBlock*block = new PBlock(block_name, lexical_scope, bt);
|
||||
|
||||
// Make this the current lexical scope
|
||||
lexical_scope = block;
|
||||
PBlock*block;
|
||||
if (pform_cur_generate) {
|
||||
block = new PBlock(block_name, pform_cur_generate->lexical_scope, bt);
|
||||
pform_cur_generate->lexical_scope = block;
|
||||
} else {
|
||||
block = new PBlock(block_name, lexical_scope, bt);
|
||||
lexical_scope = block;
|
||||
}
|
||||
|
||||
return block;
|
||||
}
|
||||
|
|
@ -146,9 +162,34 @@ PWire*pform_get_wire_in_scope(perm_string name)
|
|||
cannot be within sub-scopes. Only directly in
|
||||
modules. */
|
||||
if (pform_cur_generate)
|
||||
return pform_cur_generate->get_wire(name);
|
||||
if (pform_cur_generate->lexical_scope)
|
||||
return pform_cur_generate->lexical_scope->wires_find(name);
|
||||
else
|
||||
return pform_cur_generate->wires_find(name);
|
||||
else
|
||||
return lexical_scope->wires_find(name);
|
||||
}
|
||||
|
||||
return lexical_scope->wires_find(name);
|
||||
static void pform_put_wire_in_scope(perm_string name, PWire*net)
|
||||
{
|
||||
if (pform_cur_generate)
|
||||
if (pform_cur_generate->lexical_scope)
|
||||
pform_cur_generate->lexical_scope->wires[name] = net;
|
||||
else
|
||||
pform_cur_generate->wires[name] = net;
|
||||
else
|
||||
lexical_scope->wires[name] = net;
|
||||
}
|
||||
|
||||
static void pform_put_behavior_in_scope(PProcess*pp)
|
||||
{
|
||||
if (pform_cur_generate)
|
||||
if (pform_cur_generate->lexical_scope)
|
||||
pform_cur_generate->lexical_scope->behaviors.push_back(pp);
|
||||
else
|
||||
pform_cur_generate->behaviors.push_back(pp);
|
||||
else
|
||||
lexical_scope->behaviors.push_back(pp);
|
||||
}
|
||||
|
||||
void pform_set_default_nettype(NetNet::Type type,
|
||||
|
|
@ -1258,10 +1299,7 @@ void pform_make_reginit(const struct vlltype&li,
|
|||
PProcess*top = new PProcess(PProcess::PR_INITIAL, ass);
|
||||
FILE_NAME(top, li);
|
||||
|
||||
if (pform_cur_generate)
|
||||
pform_cur_generate->behaviors.push_back(top);
|
||||
else
|
||||
lexical_scope->behaviors.push_back(top);
|
||||
pform_put_behavior_in_scope(top);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1282,7 +1320,7 @@ void pform_module_define_port(const struct vlltype&li,
|
|||
svector<PExpr*>*range,
|
||||
svector<named_pexpr_t*>*attr)
|
||||
{
|
||||
PWire*cur = lexical_scope->wires_find(name);
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
if (cur) {
|
||||
ostringstream msg;
|
||||
msg << name << " definition conflicts with "
|
||||
|
|
@ -1316,7 +1354,7 @@ void pform_module_define_port(const struct vlltype&li,
|
|||
cur->attributes[tmp->name] = tmp->parm;
|
||||
}
|
||||
}
|
||||
lexical_scope->wires[name] = cur;
|
||||
pform_put_wire_in_scope(name, cur);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1399,12 +1437,8 @@ void pform_makewire(const vlltype&li, perm_string name,
|
|||
}
|
||||
}
|
||||
|
||||
if (new_wire_flag) {
|
||||
if (pform_cur_generate)
|
||||
pform_cur_generate->wires[name] = cur;
|
||||
else
|
||||
lexical_scope->wires[name] = cur;
|
||||
}
|
||||
if (new_wire_flag)
|
||||
pform_put_wire_in_scope(name, cur);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
@ -1480,11 +1514,11 @@ void pform_makewire(const vlltype&li,
|
|||
void pform_set_port_type(perm_string name, NetNet::PortType pt,
|
||||
const char*file, unsigned lineno)
|
||||
{
|
||||
PWire*cur = lexical_scope->wires_find(name);
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::IMPLICIT, NetNet::PIMPLICIT, IVL_VT_NO_TYPE);
|
||||
FILE_NAME(cur, file, lineno);
|
||||
lexical_scope->wires[name] = cur;
|
||||
pform_put_wire_in_scope(name, cur);
|
||||
}
|
||||
|
||||
switch (cur->get_port_type()) {
|
||||
|
|
@ -1566,13 +1600,13 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
|
|||
|
||||
/* Look for a preexisting wire. If it exists, set the
|
||||
port direction. If not, create it. */
|
||||
PWire*curw = lexical_scope->wires_find(name);
|
||||
PWire*curw = pform_get_wire_in_scope(name);
|
||||
if (curw) {
|
||||
curw->set_port_type(pt);
|
||||
} else {
|
||||
curw = new PWire(name, NetNet::IMPLICIT_REG, pt, vtype);
|
||||
FILE_NAME(curw, file, lineno);
|
||||
lexical_scope->wires[name] = curw;
|
||||
pform_put_wire_in_scope(name, curw);
|
||||
}
|
||||
|
||||
curw->set_signed(signed_flag);
|
||||
|
|
@ -1633,7 +1667,7 @@ void pform_set_reg_idx(perm_string name, PExpr*l, PExpr*r)
|
|||
{
|
||||
PWire*cur = 0;
|
||||
if (pform_cur_generate) {
|
||||
cur = pform_cur_generate->get_wire(name);
|
||||
cur = pform_cur_generate->wires_find(name);
|
||||
} else {
|
||||
cur = lexical_scope->wires_find(name);
|
||||
}
|
||||
|
|
@ -1816,13 +1850,13 @@ void pform_set_port_type(const struct vlltype&li,
|
|||
|
||||
static void pform_set_reg_integer(perm_string name)
|
||||
{
|
||||
PWire*cur = lexical_scope->wires_find(name);
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::INTEGER,
|
||||
NetNet::NOT_A_PORT,
|
||||
IVL_VT_LOGIC);
|
||||
cur->set_signed(true);
|
||||
lexical_scope->wires[name] = cur;
|
||||
pform_put_wire_in_scope(name, cur);
|
||||
} else {
|
||||
bool rc = cur->set_wire_type(NetNet::INTEGER);
|
||||
assert(rc);
|
||||
|
|
@ -1850,10 +1884,10 @@ void pform_set_reg_integer(list<perm_string>*names)
|
|||
|
||||
static void pform_set_reg_time(perm_string name)
|
||||
{
|
||||
PWire*cur = lexical_scope->wires_find(name);
|
||||
PWire*cur = pform_get_wire_in_scope(name);
|
||||
if (cur == 0) {
|
||||
cur = new PWire(name, NetNet::REG, NetNet::NOT_A_PORT, IVL_VT_LOGIC);
|
||||
lexical_scope->wires[name] = cur;
|
||||
pform_put_wire_in_scope(name, cur);
|
||||
} else {
|
||||
bool rc = cur->set_wire_type(NetNet::REG);
|
||||
assert(rc);
|
||||
|
|
@ -1912,11 +1946,7 @@ PProcess* pform_make_behavior(PProcess::Type type, Statement*st,
|
|||
delete attr;
|
||||
}
|
||||
|
||||
if (pform_cur_generate)
|
||||
pform_cur_generate->behaviors.push_back(pp);
|
||||
else
|
||||
pform_cur_module->behaviors.push_back(pp);
|
||||
|
||||
pform_put_behavior_in_scope(pp);
|
||||
return pp;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue