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:
parent
51b1d57f19
commit
f5220c54f1
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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; }
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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() )
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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*>*);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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: "
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in New Issue