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. */
Module::Module(perm_string n)
: PScope(n)
: PScope(n, 0)
{
library_flag = false;
default_nettype = NetNet::NONE;

View File

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

View File

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

View File

@ -20,14 +20,15 @@
*/
# include "StringHeap.h"
# include "pform_types.h"
# include <map>
class PEvent;
/*
* The PScope class is a base representation of an object that
* represents some sort of compile-time scope. For example, a module,
* a function/task, a named block is derived from a PScope.
* represents lexical scope. For example, a module, a function/task, a
* named block is derived from a PScope.
*
* NOTE: This is note the same concept as the "scope" of an elaborated
* hierarchy. That is represented by NetScope objects after elaboration.
@ -35,16 +36,26 @@ class PEvent;
class PScope {
public:
PScope(perm_string name);
~PScope();
// When created, a scope has a name and a parent. The name is
// 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_; }
PScope* pscope_parent() { return parent_; }
// Named events in the scope.
map<perm_string,PEvent*>events;
private:
perm_string name_;
PScope*parent_;
};
#endif

View File

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

View File

@ -51,7 +51,7 @@ struct PTaskFuncArg {
class PTask : public PScope, public LineInfo {
public:
explicit PTask(perm_string name);
explicit PTask(perm_string name, PScope*parent);
~PTask();
void set_ports(svector<PWire *>*p);
@ -90,7 +90,7 @@ class PTask : public PScope, public LineInfo {
class PFunction : public PScope, public LineInfo {
public:
explicit PFunction(perm_string name);
explicit PFunction(perm_string name, PScope*parent);
~PFunction();
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)
: name_(n), bl_type_(t), list_(st)
{
}
PBlock::PBlock(BL_TYPE t, const svector<Statement*>&st)
: bl_type_(t), list_(st)
PBlock::PBlock(perm_string n, PScope*parent, BL_TYPE t)
: PScope(n, parent), 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];
}
void PBlock::set_statement(const svector<Statement*>&st)
{
list_ = st;
}
PCallTask::PCallTask(const pform_name_t&n, const svector<PExpr*>&p)
: path_(n), parms_(p)
{

View File

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

View File

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

View File

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

71
parse.y
View File

@ -45,6 +45,12 @@ static struct {
svector<PExpr*>* range;
} 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
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
@ -1843,33 +1849,31 @@ module_item
extension. */
| K_task IDENTIFIER ';'
{ pform_push_scope($2); }
{ current_task = pform_push_task_scope($2);
FILE_NAME(current_task, @1);
}
task_item_list_opt
statement_or_null
K_endtask
{ perm_string task_name = lex_strings.make($2);
PTask*tmp = new PTask(task_name);
FILE_NAME(tmp, @1);
tmp->set_ports($5);
tmp->set_statement($6);
pform_set_task(task_name, tmp);
{ current_task->set_ports($5);
current_task->set_statement($6);
pform_pop_scope();
current_task = 0;
delete $2;
}
| K_task IDENTIFIER
{ pform_push_scope($2); }
{ current_task = pform_push_task_scope($2);
FILE_NAME(current_task, @1);
}
'(' task_port_decl_list ')' ';'
task_item_list_opt
statement_or_null
K_endtask
{ perm_string task_name = lex_strings.make($2);
PTask*tmp = new PTask(task_name);
FILE_NAME(tmp, @1);
tmp->set_ports($5);
tmp->set_statement($9);
pform_set_task(task_name, tmp);
{ current_task->set_ports($5);
current_task->set_statement($9);
pform_pop_scope();
current_task = 0;
delete $2;
}
@ -1879,17 +1883,14 @@ module_item
instead of the module. */
| K_function function_range_or_type_opt IDENTIFIER ';'
{ pform_push_scope($3); }
{ current_function = pform_push_function_scope($3); }
function_item_list statement
K_endfunction
{ perm_string name = lex_strings.make($3);
PFunction *tmp = new PFunction(name);
FILE_NAME(tmp, @1);
tmp->set_ports($6);
tmp->set_statement($7);
tmp->set_return($2);
pform_set_function(name, tmp);
{ current_function->set_ports($6);
current_function->set_statement($7);
current_function->set_return($2);
pform_pop_scope();
current_function = 0;
delete $3;
}
@ -2962,22 +2963,23 @@ statement
the declarations. The scope is popped at the end of the block. */
| 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);
tmp->set_statement(*$2);
delete $2;
$$ = tmp;
}
| 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
statement_list K_end
{ pform_pop_scope();
PBlock*tmp = new PBlock(lex_strings.make($3),
PBlock::BL_SEQ, *$6);
FILE_NAME(tmp, @1);
current_block->set_statement(*$6);
delete $3;
delete $6;
$$ = tmp;
$$ = current_block;
}
| K_begin K_end
{ PBlock*tmp = new PBlock(PBlock::BL_SEQ);
@ -2998,16 +3000,16 @@ statement
code generator can do the right thing. */
| 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
statement_list K_join
{ pform_pop_scope();
PBlock*tmp = new PBlock(lex_strings.make($3),
PBlock::BL_PAR, *$6);
FILE_NAME(tmp, @1);
current_block->set_statement(*$6);
delete $3;
delete $6;
$$ = tmp;
$$ = current_block;
}
| K_fork K_join
{ PBlock*tmp = new PBlock(PBlock::BL_PAR);
@ -3039,8 +3041,9 @@ statement
$$ = tmp;
}
| 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);
tmp->set_statement(*$2);
delete $2;
$$ = tmp;
}

View File

@ -38,6 +38,7 @@
# include "ivl_assert.h"
map<perm_string,Module*> pform_modules;
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 PScope* lexical_scope = 0;
void pform_push_scope(char*name)
{
@ -112,6 +114,7 @@ void pform_push_scope(char*name)
void pform_pop_scope()
{
scope_stack.pop_back();
lexical_scope = lexical_scope->pscope_parent();
}
static pform_name_t hier_name(const char*tail)
@ -121,6 +124,41 @@ static pform_name_t hier_name(const char*tail)
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)
{
/* 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;
}
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)
{
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
* deletes it. Thus, the string pushed must be allocated.
*/
extern void pform_push_scope(char*name);
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,
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_integer(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
$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
{
out << setw(ind) << "" << "begin";
if (name_ != 0)
out << " : " << name_;
if (pscope_name() != 0)
out << " : " << pscope_name();
out << endl;
for (unsigned idx = 0 ; idx < list_.count() ; idx += 1) {