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:
parent
3f2fa29482
commit
b0e4a6884a
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
19
PScope.h
19
PScope.h
|
|
@ -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
|
||||||
|
|
|
||||||
4
PTask.cc
4
PTask.cc
|
|
@ -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)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
4
PTask.h
4
PTask.h
|
|
@ -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);
|
||||||
|
|
|
||||||
16
Statement.cc
16
Statement.cc
|
|
@ -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)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
10
Statement.h
10
Statement.h
|
|
@ -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_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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."
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
167
parse.y
167
parse.y
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1878,20 +1882,17 @@ module_item
|
||||||
definitions in the func_body to take on the scope of the function
|
definitions in the func_body to take on the scope of the function
|
||||||
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);
|
pform_pop_scope();
|
||||||
tmp->set_statement($7);
|
current_function = 0;
|
||||||
tmp->set_return($2);
|
delete $3;
|
||||||
pform_set_function(name, tmp);
|
}
|
||||||
pform_pop_scope();
|
|
||||||
delete $3;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* A generate region can contain further module items. Actually, it
|
/* A generate region can contain further module items. Actually, it
|
||||||
is supposed to be limited to certain kinds of module items, but
|
is supposed to be limited to certain kinds of module items, but
|
||||||
|
|
@ -2961,65 +2962,66 @@ statement
|
||||||
name. These are handled by pushing the scope name then matching
|
name. These are handled by pushing the scope name then matching
|
||||||
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);
|
||||||
delete $2;
|
tmp->set_statement(*$2);
|
||||||
$$ = tmp;
|
delete $2;
|
||||||
}
|
$$ = tmp;
|
||||||
| K_begin ':' IDENTIFIER
|
}
|
||||||
{ pform_push_scope($3); }
|
| K_begin ':' IDENTIFIER
|
||||||
block_item_decls_opt
|
{ current_block = pform_push_block_scope($3, PBlock::BL_SEQ);
|
||||||
statement_list K_end
|
FILE_NAME(current_block, @1);
|
||||||
{ pform_pop_scope();
|
}
|
||||||
PBlock*tmp = new PBlock(lex_strings.make($3),
|
block_item_decls_opt
|
||||||
PBlock::BL_SEQ, *$6);
|
statement_list K_end
|
||||||
FILE_NAME(tmp, @1);
|
{ pform_pop_scope();
|
||||||
delete $3;
|
current_block->set_statement(*$6);
|
||||||
delete $6;
|
delete $3;
|
||||||
$$ = tmp;
|
delete $6;
|
||||||
}
|
$$ = current_block;
|
||||||
| K_begin K_end
|
}
|
||||||
{ PBlock*tmp = new PBlock(PBlock::BL_SEQ);
|
| K_begin K_end
|
||||||
FILE_NAME(tmp, @1);
|
{ PBlock*tmp = new PBlock(PBlock::BL_SEQ);
|
||||||
$$ = tmp;
|
FILE_NAME(tmp, @1);
|
||||||
}
|
$$ = tmp;
|
||||||
| K_begin ':' IDENTIFIER K_end
|
}
|
||||||
{ PBlock*tmp = new PBlock(PBlock::BL_SEQ);
|
| K_begin ':' IDENTIFIER K_end
|
||||||
FILE_NAME(tmp, @1);
|
{ PBlock*tmp = new PBlock(PBlock::BL_SEQ);
|
||||||
$$ = tmp;
|
FILE_NAME(tmp, @1);
|
||||||
}
|
$$ = tmp;
|
||||||
| K_begin error K_end
|
}
|
||||||
{ yyerrok; }
|
| K_begin error K_end
|
||||||
|
{ yyerrok; }
|
||||||
|
|
||||||
/* fork-join blocks are very similar to begin-end blocks. In fact,
|
/* fork-join blocks are very similar to begin-end blocks. In fact,
|
||||||
from the parser's perspective there is no real difference. All we
|
from the parser's perspective there is no real difference. All we
|
||||||
need to do is remember that this is a parallel block so that the
|
need to do is remember that this is a parallel block so that the
|
||||||
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);
|
||||||
block_item_decls_opt
|
FILE_NAME(current_block, @1);
|
||||||
statement_list K_join
|
}
|
||||||
{ pform_pop_scope();
|
block_item_decls_opt
|
||||||
PBlock*tmp = new PBlock(lex_strings.make($3),
|
statement_list K_join
|
||||||
PBlock::BL_PAR, *$6);
|
{ pform_pop_scope();
|
||||||
FILE_NAME(tmp, @1);
|
current_block->set_statement(*$6);
|
||||||
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);
|
||||||
FILE_NAME(tmp, @1);
|
FILE_NAME(tmp, @1);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
| K_fork ':' IDENTIFIER K_join
|
| K_fork ':' IDENTIFIER K_join
|
||||||
{ PBlock*tmp = new PBlock(PBlock::BL_PAR);
|
{ PBlock*tmp = new PBlock(PBlock::BL_PAR);
|
||||||
FILE_NAME(tmp, @1);
|
FILE_NAME(tmp, @1);
|
||||||
delete $3;
|
delete $3;
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
|
|
||||||
| K_disable hierarchy_identifier ';'
|
| K_disable hierarchy_identifier ';'
|
||||||
{ PDisable*tmp = new PDisable(*$2);
|
{ PDisable*tmp = new PDisable(*$2);
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
49
pform.cc
49
pform.cc
|
|
@ -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);
|
||||||
|
|
|
||||||
7
pform.h
7
pform.h
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue