From f5220c54f1cffacb1f0eecc707ef74c9876e4dc4 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 17 Aug 2011 20:19:15 -0700 Subject: [PATCH] Handle variables in process statements Parse variables declared in the declaration section of process statements, and support variable assignment statements. --- vhdlpp/architec_emit.cc | 18 +++++++++++ vhdlpp/debug.cc | 4 +-- vhdlpp/expression_elaborate.cc | 25 ++++++++++------ vhdlpp/parse.y | 55 +++++++++++++++++++++++++++++----- vhdlpp/scope.cc | 19 ++++++++++++ vhdlpp/scope.h | 12 ++++++++ vhdlpp/sequential.cc | 11 +++++++ vhdlpp/sequential.h | 15 ++++++++++ vhdlpp/sequential_debug.cc | 11 +++++++ vhdlpp/sequential_elaborate.cc | 22 ++++++++++++++ vhdlpp/sequential_emit.cc | 13 ++++++++ vhdlpp/vsignal.cc | 28 +++++++++++++---- vhdlpp/vsignal.h | 48 +++++++++++++++++++++++------ 13 files changed, 248 insertions(+), 33 deletions(-) diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index 2338bb312..fb08367cc 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -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::iterator cur = old_variables_.begin() + ; cur != old_variables_.end() ; ++cur) { + + errors += cur->second->emit(out, entity, arc); + } + for (map::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::iterator cur = statements_.begin() ; cur != statements_.end() ; ++cur) { diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 165d89670..89714035c 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -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 diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 2e73b56e5..828bbfc7f 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -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) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index d2cdee2c9..faf8a8fce 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -255,7 +255,7 @@ const VType*parse_type_by_name(perm_string name) %type sequence_of_statements if_statement_else %type sequential_statement if_statement signal_assignment_statement %type case_statement procedure_call procedure_call_statement -%type loop_statement +%type loop_statement variable_assignment_statement %type 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::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; } diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index 6c27d0ed9..c7f09d054 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -36,6 +36,11 @@ ScopeBase::ScopeBase(const ScopeBase&ref) insert_iterator >( old_signals_, old_signals_.end()) ); + merge(ref.old_variables_.begin(), ref.old_variables_.end(), + ref.new_variables_.begin(), ref.new_variables_.end(), + insert_iterator >( + old_variables_, old_variables_.end()) + ); merge(ref.old_components_.begin(), ref.old_components_.end(), ref.new_components_.begin(), ref.new_components_.end(), insert_iterator >( @@ -172,3 +177,17 @@ Signal* Scope::find_signal(perm_string by_name) return cur->second; } } + +Variable* Scope::find_variable(perm_string by_name) +{ + map::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; + } +} diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index 4d573948a..a374e72c6 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -66,6 +66,9 @@ class ScopeBase { // Signal declarations... std::map old_signals_; //previous scopes std::map new_signals_; //current scope + // Variable declarations... + std::map old_variables_; //previous scopes + std::map new_variables_; //current scope // Component declarations... std::map old_components_; //previous scopes std::map 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::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::iterator it; if((it = old_components_.find(name)) != old_components_.end() ) diff --git a/vhdlpp/sequential.cc b/vhdlpp/sequential.cc index e3c160679..4179558c6 100644 --- a/vhdlpp/sequential.cc +++ b/vhdlpp/sequential.cc @@ -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* stmts) : LoopStatement(stmts), cond_(cond) { diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index 8c187e9f8..3fbe2e42b 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -164,6 +164,21 @@ class LoopStatement : public SequentialStmt { std::list 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*); diff --git a/vhdlpp/sequential_debug.cc b/vhdlpp/sequential_debug.cc index 688497aa0..c58ce2ddf 100644 --- a/vhdlpp/sequential_debug.cc +++ b/vhdlpp/sequential_debug.cc @@ -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; diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index 8bc093732..300eaca1f 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -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) diff --git a/vhdlpp/sequential_emit.cc b/vhdlpp/sequential_emit.cc index 5a5f3d1a9..6deee0de5 100644 --- a/vhdlpp/sequential_emit.cc +++ b/vhdlpp/sequential_emit.cc @@ -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: " diff --git a/vhdlpp/vsignal.cc b/vhdlpp/vsignal.cc index d280ce73a..4e1367ceb 100644 --- a/vhdlpp/vsignal.cc +++ b/vhdlpp/vsignal.cc @@ -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; } diff --git a/vhdlpp/vsignal.h b/vhdlpp/vsignal.h index abe21e689..76d3167cb 100644 --- a/vhdlpp/vsignal.h +++ b/vhdlpp/vsignal.h @@ -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