Objects of lexical scope use PScope base class.

All the pform objects that represent lexical scope now are derived
from the PScope class, and are kept in a lexical_scope table so that
the scope can be managed.
This commit is contained in:
Stephen Williams 2008-02-15 21:20:24 -08:00
parent 3f2fa29482
commit b0e4a6884a
14 changed files with 173 additions and 129 deletions

View File

@ -29,7 +29,7 @@
/* n is a permallocated string. */ /* n is a permallocated string. */
Module::Module(perm_string n) Module::Module(perm_string n)
: PScope(n) : PScope(n, 0)
{ {
library_flag = false; library_flag = false;
default_nettype = NetNet::NONE; default_nettype = NetNet::NONE;

View File

@ -21,8 +21,8 @@
#include "PTask.h" #include "PTask.h"
PFunction::PFunction(perm_string name) PFunction::PFunction(perm_string name, PScope*parent)
: PScope(name), ports_(0), statement_(0) : PScope(name, parent), ports_(0), statement_(0)
{ {
return_type_.type = PTF_NONE; return_type_.type = PTF_NONE;
} }

View File

@ -19,8 +19,8 @@
# include "PScope.h" # include "PScope.h"
PScope::PScope(perm_string n) PScope::PScope(perm_string n, PScope*p)
: name_(n) : name_(n), parent_(p)
{ {
} }

View File

@ -20,14 +20,15 @@
*/ */
# include "StringHeap.h" # include "StringHeap.h"
# include "pform_types.h"
# include <map> # include <map>
class PEvent; class PEvent;
/* /*
* The PScope class is a base representation of an object that * The PScope class is a base representation of an object that
* represents some sort of compile-time scope. For example, a module, * represents lexical scope. For example, a module, a function/task, a
* a function/task, a named block is derived from a PScope. * named block is derived from a PScope.
* *
* NOTE: This is note the same concept as the "scope" of an elaborated * NOTE: This is note the same concept as the "scope" of an elaborated
* hierarchy. That is represented by NetScope objects after elaboration. * hierarchy. That is represented by NetScope objects after elaboration.
@ -35,16 +36,26 @@ class PEvent;
class PScope { class PScope {
public: public:
PScope(perm_string name); // When created, a scope has a name and a parent. The name is
~PScope(); // the name of the definition. For example, if this is a
// module declaration, the name is the name after the "module"
// keyword, and if this is a task scope, the name is the task
// name. The parent is the lexical parent of this scope. Since
// modules do not nest in Verilog, the parent must be nil for
// modules. Scopes for tasks and functions point to their
// containing module.
PScope(perm_string name, PScope*parent);
virtual ~PScope();
perm_string pscope_name() const { return name_; } perm_string pscope_name() const { return name_; }
PScope* pscope_parent() { return parent_; }
// Named events in the scope. // Named events in the scope.
map<perm_string,PEvent*>events; map<perm_string,PEvent*>events;
private: private:
perm_string name_; perm_string name_;
PScope*parent_;
}; };
#endif #endif

View File

@ -21,8 +21,8 @@
# include "PTask.h" # include "PTask.h"
PTask::PTask(perm_string name) PTask::PTask(perm_string name, PScope*parent)
: PScope(name), ports_(0), statement_(0) : PScope(name, parent), ports_(0), statement_(0)
{ {
} }

View File

@ -51,7 +51,7 @@ struct PTaskFuncArg {
class PTask : public PScope, public LineInfo { class PTask : public PScope, public LineInfo {
public: public:
explicit PTask(perm_string name); explicit PTask(perm_string name, PScope*parent);
~PTask(); ~PTask();
void set_ports(svector<PWire *>*p); void set_ports(svector<PWire *>*p);
@ -90,7 +90,7 @@ class PTask : public PScope, public LineInfo {
class PFunction : public PScope, public LineInfo { class PFunction : public PScope, public LineInfo {
public: public:
explicit PFunction(perm_string name); explicit PFunction(perm_string name, PScope*parent);
~PFunction(); ~PFunction();
void set_ports(svector<PWire *>*p); void set_ports(svector<PWire *>*p);

View File

@ -86,18 +86,13 @@ PAssignNB::~PAssignNB()
{ {
} }
PBlock::PBlock(perm_string n, BL_TYPE t, const svector<Statement*>&st) PBlock::PBlock(perm_string n, PScope*parent, BL_TYPE t)
: name_(n), bl_type_(t), list_(st) : PScope(n, parent), bl_type_(t)
{
}
PBlock::PBlock(BL_TYPE t, const svector<Statement*>&st)
: bl_type_(t), list_(st)
{ {
} }
PBlock::PBlock(BL_TYPE t) PBlock::PBlock(BL_TYPE t)
: bl_type_(t) : PScope(perm_string(),0), bl_type_(t)
{ {
} }
@ -107,6 +102,11 @@ PBlock::~PBlock()
delete list_[idx]; delete list_[idx];
} }
void PBlock::set_statement(const svector<Statement*>&st)
{
list_ = st;
}
PCallTask::PCallTask(const pform_name_t&n, const svector<PExpr*>&p) PCallTask::PCallTask(const pform_name_t&n, const svector<PExpr*>&p)
: path_(n), parms_(p) : path_(n), parms_(p)
{ {

View File

@ -27,6 +27,7 @@
# include "StringHeap.h" # include "StringHeap.h"
# include "PDelays.h" # include "PDelays.h"
# include "PExpr.h" # include "PExpr.h"
# include "PScope.h"
# include "HName.h" # include "HName.h"
# include "LineInfo.h" # include "LineInfo.h"
class PExpr; class PExpr;
@ -147,25 +148,26 @@ class PAssignNB : public PAssign_ {
* statements before constructing this object, so it knows a priori * statements before constructing this object, so it knows a priori
* what is contained. * what is contained.
*/ */
class PBlock : public Statement { class PBlock : public PScope, public Statement {
public: public:
enum BL_TYPE { BL_SEQ, BL_PAR }; enum BL_TYPE { BL_SEQ, BL_PAR };
explicit PBlock(perm_string n, BL_TYPE t, const svector<Statement*>&st); // If the block has a name, it is a scope and also has a parent.
explicit PBlock(BL_TYPE t, const svector<Statement*>&st); explicit PBlock(perm_string n, PScope*parent, BL_TYPE t);
// If it doesn't have a name, it's not a scope
explicit PBlock(BL_TYPE t); explicit PBlock(BL_TYPE t);
~PBlock(); ~PBlock();
BL_TYPE bl_type() const { return bl_type_; } BL_TYPE bl_type() const { return bl_type_; }
void set_statement(const svector<Statement*>&st);
virtual void dump(ostream&out, unsigned ind) const; virtual void dump(ostream&out, unsigned ind) const;
virtual NetProc* elaborate(Design*des, NetScope*scope) const; virtual NetProc* elaborate(Design*des, NetScope*scope) const;
virtual void elaborate_scope(Design*des, NetScope*scope) const; virtual void elaborate_scope(Design*des, NetScope*scope) const;
private: private:
perm_string name_;
const BL_TYPE bl_type_; const BL_TYPE bl_type_;
svector<Statement*>list_; svector<Statement*>list_;
}; };

View File

@ -794,8 +794,8 @@ void PBlock::elaborate_scope(Design*des, NetScope*scope) const
{ {
NetScope*my_scope = scope; NetScope*my_scope = scope;
if (name_ != 0) { if (pscope_name() != 0) {
hname_t use_name(name_); hname_t use_name(pscope_name());
if (scope->child(use_name)) { if (scope->child(use_name)) {
cerr << get_fileline() << ": error: block/scope name " cerr << get_fileline() << ": error: block/scope name "
<< use_name << " already used in this context." << use_name << " already used in this context."

View File

@ -1846,12 +1846,12 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
: NetBlock::SEQU; : NetBlock::SEQU;
NetScope*nscope = 0; NetScope*nscope = 0;
if (name_.str() != 0) { if (pscope_name() != 0) {
nscope = scope->child(hname_t(name_)); nscope = scope->child(hname_t(pscope_name()));
if (nscope == 0) { if (nscope == 0) {
cerr << get_fileline() << ": internal error: " cerr << get_fileline() << ": internal error: "
"unable to find block scope " << scope_path(scope) "unable to find block scope " << scope_path(scope)
<< "<" << name_ << ">" << endl; << "<" << pscope_name() << ">" << endl;
des->errors += 1; des->errors += 1;
return 0; return 0;
} }
@ -1869,7 +1869,7 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const
// statement. There is no need to keep the block node. Also, // statement. There is no need to keep the block node. Also,
// don't elide named blocks, because they might be referenced // don't elide named blocks, because they might be referenced
// elsewhere. // elsewhere.
if ((list_.count() == 1) && (name_.str() == 0)) { if ((list_.count() == 1) && (pscope_name() == 0)) {
assert(list_[0]); assert(list_[0]);
NetProc*tmp = list_[0]->elaborate(des, nscope); NetProc*tmp = list_[0]->elaborate(des, nscope);
return tmp; return tmp;

71
parse.y
View File

@ -45,6 +45,12 @@ static struct {
svector<PExpr*>* range; svector<PExpr*>* range;
} port_declaration_context; } port_declaration_context;
/* The task and function rules need to briefly hold the pointer to the
task/function that is currently in progress. */
static PTask* current_task = 0;
static PFunction* current_function = 0;
static PBlock* current_block = 0;
/* Later version of bison (including 1.35) will not compile in stack /* Later version of bison (including 1.35) will not compile in stack
extension if the output is compiled with C++ and either the YYSTYPE extension if the output is compiled with C++ and either the YYSTYPE
or YYLTYPE are provided by the source code. However, I can get the or YYLTYPE are provided by the source code. However, I can get the
@ -1843,33 +1849,31 @@ module_item
extension. */ extension. */
| K_task IDENTIFIER ';' | K_task IDENTIFIER ';'
{ pform_push_scope($2); } { current_task = pform_push_task_scope($2);
FILE_NAME(current_task, @1);
}
task_item_list_opt task_item_list_opt
statement_or_null statement_or_null
K_endtask K_endtask
{ perm_string task_name = lex_strings.make($2); { current_task->set_ports($5);
PTask*tmp = new PTask(task_name); current_task->set_statement($6);
FILE_NAME(tmp, @1);
tmp->set_ports($5);
tmp->set_statement($6);
pform_set_task(task_name, tmp);
pform_pop_scope(); pform_pop_scope();
current_task = 0;
delete $2; delete $2;
} }
| K_task IDENTIFIER | K_task IDENTIFIER
{ pform_push_scope($2); } { current_task = pform_push_task_scope($2);
FILE_NAME(current_task, @1);
}
'(' task_port_decl_list ')' ';' '(' task_port_decl_list ')' ';'
task_item_list_opt task_item_list_opt
statement_or_null statement_or_null
K_endtask K_endtask
{ perm_string task_name = lex_strings.make($2); { current_task->set_ports($5);
PTask*tmp = new PTask(task_name); current_task->set_statement($9);
FILE_NAME(tmp, @1);
tmp->set_ports($5);
tmp->set_statement($9);
pform_set_task(task_name, tmp);
pform_pop_scope(); pform_pop_scope();
current_task = 0;
delete $2; delete $2;
} }
@ -1879,17 +1883,14 @@ module_item
instead of the module. */ instead of the module. */
| K_function function_range_or_type_opt IDENTIFIER ';' | K_function function_range_or_type_opt IDENTIFIER ';'
{ pform_push_scope($3); } { current_function = pform_push_function_scope($3); }
function_item_list statement function_item_list statement
K_endfunction K_endfunction
{ perm_string name = lex_strings.make($3); { current_function->set_ports($6);
PFunction *tmp = new PFunction(name); current_function->set_statement($7);
FILE_NAME(tmp, @1); current_function->set_return($2);
tmp->set_ports($6);
tmp->set_statement($7);
tmp->set_return($2);
pform_set_function(name, tmp);
pform_pop_scope(); pform_pop_scope();
current_function = 0;
delete $3; delete $3;
} }
@ -2962,22 +2963,23 @@ statement
the declarations. The scope is popped at the end of the block. */ the declarations. The scope is popped at the end of the block. */
| K_begin statement_list K_end | K_begin statement_list K_end
{ PBlock*tmp = new PBlock(PBlock::BL_SEQ, *$2); { PBlock*tmp = new PBlock(PBlock::BL_SEQ);
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);
tmp->set_statement(*$2);
delete $2; delete $2;
$$ = tmp; $$ = tmp;
} }
| K_begin ':' IDENTIFIER | K_begin ':' IDENTIFIER
{ pform_push_scope($3); } { current_block = pform_push_block_scope($3, PBlock::BL_SEQ);
FILE_NAME(current_block, @1);
}
block_item_decls_opt block_item_decls_opt
statement_list K_end statement_list K_end
{ pform_pop_scope(); { pform_pop_scope();
PBlock*tmp = new PBlock(lex_strings.make($3), current_block->set_statement(*$6);
PBlock::BL_SEQ, *$6);
FILE_NAME(tmp, @1);
delete $3; delete $3;
delete $6; delete $6;
$$ = tmp; $$ = current_block;
} }
| K_begin K_end | K_begin K_end
{ PBlock*tmp = new PBlock(PBlock::BL_SEQ); { PBlock*tmp = new PBlock(PBlock::BL_SEQ);
@ -2998,16 +3000,16 @@ statement
code generator can do the right thing. */ code generator can do the right thing. */
| K_fork ':' IDENTIFIER | K_fork ':' IDENTIFIER
{ pform_push_scope($3); } { current_block = pform_push_block_scope($3, PBlock::BL_PAR);
FILE_NAME(current_block, @1);
}
block_item_decls_opt block_item_decls_opt
statement_list K_join statement_list K_join
{ pform_pop_scope(); { pform_pop_scope();
PBlock*tmp = new PBlock(lex_strings.make($3), current_block->set_statement(*$6);
PBlock::BL_PAR, *$6);
FILE_NAME(tmp, @1);
delete $3; delete $3;
delete $6; delete $6;
$$ = tmp; $$ = current_block;
} }
| K_fork K_join | K_fork K_join
{ PBlock*tmp = new PBlock(PBlock::BL_PAR); { PBlock*tmp = new PBlock(PBlock::BL_PAR);
@ -3039,8 +3041,9 @@ statement
$$ = tmp; $$ = tmp;
} }
| K_fork statement_list K_join | K_fork statement_list K_join
{ PBlock*tmp = new PBlock(PBlock::BL_PAR, *$2); { PBlock*tmp = new PBlock(PBlock::BL_PAR);
FILE_NAME(tmp, @1); FILE_NAME(tmp, @1);
tmp->set_statement(*$2);
delete $2; delete $2;
$$ = tmp; $$ = tmp;
} }

View File

@ -38,6 +38,7 @@
# include "ivl_assert.h" # include "ivl_assert.h"
map<perm_string,Module*> pform_modules; map<perm_string,Module*> pform_modules;
map<perm_string,PUdp*> pform_primitives; map<perm_string,PUdp*> pform_primitives;
@ -103,6 +104,7 @@ static inline void FILE_NAME(LineInfo*tmp, const struct vlltype&where)
*/ */
static pform_name_t scope_stack; static pform_name_t scope_stack;
static PScope* lexical_scope = 0;
void pform_push_scope(char*name) void pform_push_scope(char*name)
{ {
@ -112,6 +114,7 @@ void pform_push_scope(char*name)
void pform_pop_scope() void pform_pop_scope()
{ {
scope_stack.pop_back(); scope_stack.pop_back();
lexical_scope = lexical_scope->pscope_parent();
} }
static pform_name_t hier_name(const char*tail) static pform_name_t hier_name(const char*tail)
@ -121,6 +124,41 @@ static pform_name_t hier_name(const char*tail)
return name; return name;
} }
PTask* pform_push_task_scope(char*name)
{
pform_push_scope(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
pform_cur_module->add_task(task->pscope_name(), task);
// Make this the current lexical scope
lexical_scope = task;
return task;
}
PFunction* pform_push_function_scope(char*name)
{
pform_push_scope(name);
perm_string func_name = lex_strings.make(name);
PFunction*func = new PFunction(func_name, lexical_scope);
// Add the task to the current module
pform_cur_module->add_function(func->pscope_name(), func);
// Make this the current lexical scope
lexical_scope = func;
return func;
}
PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt)
{
pform_push_scope(name);
perm_string block_name = lex_strings.make(name);
PBlock*block = new PBlock(block_name, lexical_scope, bt);
return block;
}
static PWire*get_wire_in_module(const pform_name_t&name) static PWire*get_wire_in_module(const pform_name_t&name)
{ {
/* Note that if we are processing a generate, then the /* Note that if we are processing a generate, then the
@ -1590,17 +1628,6 @@ svector<PWire*>*pform_make_task_ports(NetNet::PortType pt,
return res; return res;
} }
void pform_set_task(perm_string name, PTask*task)
{
pform_cur_module->add_task(name, task);
}
void pform_set_function(perm_string name, PFunction*func)
{
pform_cur_module->add_function(name, func);
}
void pform_set_attrib(perm_string name, perm_string key, char*value) void pform_set_attrib(perm_string name, perm_string key, char*value)
{ {
pform_name_t path = hier_name(name); pform_name_t path = hier_name(name);

View File

@ -167,9 +167,12 @@ extern void pform_make_udp(perm_string name,
* name string onto the scope hierarchy. The pop pulls it off and * name string onto the scope hierarchy. The pop pulls it off and
* deletes it. Thus, the string pushed must be allocated. * deletes it. Thus, the string pushed must be allocated.
*/ */
extern void pform_push_scope(char*name);
extern void pform_pop_scope(); extern void pform_pop_scope();
extern PTask*pform_push_task_scope(char*name);
extern PFunction*pform_push_function_scope(char*name);
extern PBlock*pform_push_block_scope(char*name, PBlock::BL_TYPE tt);
extern verinum* pform_verinum_with_size(verinum*s, verinum*val, extern verinum* pform_verinum_with_size(verinum*s, verinum*val,
const char*file, unsigned loneno); const char*file, unsigned loneno);
@ -248,8 +251,6 @@ extern void pform_set_net_range(list<perm_string>*names,
extern void pform_set_reg_idx(const char*name, PExpr*l, PExpr*r); extern void pform_set_reg_idx(const char*name, PExpr*l, PExpr*r);
extern void pform_set_reg_integer(list<perm_string>*names); extern void pform_set_reg_integer(list<perm_string>*names);
extern void pform_set_reg_time(list<perm_string>*names); extern void pform_set_reg_time(list<perm_string>*names);
extern void pform_set_task(perm_string name, PTask*);
extern void pform_set_function(perm_string name, PFunction*);
/* pform_set_attrib and pform_set_type_attrib exist to support the /* pform_set_attrib and pform_set_type_attrib exist to support the
$attribute syntax, which can only set string values to $attribute syntax, which can only set string values to

View File

@ -504,8 +504,8 @@ void PAssignNB::dump(ostream&out, unsigned ind) const
void PBlock::dump(ostream&out, unsigned ind) const void PBlock::dump(ostream&out, unsigned ind) const
{ {
out << setw(ind) << "" << "begin"; out << setw(ind) << "" << "begin";
if (name_ != 0) if (pscope_name() != 0)
out << " : " << name_; out << " : " << pscope_name();
out << endl; out << endl;
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1) { for (unsigned idx = 0 ; idx < list_.count() ; idx += 1) {