From c87e629150d4d20c0fd00b3e7291c188a4c2d12d Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 19 Jun 2008 21:31:53 -0700 Subject: [PATCH] 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. --- PGenerate.cc | 10 +---- PGenerate.h | 10 +++-- PScope.cc | 2 +- PScope.h | 21 ++++++--- pform.cc | 118 ++++++++++++++++++++++++++++++++------------------- 5 files changed, 98 insertions(+), 63 deletions(-) diff --git a/PGenerate.cc b/PGenerate.cc index 97b7f9142..a769501e7 100644 --- a/PGenerate.cc +++ b/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::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); diff --git a/PGenerate.h b/PGenerate.h index f76eaeec9..d88115533 100644 --- a/PGenerate.h +++ b/PGenerate.h @@ -22,6 +22,7 @@ # include "LineInfo.h" # include "StringHeap.h" # include "HName.h" +# include "PScope.h" # include # include # 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; - mapwires; - PWire* get_wire(perm_string name) const; - list gates; void add_gate(PGate*); diff --git a/PScope.cc b/PScope.cc index c7f1a4517..92022fa26 100644 --- a/PScope.cc +++ b/PScope.cc @@ -33,7 +33,7 @@ PScope::~PScope() { } -PWire* PScope::wires_find(perm_string name) +PWire* LexicalScope::wires_find(perm_string name) { map::const_iterator cur = wires.find(name); if (cur == wires.end()) diff --git a/PScope.h b/PScope.h index 67129f52a..d65244a03 100644 --- a/PScope.h +++ b/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 + mapwires; + 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 - mapwires; - PWire* wires_find(perm_string name); - // Named events in the scope. mapevents; diff --git a/pform.cc b/pform.cc index 0299b9f5a..022a30461 100644 --- a/pform.cc +++ b/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*range, svector*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*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*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; }