Handle variables in process statements

Parse variables declared in the declaration section of process
statements, and support variable assignment statements.
This commit is contained in:
Stephen Williams 2011-08-17 20:19:15 -07:00
parent 51b1d57f19
commit f5220c54f1
13 changed files with 248 additions and 33 deletions

View File

@ -43,6 +43,23 @@ int Scope::emit_signals(ostream&out, Entity*entity, Architecture*arc)
return errors;
}
int Scope::emit_variables(ostream&out, Entity*entity, Architecture*arc)
{
int errors = 0;
for (map<perm_string,Variable*>::iterator cur = old_variables_.begin()
; cur != old_variables_.end() ; ++cur) {
errors += cur->second->emit(out, entity, arc);
}
for (map<perm_string,Variable*>::iterator cur = new_variables_.begin()
; cur != new_variables_.end() ; ++cur) {
errors += cur->second->emit(out, entity, arc);
}
return errors;
}
int Architecture::emit(ostream&out, Entity*entity)
{
int errors = 0;
@ -63,6 +80,7 @@ int Architecture::emit(ostream&out, Entity*entity)
}
errors += emit_signals(out, entity, this);
errors += emit_variables(out, entity, this);
for (list<Architecture::Statement*>::iterator cur = statements_.begin()
; cur != statements_.end() ; ++cur) {

View File

@ -145,9 +145,9 @@ void Entity::dump(ostream&out, int indent) const
}
}
void Signal::dump(ostream&out, int indent) const
void SigVarBase::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "signal " << name_ << " is ";
out << setw(indent) << "" << "signal/variable " << name_ << " is ";
if (type_)
out << *type_;
else

View File

@ -57,18 +57,25 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ)
return errors;
}
Signal*sig = arc->find_signal(name_);
if (sig == 0) {
cerr << get_fileline() << ": error: Signal/variable " << name_
<< " not found in this context." << endl;
return errors + 1;
if (Signal*sig = arc->find_signal(name_)) {
// Tell the target signal that this may be a sequential l-value.
if (is_sequ) sig->count_ref_sequ();
set_type(sig->peek_type());
return errors;
}
// Tell the target signal that this may be a sequential l-value.
if (is_sequ) sig->count_ref_sequ();
if (Variable*sig = arc->find_variable(name_)) {
// Tell the target signal that this may be a sequential l-value.
if (is_sequ) sig->count_ref_sequ();
set_type(sig->peek_type());
return errors;
set_type(sig->peek_type());
return errors;
}
cerr << get_fileline() << ": error: Signal/variable " << name_
<< " not found in this context." << endl;
return errors + 1;
}
int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lval)

View File

