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