From cab974c0c2a28dfee53595fe08d43741a326cf86 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 12 Jun 2011 15:38:03 -0700 Subject: [PATCH] vhdl sequential l-values cause variables to be reg vs. net. When a signal (or port) is assigned by a sequential assignment, the signal or port becomes a reg, instead of a wire(net). Detect this distinction during elaboration and generate the correct signal/port declaration. --- vhdlpp/architec_elaborate.cc | 2 +- vhdlpp/expression.h | 7 ++++--- vhdlpp/expression_elaborate.cc | 15 ++++++++++----- vhdlpp/sequential_elaborate.cc | 2 +- vhdlpp/vsignal.cc | 4 +++- vhdlpp/vsignal.h | 11 +++++++++++ 6 files changed, 30 insertions(+), 11 deletions(-) diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index 0bc44a8b2..8a618b552 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -215,7 +215,7 @@ int SignalAssignment::elaborate(Entity*ent, Architecture*arc) int errors = 0; // Elaborate the l-value expression. - errors += lval_->elaborate_lval(ent, arc); + errors += lval_->elaborate_lval(ent, arc, false); // The elaborate_lval should have resolved the type of the // l-value expression. We'll use that type to elaborate the diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 654101608..40d352507 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -49,7 +49,8 @@ class Expression : public LineInfo { // assignment. This generates an error for most cases, but // expressions that are valid l-values return 0 and set any // flags needed to indicate their status as writable variables. - virtual int elaborate_lval(Entity*ent, Architecture*arc); + virtual int elaborate_lval(Entity*ent, Architecture*arc, + bool is_sequ); // This virtual method probes the expression to get the most // constrained type for the expression. For a given instance, @@ -319,7 +320,7 @@ class ExpName : public Expression { ~ExpName(); public: // Base methods - int elaborate_lval(Entity*ent, Architecture*arc); + int elaborate_lval(Entity*ent, Architecture*arc, bool); const VType* probe_type(Entity*ent, Architecture*arc) const; int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); int emit(ostream&out, Entity*ent, Architecture*arc); @@ -340,7 +341,7 @@ class ExpNameALL : public ExpName { ExpNameALL() : ExpName(perm_string()) { } public: - int elaborate_lval(Entity*ent, Architecture*arc); + int elaborate_lval(Entity*ent, Architecture*arc, bool); const VType* probe_type(Entity*ent, Architecture*arc) const; void dump(ostream&out, int indent =0) const; }; diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index feeb546c7..654702934 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -28,7 +28,7 @@ using namespace std; -int Expression::elaborate_lval(Entity*, Architecture*) +int Expression::elaborate_lval(Entity*, Architecture*, bool) { cerr << get_fileline() << ": error: Expression is not a valie l-value." << endl; return 1; @@ -39,7 +39,7 @@ const VType* Expression::probe_type(Entity*, Architecture*) const return 0; } -int ExpName::elaborate_lval(Entity*ent, Architecture*arc) +int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ) { int errors = 0; @@ -50,7 +50,9 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc) return errors += 1; } - ent->set_declaration_l_value(name_, true); + if (is_sequ) + ent->set_declaration_l_value(name_, is_sequ); + set_type(cur->type); return errors; } @@ -62,13 +64,16 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc) return errors + 1; } + // 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; } -int ExpNameALL::elaborate_lval(Entity*ent, Architecture*arc) +int ExpNameALL::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ) { - return Expression::elaborate_lval(ent, arc); + return Expression::elaborate_lval(ent, arc, is_sequ); } int Expression::elaborate_expr(Entity*, Architecture*, const VType*) diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index 6bc027f8f..4229bc91d 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -49,7 +49,7 @@ int SignalSeqAssignment::elaborate(Entity*ent, Architecture*arc) int errors = 0; // Elaborate the l-value expression. - errors += lval_->elaborate_lval(ent, arc); + 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 diff --git a/vhdlpp/vsignal.cc b/vhdlpp/vsignal.cc index c72211608..d280ce73a 100644 --- a/vhdlpp/vsignal.cc +++ b/vhdlpp/vsignal.cc @@ -24,7 +24,7 @@ using namespace std; Signal::Signal(perm_string nam, const VType*typ) -: name_(nam), type_(typ) +: name_(nam), type_(typ), refcnt_sequ_(0) { } @@ -38,6 +38,8 @@ int Signal::emit(ostream&out, Entity*, Architecture*) VType::decl_t decl; type_->elaborate(decl); + if (refcnt_sequ_ > 0) + decl.reg_flag = true; errors += decl.emit(out, name_); out << ";" << endl; return errors; diff --git a/vhdlpp/vsignal.h b/vhdlpp/vsignal.h index 8baf7a90f..abe21e689 100644 --- a/vhdlpp/vsignal.h +++ b/vhdlpp/vsignal.h @@ -34,6 +34,10 @@ class Signal : public LineInfo { const VType* peek_type(void) const { return type_; } + // Call this method for each occasion where this signal is the + // 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; @@ -42,9 +46,16 @@ class Signal : public LineInfo { perm_string name_; const VType*type_; + unsigned refcnt_sequ_; + private: // Not implemented Signal(const Signal&); Signal& operator = (const Signal&); }; +inline void Signal::count_ref_sequ() +{ + refcnt_sequ_ += 1; +} + #endif