@ -255,7 +255,7 @@ const VType*parse_type_by_name(perm_string name)
%type <sequ_list> sequence_of_statements if_statement_else
%type <sequ> sequential_statement if_statement signal_assignment_statement
%type <sequ> case_statement procedure_call procedure_call_statement
%type <sequ> loop_statement
%type <sequ> loop_statement variable_assignment_statement
%type <range> range
@ -1321,28 +1321,53 @@ procedure_call_statement
| procedure_call { $$ = $1; }
;
process_declarative_item
: K_variable identifier_list ':' subtype_indication ';'
{ /* Save the signal declaration in the block_signals map. */
for (std::list<perm_string>::iterator cur = $2->begin()
; cur != $2->end() ; ++cur) {
Variable*sig = new Variable(*cur, $4);
FILE_NAME(sig, @1);
active_scope->bind_name(*cur, sig);
}
delete $2;
}
;
process_declarative_part
: process_declarative_part process_declarative_item
| process_declarative_item
;
process_declarative_part_opt
: process_declarative_part
|
;
process_statement
: IDENTIFIER ':' K_postponed_opt K_process
process_sensitivity_list_opt K_is_opt
process_declarative_part_opt
K_begin sequence_of_statements
K_end K_postponed_opt K_process identifier_opt ';'
{ perm_string iname = lex_strings.make($1);
if ($12) {
if (iname != $12)
errormsg(@12, "Process name %s does not match opening name %s.\n",
$12, $1);
delete[]$12;
if ($13) {
if (iname != $13)
errormsg(@13, "Process name %s does not match opening name %s.\n",
$13, $1);
delete[]$13;
}
ProcessStatement*tmp = new ProcessStatement(iname, $5, $8);
ProcessStatement*tmp = new ProcessStatement(iname, $5, $9);
FILE_NAME(tmp, @4);
delete $5;
delete $8;
delete $9;
$$ = tmp;
}
| IDENTIFIER ':' K_postponed_opt K_process
process_sensitivity_list_opt K_is_opt
process_declarative_part_opt
K_begin error
K_end K_postponed_opt K_process identifier_opt ';'
{ errormsg(@8, "Too many errors in process sequential statements.\n");
@ -1498,10 +1523,16 @@ sequence_of_statements
sequential_statement
: if_statement { $$ = $1; }
| signal_assignment_statement { $$ = $1; }
| variable_assignment_statement { $$ = $1; }
| case_statement { $$ = $1; }
| procedure_call_statement { $$ = $1; }
| loop_statement { $$ = $1; }
| K_null ';' { $$ = 0; }
| error ';'
{ errormsg(@1, "Syntax error in sequential statement.\n");
$$ = 0;
yyerrok;
}
;
shift_expression : simple_expression { $$ = $1; } ;
@ -1646,6 +1677,14 @@ use_clauses_opt
|
;
variable_assignment_statement
: name VASSIGN expression ';'
{ VariableSeqAssignment*tmp = new VariableSeqAssignment($1, $3);
FILE_NAME(tmp, @1);
$$ = tmp;
}
;
waveform
: waveform_elements
{ $$ = $1; }

View File

@ -36,6 +36,11 @@ ScopeBase::ScopeBase(const ScopeBase&ref)
insert_iterator<map<perm_string, Signal*> >(
old_signals_, old_signals_.end())
);
merge(ref.old_variables_.begin(), ref.old_variables_.end(),
ref.new_variables_.begin(), ref.new_variables_.end(),
insert_iterator<map<perm_string, Variable*> >(
old_variables_, old_variables_.end())
);
merge(ref.old_components_.begin(), ref.old_components_.end(),
ref.new_components_.begin(), ref.new_components_.end(),
insert_iterator<map<perm_string, ComponentBase*> >(
@ -172,3 +177,17 @@ Signal* Scope::find_signal(perm_string by_name)
return cur->second;
}
}
Variable* Scope::find_variable(perm_string by_name)
{
map<perm_string,Variable*>::const_iterator cur = new_variables_.find(by_name);
if (cur == new_variables_.end()) {
cur = old_variables_.find(by_name);
if (cur == old_variables_.end())
return 0;
else
return cur->second;
} else {
return cur->second;
}
}

View File

@ -66,6 +66,9 @@ class ScopeBase {
// Signal declarations...
std::map<perm_string,Signal*> old_signals_; //previous scopes
std::map<perm_string,Signal*> new_signals_; //current scope
// Variable declarations...
std::map<perm_string,Variable*> old_variables_; //previous scopes
std::map<perm_string,Variable*> new_variables_; //current scope
// Component declarations...
std::map<perm_string,ComponentBase*> old_components_; //previous scopes
std::map<perm_string,ComponentBase*> new_components_; //current scope
@ -95,6 +98,7 @@ class Scope : public ScopeBase {
ComponentBase* find_component(perm_string by_name);
Signal* find_signal(perm_string by_name);
Variable* find_variable(perm_string by_name);
public:
void dump_scope(ostream&out) const;
@ -102,6 +106,7 @@ class Scope : public ScopeBase {
protected:
// Helper method for emitting signals in the scope.
int emit_signals(ostream&out, Entity*ent, Architecture*arc);
int emit_variables(ostream&out, Entity*ent, Architecture*arc);
};
/*
@ -134,6 +139,13 @@ class ActiveScope : public ScopeBase {
new_signals_[name] = obj;
}
void bind_name(perm_string name, Variable*obj)
{ map<perm_string, Variable*>::iterator it;
if((it = old_variables_.find(name)) != old_variables_.end() )
old_variables_.erase(it);
new_variables_[name] = obj;
}
void bind_name(perm_string name, ComponentBase*obj)
{ map<perm_string, ComponentBase*>::iterator it;
if((it = old_components_.find(name)) != old_components_.end() )

View File

@ -177,6 +177,17 @@ ForLoopStatement::~ForLoopStatement()
delete range_;
}
VariableSeqAssignment::VariableSeqAssignment(Expression*lval, Expression*rval)
: lval_(lval), rval_(rval)
{
}
VariableSeqAssignment::~VariableSeqAssignment()
{
delete lval_;
delete rval_;
}
WhileLoopStatement::WhileLoopStatement(ExpLogical* cond, list<SequentialStmt*>* stmts)
: LoopStatement(stmts), cond_(cond)
{

View File

@ -164,6 +164,21 @@ class LoopStatement : public SequentialStmt {
std::list<SequentialStmt*> stmts_;
};
class VariableSeqAssignment : public SequentialStmt {
public:
VariableSeqAssignment(Expression*sig, Expression*rval);
~VariableSeqAssignment();
public:
int elaborate(Entity*ent, Architecture*arc);
int emit(ostream&out, Entity*entity, Architecture*arc);
void dump(ostream&out, int indent) const;
private:
Expression*lval_;
Expression*rval_;
};
class WhileLoopStatement : public LoopStatement {
public:
WhileLoopStatement(ExpLogical*, list<SequentialStmt*>*);

View File

@ -125,6 +125,17 @@ void ForLoopStatement::dump(ostream&out, int indent) const
LoopStatement::dump(out, indent+2);
}
void VariableSeqAssignment::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "VariableSeqAssignment at file=" << get_fileline() << endl;
out << setw(indent+3) << "" << "l-value:" << endl;
lval_->dump(out, indent+4);
out << setw(indent+3) << "" << "r-value:" << endl;
rval_->dump(out, indent+4);
}
void WhileLoopStatement::dump(ostream&out, int indent) const
{
out << setw(indent) << "" << "WhileLoopStatement at file=" << get_fileline() << endl;

View File

@ -99,6 +99,28 @@ int ForLoopStatement::elaborate(Entity*, Architecture*)
return 0;
}
int VariableSeqAssignment::elaborate(Entity*ent, Architecture*arc)
{
int errors = 0;
// Elaborate the l-value expression.
errors += lval_->elaborate_lval(ent, arc, true);
// The elaborate_lval should have resolved the type of the
// l-value expression. We'll use that type to elaborate the
// r-value.
const VType*lval_type = lval_->peek_type();
if (lval_type == 0) {
if (errors == 0) errors += 1;
return errors;
}
// Elaborate the r-value expression.
errors += rval_->elaborate_expr(ent, arc, lval_type);
return errors;
}
int WhileLoopStatement::elaborate(Entity*, Architecture*)
{
//TODO:check whether there is any wait statement in the statements (there should be)

View File

@ -99,6 +99,19 @@ int SignalSeqAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
return errors;
}
int VariableSeqAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
{
int errors = 0;
errors += lval_->emit(out, ent, arc);
out << " = ";
rval_->emit(out, ent, arc);
out << ";" << endl;
return errors;
}
int ProcedureCall::emit(ostream&out, Entity*, Architecture*)
{
out << " // " << get_fileline() << ": internal error: "

View File

@ -23,24 +23,42 @@
using namespace std;
Signal::Signal(perm_string nam, const VType*typ)
SigVarBase::SigVarBase(perm_string nam, const VType*typ)
: name_(nam), type_(typ), refcnt_sequ_(0)
{
}
Signal::~Signal()
SigVarBase::~SigVarBase()
{
}
void SigVarBase::type_elaborate_(VType::decl_t&decl)
{
type_->elaborate(decl);
}
int Signal::emit(ostream&out, Entity*, Architecture*)
{
int errors = 0;
VType::decl_t decl;
type_->elaborate(decl);
if (refcnt_sequ_ > 0)
type_elaborate_(decl);
if (peek_refcnt_sequ_() > 0)
decl.reg_flag = true;
errors += decl.emit(out, name_);
errors += decl.emit(out, peek_name_());
out << ";" << endl;
return errors;
}
int Variable::emit(ostream&out, Entity*, Architecture*)
{
int errors = 0;
VType::decl_t decl;
type_elaborate_(decl);
if (peek_refcnt_sequ_() > 0)
decl.reg_flag = true;
errors += decl.emit(out, peek_name_());
out << ";" << endl;
return errors;
}

View File

@ -21,16 +21,16 @@
# include "StringHeap.h"
# include "LineInfo.h"
# include "vtype.h"
class Architecture;
class Entity;
class VType;
class Signal : public LineInfo {
class SigVarBase : public LineInfo {
public:
Signal(perm_string name, const VType*type);
~Signal();
SigVarBase(perm_string name, const VType*type);
virtual ~SigVarBase();
const VType* peek_type(void) const { return type_; }
@ -38,10 +38,14 @@ class Signal : public LineInfo {
// l-value of a sequential assignment.
void count_ref_sequ();
int emit(ostream&out, Entity*ent, Architecture*arc);
void dump(ostream&out, int indent = 0) const;
protected:
perm_string peek_name_() const { return name_; }
unsigned peek_refcnt_sequ_() const { return refcnt_sequ_; }
void type_elaborate_(VType::decl_t&decl);
private:
perm_string name_;
const VType*type_;
@ -49,13 +53,39 @@ class Signal : public LineInfo {
unsigned refcnt_sequ_;
private: // Not implemented
Signal(const Signal&);
Signal& operator = (const Signal&);
SigVarBase(const SigVarBase&);
SigVarBase& operator = (const SigVarBase&);
};
inline void Signal::count_ref_sequ()
class Signal : public SigVarBase {
public:
Signal(perm_string name, const VType*type);
int emit(ostream&out, Entity*ent, Architecture*arc);
};
class Variable : public SigVarBase {
public:
Variable(perm_string name, const VType*type);
int emit(ostream&out, Entity*ent, Architecture*arc);
};
inline void SigVarBase::count_ref_sequ()
{
refcnt_sequ_ += 1;
}
inline Signal::Signal(perm_string name, const VType*type)
: SigVarBase(name, type)
{
}
inline Variable::Variable(perm_string name, const VType*type)
: SigVarBase(name, type)
{
}
#endif