From d6ff1946f978e4871884555030a3b1020cdb77e4 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 20 May 2015 18:53:29 +0200 Subject: [PATCH 1/7] vhdlpp: Support for time expressions. --- vhdlpp/expression.cc | 22 ++++++++++++++++++++++ vhdlpp/expression.h | 22 ++++++++++++++++++++++ vhdlpp/expression_debug.cc | 5 +++++ vhdlpp/expression_elaborate.cc | 7 +++++++ vhdlpp/expression_emit.cc | 16 ++++++++++++++++ vhdlpp/expression_evaluate.cc | 20 ++++++++++++++++++++ vhdlpp/expression_stream.cc | 14 ++++++++++++++ vhdlpp/lexor.lex | 1 + vhdlpp/library.cc | 3 +++ vhdlpp/parse.y | 26 ++++++++++++++++++++++++++ vhdlpp/vtype.cc | 3 +++ vhdlpp/vtype.h | 3 ++- vhdlpp/vtype_emit.cc | 3 +++ vhdlpp/vtype_stream.cc | 3 +++ 14 files changed, 147 insertions(+), 1 deletion(-) diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 949d568ae..7886618ee 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -564,3 +564,25 @@ ExpNew::~ExpNew() { delete size_; } + +ExpTime::ExpTime(uint64_t amount, timeunit_t unit) +: amount_(amount), unit_(unit) +{ +} + +double ExpTime::to_fs() const +{ + double val = amount_; + + switch(unit_) { + case FS: break; + case PS: val *= 1e3; break; + case NS: val *= 1e6; break; + case US: val *= 1e9; break; + case MS: val *= 1e12; break; + case S: val *= 1e15; break; + default: ivl_assert(*this, false); break; + } + + return val; +} diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 7d5f47ee6..717b1e116 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -838,4 +838,26 @@ class ExpNew : public Expression { Expression*size_; }; +class ExpTime : public Expression { + public: + typedef enum { FS, PS, NS, US, MS, S } timeunit_t; + + ExpTime(uint64_t amount, timeunit_t unit); + + Expression*clone() const { return new ExpTime(amount_, unit_); } + + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); + void write_to_stream(std::ostream&) const; + int emit(ostream&out, Entity*ent, ScopeBase*scope); + bool evaluate(ScopeBase*scope, int64_t&val) const; + bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const; + void dump(ostream&out, int indent = 0) const; + + private: + // Returns the time value expressed in femtoseconds + double to_fs() const; + uint64_t amount_; + timeunit_t unit_; +}; + #endif /* IVL_expression_H */ diff --git a/vhdlpp/expression_debug.cc b/vhdlpp/expression_debug.cc index 1a7b44e8c..fd52b6875 100644 --- a/vhdlpp/expression_debug.cc +++ b/vhdlpp/expression_debug.cc @@ -112,3 +112,8 @@ void ExpShift::dump(ostream&out, int indent) const dump_operands(out, indent+4); } +void ExpTime::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "Time "; + write_to_stream(out); +} diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 30985fa53..71cda7c97 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -1133,3 +1133,10 @@ int ExpUNot::elaborate_expr(Entity*, ScopeBase*, const VType*ltype) set_type(ltype); return 0; } + + +int ExpTime::elaborate_expr(Entity*, ScopeBase*, const VType*) +{ + set_type(&primitive_INTEGER); + return 0; +} diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index b0ccefc5e..e7263e406 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -1068,3 +1068,19 @@ int ExpNew::emit(ostream&out, Entity*ent, ScopeBase*scope) out << "]"; return errors; } + +int ExpTime::emit(ostream&out, Entity*, ScopeBase*) +{ + out << amount_; + + switch(unit_) { + case FS: out << "fs"; break; + case PS: out << "ps"; break; + case NS: out << "ns"; break; + case US: out << "us"; break; + case MS: out << "ms"; break; + case S: out << "s"; break; + } + + return 0; +} diff --git a/vhdlpp/expression_evaluate.cc b/vhdlpp/expression_evaluate.cc index 54bf704b4..2e26ba502 100644 --- a/vhdlpp/expression_evaluate.cc +++ b/vhdlpp/expression_evaluate.cc @@ -22,6 +22,7 @@ # include "expression.h" # include "architec.h" # include +# include bool Expression::evaluate(ScopeBase*, int64_t&) const { @@ -245,3 +246,22 @@ bool ExpShift::evaluate(ScopeBase*scope, int64_t&val) const return true; } + +bool ExpTime::evaluate(ScopeBase*, int64_t&val) const +{ + double v = to_fs(); + + if(v > std::numeric_limits::max()) { + val = std::numeric_limits::max(); + cerr << get_fileline() << ": sorry: Time value is higher than the " + << "handled limit, reduced to " << val << " fs." << endl; + } + + val = v; + return true; +} + +bool ExpTime::evaluate(Entity*, ScopeBase*, int64_t&val) const +{ + return evaluate(NULL, NULL, val); +} diff --git a/vhdlpp/expression_stream.cc b/vhdlpp/expression_stream.cc index c379795bf..1321a3740 100644 --- a/vhdlpp/expression_stream.cc +++ b/vhdlpp/expression_stream.cc @@ -297,3 +297,17 @@ void ExpCast::write_to_stream(ostream&fd) const // SystemVerilog, so no need to use it here base_->write_to_stream(fd); } + +void ExpTime::write_to_stream(ostream&fd) const +{ + fd << amount_; + + switch(unit_) { + case FS: fd << " fs"; break; + case PS: fd << " ps"; break; + case NS: fd << " ns"; break; + case US: fd << " us"; break; + case MS: fd << " ms"; break; + case S: fd << " s"; break; + } +} diff --git a/vhdlpp/lexor.lex b/vhdlpp/lexor.lex index c9dae5c51..1cbda23c9 100644 --- a/vhdlpp/lexor.lex +++ b/vhdlpp/lexor.lex @@ -84,6 +84,7 @@ exponent [eE][-+]?{integer} based_literal {integer}#{based_integer}(\.{based_integer})?#{exponent}? based_integer [0-9a-fA-F](_?[0-9a-fA-F])* +time {integer}{W}*([fFpPnNuUmM]?[sS]) %% [ \t\b\f\r] { ; } diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index fda670a34..b0594c38d 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -391,6 +391,7 @@ const VTypePrimitive primitive_NATURAL(VTypePrimitive::NATURAL); const VTypePrimitive primitive_REAL(VTypePrimitive::REAL); const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC, true); const VTypePrimitive primitive_CHARACTER(VTypePrimitive::CHARACTER); +const VTypePrimitive primitive_TIME(VTypePrimitive::TIME); static const VTypeArray primitive_BIT_VECTOR(&primitive_BIT, vector (1)); static const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector (1)); @@ -407,6 +408,7 @@ void generate_global_types(ActiveScope*res) res->use_name(perm_string::literal("bit_vector"),&primitive_BIT_VECTOR); res->use_name(perm_string::literal("string"), &primitive_STRING); res->use_name(perm_string::literal("natural"), &primitive_NATURAL); + res->use_name(perm_string::literal("time"), &primitive_TIME); } void emit_std_types(ostream&out) @@ -431,6 +433,7 @@ bool is_global_type(perm_string name) if (name == "natural") return true; if (name == "signed") return true; if (name == "unsigned") return true; + if (name == "time") return true; return false; } diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index c3a4e2ab9..7b3b4212b 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -1835,6 +1835,32 @@ primary delete[]$1; $$ = tmp; } + | INT_LITERAL IDENTIFIER + { ExpTime::timeunit_t unit = ExpTime::FS; + + if(!strcasecmp($2, "us")) + unit = ExpTime::US; + else if(!strcasecmp($2, "ms")) + unit = ExpTime::MS; + else if(!strcasecmp($2, "ns")) + unit = ExpTime::NS; + else if(!strcasecmp($2, "s")) + unit = ExpTime::S; + else if(!strcasecmp($2, "ps")) + unit = ExpTime::PS; + else if(!strcasecmp($2, "fs")) + unit = ExpTime::FS; + else + errormsg(@2, "Invalid time unit (accepted are fs, ps, ns, us, ms, s)."); + + if($1 < 0) + errormsg(@1, "Time cannot be negative."); + + ExpTime*tmp = new ExpTime($1, unit); + FILE_NAME(tmp, @1); + delete[] $2; + $$ = tmp; + } /*XXXX Caught up in element_association_list? | '(' expression ')' diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index ee43570e7..4dc97199a 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -76,6 +76,9 @@ void VTypePrimitive::show(ostream&out) const case STDLOGIC: out << "STD_LOGIC"; break; + case TIME: + out << "TIME"; + break; } } diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 62b528240..0756ff68b 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -156,7 +156,7 @@ class VTypeERROR : public VType { class VTypePrimitive : public VType { public: - enum type_t { BOOLEAN, BIT, INTEGER, NATURAL, REAL, STDLOGIC, CHARACTER }; + enum type_t { BOOLEAN, BIT, INTEGER, NATURAL, REAL, STDLOGIC, CHARACTER, TIME }; public: VTypePrimitive(type_t tt, bool packed = false); @@ -187,6 +187,7 @@ extern const VTypePrimitive primitive_NATURAL; extern const VTypePrimitive primitive_REAL; extern const VTypePrimitive primitive_STDLOGIC; extern const VTypePrimitive primitive_CHARACTER; +extern const VTypePrimitive primitive_TIME; /* * An array is a compound N-dimensional array of element type. The diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index b97d00d7e..cfb8f6390 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -169,6 +169,9 @@ int VTypePrimitive::emit_primitive_type(ostream&out) const case CHARACTER: out << "char"; break; + case TIME: + out << "time"; + break; default: assert(0); break; diff --git a/vhdlpp/vtype_stream.cc b/vhdlpp/vtype_stream.cc index 2cf159db8..9f8b6c689 100644 --- a/vhdlpp/vtype_stream.cc +++ b/vhdlpp/vtype_stream.cc @@ -168,6 +168,9 @@ void VTypePrimitive::write_to_stream(ostream&fd) const case BOOLEAN: fd << "boolean"; break; + case TIME: + fd << "time"; + break; default: assert(0); fd << "/* PRIMITIVE: " << type_ << " */"; From 68f8007fc4f60cc24ff5bd9add77fff79ae6bf48 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 22 May 2015 18:07:31 +0200 Subject: [PATCH 2/7] vhdlpp: 'wait for' statement. --- vhdlpp/parse.y | 11 ++++++++++- vhdlpp/sequential.cc | 5 +++++ vhdlpp/sequential.h | 13 +++++++++++++ vhdlpp/sequential_debug.cc | 7 +++++++ vhdlpp/sequential_elaborate.cc | 5 +++++ vhdlpp/sequential_emit.cc | 17 +++++++++++++++++ 6 files changed, 57 insertions(+), 1 deletion(-) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 7b3b4212b..b6a877438 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -359,7 +359,7 @@ static void touchup_interface_for_functions(std::list*ports) %type sequential_statement if_statement signal_assignment signal_assignment_statement %type case_statement procedure_call procedure_call_statement %type loop_statement variable_assignment variable_assignment_statement -%type assertion_statement report_statement return_statement +%type assertion_statement report_statement return_statement wait_for_statement %type range %type range_list index_constraint @@ -2201,6 +2201,7 @@ sequential_statement | return_statement { $$ = $1; } | report_statement { $$ = $1; } | assertion_statement { $$ = $1; } + | wait_for_statement { $$ = $1; } | K_null ';' { $$ = 0; } | error ';' { errormsg(@1, "Syntax error in sequential statement.\n"); @@ -2631,6 +2632,14 @@ variable_declaration /* IEEE 1076-2008 P6.4.2.4 */ } ; +wait_for_statement + : K_wait K_for expression ';' + { WaitForStmt*tmp = new WaitForStmt($3); + FILE_NAME(tmp, @1); + $$ = tmp; + } + ; + waveform : waveform_elements { $$ = $1; } diff --git a/vhdlpp/sequential.cc b/vhdlpp/sequential.cc index 95497a987..b6a4c1079 100644 --- a/vhdlpp/sequential.cc +++ b/vhdlpp/sequential.cc @@ -284,3 +284,8 @@ AssertStmt::AssertStmt(Expression*condition, const char*msg, ReportStmt::severit } const std::string AssertStmt::default_msg_ = std::string("Assertion violation."); + +WaitForStmt::WaitForStmt(Expression*delay) +: delay_(delay) +{ +} diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index d561b0559..ed7bb17a8 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -308,4 +308,17 @@ class AssertStmt : public ReportStmt { static const std::string default_msg_; }; +class WaitForStmt : public SequentialStmt { + public: + WaitForStmt(Expression*delay); + + void dump(ostream&out, int indent) const; + int elaborate(Entity*ent, ScopeBase*scope); + int emit(ostream&out, Entity*entity, ScopeBase*scope); + void write_to_stream(std::ostream&fd); + + private: + Expression*delay_; +}; + #endif /* IVL_sequential_H */ diff --git a/vhdlpp/sequential_debug.cc b/vhdlpp/sequential_debug.cc index 786fa5cc6..5c40b5012 100644 --- a/vhdlpp/sequential_debug.cc +++ b/vhdlpp/sequential_debug.cc @@ -180,3 +180,10 @@ void AssertStmt::dump(ostream&out, int indent) const cond_->dump(out, indent+3); ReportStmt::dump(out, indent+3); } + +void WaitForStmt::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "WaitForStmt at file=" << get_fileline() << endl; + out << setw(indent+3) << "" << "delay: "; + delay_->dump(out, indent+3); +} diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index 2c342030b..a0cfafe6d 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -197,3 +197,8 @@ int AssertStmt::elaborate(Entity*ent, ScopeBase*scope) { return cond_->elaborate_expr(ent, scope, 0); } + +int WaitForStmt::elaborate(Entity*ent, ScopeBase*scope) +{ + return delay_->elaborate_expr(ent, scope, 0); +} diff --git a/vhdlpp/sequential_emit.cc b/vhdlpp/sequential_emit.cc index 29f488b80..f0e6f0b5c 100644 --- a/vhdlpp/sequential_emit.cc +++ b/vhdlpp/sequential_emit.cc @@ -512,3 +512,20 @@ void AssertStmt::write_to_stream(std::ostream&fd) fd << std::endl; ReportStmt::write_to_stream(fd); } + +int WaitForStmt::emit(ostream&out, Entity*ent, ScopeBase*scope) +{ + int errors = 0; + + out << "#("; + errors += delay_->emit(out, ent, scope); + out << ")"; + + return errors; +} + +void WaitForStmt::write_to_stream(std::ostream&fd) +{ + fd << "wait for "; + delay_->write_to_stream(fd); +} From cd3180d1c29115c94b1306a23e8af9fd862b79fe Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 27 May 2015 13:48:30 +0200 Subject: [PATCH 3/7] ivl: TIME_LITERAL added as a primary expression. --- parse.y | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/parse.y b/parse.y index 787f409cb..f362d6505 100644 --- a/parse.y +++ b/parse.y @@ -3339,6 +3339,22 @@ expr_primary FILE_NAME(tmp, @1); $$ = tmp; } + | TIME_LITERAL + { int unit; + + based_size = 0; + $$ = 0; + if ($1 == 0 || !get_time_unit($1, unit)) + yyerror(@1, "internal error: delay."); + else { + double p = pow(10.0, (double)(unit - pform_get_timeunit())); + double time = atof($1) * p; + + verireal *v = new verireal(time); + $$ = new PEFNumber(v); + FILE_NAME($$, @1); + } + } | SYSTEM_IDENTIFIER { perm_string tn = lex_strings.make($1); PECallFunction*tmp = new PECallFunction(tn); From 80403d2ade171979f0edeebd9e39017a854ace9c Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 8 Jun 2015 18:42:17 +0200 Subject: [PATCH 4/7] ivl: Disabled reg_flag for time type in SV. --- parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parse.y b/parse.y index f362d6505..fe3eef5c3 100644 --- a/parse.y +++ b/parse.y @@ -1066,7 +1066,7 @@ data_type /* IEEE1800-2005: A.2.2.1 */ | K_time { list*pd = make_range_from_width(64); vector_type_t*tmp = new vector_type_t(IVL_VT_LOGIC, false, pd); - tmp->reg_flag = true; + tmp->reg_flag = !gn_system_verilog(); $$ = tmp; } | TYPE_IDENTIFIER dimensions_opt From 1f1d47887ed541fe89c90bb9c22c3b98a45c08d3 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 28 May 2015 17:51:18 +0200 Subject: [PATCH 5/7] vhdlpp: Visitor for Expression class. --- vhdlpp/expression.cc | 104 +++++++++++++++++++++++++++++++++++++++++++ vhdlpp/expression.h | 20 ++++++++- 2 files changed, 123 insertions(+), 1 deletion(-) diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 7886618ee..0e3a0b493 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -69,6 +69,12 @@ Expression*ExpAttribute::clone() const return new ExpAttribute(static_cast(base_->clone()), name_); } +void ExpAttribute::visit(ExprVisitor& func) +{ + base_->visit(func); + func(this); +} + ExpBinary::ExpBinary(Expression*op1, Expression*op2) : operand1_(op1), operand2_(op2) { @@ -90,6 +96,13 @@ bool ExpBinary::eval_operand2(ScopeBase*scope, int64_t&val) const return operand2_->evaluate(scope, val); } +void ExpBinary::visit(ExprVisitor& func) +{ + operand1_->visit(func); + operand2_->visit(func); + func(this); +} + ExpUnary::ExpUnary(Expression*op1) : operand1_(op1) { @@ -100,6 +113,12 @@ ExpUnary::~ExpUnary() delete operand1_; } +void ExpUnary::visit(ExprVisitor& func) +{ + operand1_->visit(func); + func(this); +} + ExpAggregate::ExpAggregate(std::list*el) : elements_(el? el->size() : 0) { @@ -135,6 +154,24 @@ Expression* ExpAggregate::clone() const return new ExpAggregate(new_elements); } +void ExpAggregate::visit(ExprVisitor& func) +{ + for(std::vector::iterator it = elements_.begin(); + it != elements_.end(); ++it) { + (*it)->extract_expression()->visit(func); + } + + for(std::vector::iterator it = aggregate_.begin(); + it != aggregate_.end(); ++it) { + if(Expression*choice_expr = it->choice->simple_expression(false)) + choice_expr->visit(func); + + it->expr->visit(func); + } + + func(this); +} + ExpAggregate::choice_t::choice_t(Expression*exp) : expr_(exp) { @@ -256,6 +293,13 @@ ExpConcat::~ExpConcat() delete operand2_; } +void ExpConcat::visit(ExprVisitor& func) +{ + operand1_->visit(func); + operand2_->visit(func); + func(this); +} + ExpConditional::ExpConditional(Expression*co, list*tru, list*fal) : cond_(co) @@ -304,6 +348,30 @@ Expression*ExpConditional::clone() const return new ExpConditional(cond_->clone(), new_true_clause, new_else_clause); } +void ExpConditional::visit(ExprVisitor& func) +{ + if(!true_clause_.empty()) { + for(std::list::iterator it = true_clause_.begin(); + it != true_clause_.end(); ++it) { + (*it)->visit(func); + } + } + + if(!else_clause_.empty()) { + for(std::list::iterator it = else_clause_.begin(); + it != else_clause_.end(); ++it) { + std::list& else_clause = (*it)->extract_true_clause(); + + for(std::list::iterator jt = else_clause.begin(); + jt != else_clause.end(); ++jt) { + (*jt)->visit(func); + } + } + } + + func(this); +} + ExpConditional::else_t::else_t(Expression*cond, std::list*tru) : cond_(cond) { @@ -378,6 +446,16 @@ Expression*ExpFunc::clone() const { return f; } +void ExpFunc::visit(ExprVisitor& func) { + if(!argv_.empty()) { + for(std::vector::iterator it = argv_.begin(); + it != argv_.end(); ++it) + (*it)->visit(func); + } + + func(this); +} + const VType* ExpFunc::func_ret_type() const { return def_ ? def_->peek_return_type() : NULL; @@ -481,6 +559,20 @@ void ExpName::set_range(Expression*msb, Expression*lsb) lsb_ = lsb; } +void ExpName::visit(ExprVisitor& func) +{ + if(prefix_.get()) + prefix_.get()->visit(func); + + if(index_) + index_->visit(func); + + if(lsb_) + lsb_->visit(func); + + func(this); +} + int ExpName::index_t::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; @@ -555,6 +647,12 @@ ExpCast::~ExpCast() { } +void ExpCast::visit(ExprVisitor& func) +{ + base_->visit(func); + func(this); +} + ExpNew::ExpNew(Expression*size) : size_(size) { @@ -565,6 +663,12 @@ ExpNew::~ExpNew() delete size_; } +void ExpNew::visit(ExprVisitor& func) +{ + size_->visit(func); + func(this); +} + ExpTime::ExpTime(uint64_t amount, timeunit_t unit) : amount_(amount), unit_(unit) { diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 717b1e116..479d207d5 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -38,6 +38,11 @@ class VTypeArray; class VTypePrimitive; class ExpName; +struct ExprVisitor { + virtual ~ExprVisitor() {}; + virtual void operator() (Expression*s) = 0; +}; + /* * The Expression class represents parsed expressions from the parsed * VHDL input. The Expression class is a virtual class that holds more @@ -120,6 +125,9 @@ class Expression : public LineInfo { virtual void dump(ostream&out, int indent = 0) const =0; virtual ostream& dump_inline(ostream&out) const; + // Recursively visits a tree of expressions (useful of complex expressions). + virtual void visit(ExprVisitor& func) { func(this); } + protected: // This function is called by the derived class during // elaboration to set the type of the current expression that @@ -160,6 +168,7 @@ class ExpUnary : public Expression { inline const Expression*peek_operand() const { return operand1_; } const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; + void visit(ExprVisitor& func); protected: inline void write_to_stream_operand1(std::ostream&fd) const @@ -186,6 +195,7 @@ class ExpBinary : public Expression { inline const Expression* peek_operand2(void) const { return operand2_; } const VType*probe_type(Entity*ent, ScopeBase*scope) const; + void visit(ExprVisitor& func); protected: @@ -299,6 +309,7 @@ class ExpAggregate : public Expression { void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: int elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype); @@ -360,6 +371,7 @@ class ExpAttribute : public Expression { bool evaluate(ScopeBase*scope, int64_t&val) const; bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const; void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: ExpName*base_; @@ -430,6 +442,7 @@ class ExpConcat : public Expression { virtual bool evaluate(ScopeBase*scope, int64_t&val) const; bool is_primary(void) const; void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: int elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype); @@ -457,6 +470,7 @@ class ExpConditional : public Expression { int emit_when_else(ostream&out, Entity*ent, ScopeBase*scope); int emit_else(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + std::list& extract_true_clause() { return true_clause_; } private: Expression*cond_; @@ -475,6 +489,7 @@ class ExpConditional : public Expression { void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: Expression*cond_; @@ -528,6 +543,7 @@ class ExpFunc : public Expression { void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); // NOTE: does not handle expressions in subprogram private: perm_string name_; @@ -638,8 +654,8 @@ class ExpName : public Expression { void dump(ostream&out, int indent = 0) const; inline const char* name() const { return name_; } inline const perm_string& peek_name() const { return name_; } - void set_range(Expression*msb, Expression*lsb); + void visit(ExprVisitor& func); private: class index_t { @@ -811,6 +827,7 @@ class ExpCast : public Expression { void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: Expression*base_; @@ -833,6 +850,7 @@ class ExpNew : public Expression { void write_to_stream(std::ostream&) const {}; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: Expression*size_; From 4a31f36646c695f18689004da0efd406810e91f1 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 29 May 2015 10:51:17 +0200 Subject: [PATCH 6/7] vhdlpp: Minor code cleaning. --- vhdlpp/architec_elaborate.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index 9ab09bfa8..327457ef1 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -338,10 +338,7 @@ int ProcessStatement::elaborate(Entity*ent, Architecture*arc) int errors = 0; if (rewrite_as_always_edge_(ent, arc) >= 0) { - - } else if (extract_anyedge_(ent, arc) >= 0) { - - } else { + extract_anyedge_(ent, arc); } for (list::iterator cur = statements_list_.begin() From 29ddd5208fce6a113e05173cfb838293f4216e0a Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 29 May 2015 10:54:29 +0200 Subject: [PATCH 7/7] vhdlpp: 'wait on' and 'wait until' statements. --- vhdlpp/parse.y | 16 +++++++++--- vhdlpp/sequential.cc | 5 ++++ vhdlpp/sequential.h | 20 ++++++++++++-- vhdlpp/sequential_debug.cc | 7 +++++ vhdlpp/sequential_elaborate.cc | 24 +++++++++++++++++ vhdlpp/sequential_emit.cc | 48 ++++++++++++++++++++++++++++++++++ 6 files changed, 115 insertions(+), 5 deletions(-) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index b6a877438..f75cd19e2 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -359,7 +359,7 @@ static void touchup_interface_for_functions(std::list*ports) %type sequential_statement if_statement signal_assignment signal_assignment_statement %type case_statement procedure_call procedure_call_statement %type loop_statement variable_assignment variable_assignment_statement -%type assertion_statement report_statement return_statement wait_for_statement +%type assertion_statement report_statement return_statement wait_statement %type range %type range_list index_constraint @@ -2201,7 +2201,7 @@ sequential_statement | return_statement { $$ = $1; } | report_statement { $$ = $1; } | assertion_statement { $$ = $1; } - | wait_for_statement { $$ = $1; } + | wait_statement { $$ = $1; } | K_null ';' { $$ = 0; } | error ';' { errormsg(@1, "Syntax error in sequential statement.\n"); @@ -2632,12 +2632,22 @@ variable_declaration /* IEEE 1076-2008 P6.4.2.4 */ } ; -wait_for_statement +wait_statement : K_wait K_for expression ';' { WaitForStmt*tmp = new WaitForStmt($3); FILE_NAME(tmp, @1); $$ = tmp; } + | K_wait K_on expression ';' + { WaitStmt*tmp = new WaitStmt(WaitStmt::ON, $3); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | K_wait K_until expression ';' + { WaitStmt*tmp = new WaitStmt(WaitStmt::UNTIL, $3); + FILE_NAME(tmp, @1); + $$ = tmp; + } ; waveform diff --git a/vhdlpp/sequential.cc b/vhdlpp/sequential.cc index b6a4c1079..0f793b713 100644 --- a/vhdlpp/sequential.cc +++ b/vhdlpp/sequential.cc @@ -289,3 +289,8 @@ WaitForStmt::WaitForStmt(Expression*delay) : delay_(delay) { } + +WaitStmt::WaitStmt(wait_type_t type, Expression*expr) +: type_(type), expr_(expr) +{ +} diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index ed7bb17a8..eba398cef 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -22,8 +22,7 @@ # include "LineInfo.h" # include "parse_types.h" -# include -# include +# include class ScopeBase; class Entity; @@ -321,4 +320,21 @@ class WaitForStmt : public SequentialStmt { Expression*delay_; }; +class WaitStmt : public SequentialStmt { + public: + typedef enum { ON, UNTIL } wait_type_t; + WaitStmt(wait_type_t type, Expression*expression); + + void dump(ostream&out, int indent) const; + int elaborate(Entity*ent, ScopeBase*scope); + int emit(ostream&out, Entity*entity, ScopeBase*scope); + void write_to_stream(std::ostream&fd); + + private: + wait_type_t type_; + Expression*expr_; + // Sensitivity list for 'wait until' statement + std::set sens_list_; +}; + #endif /* IVL_sequential_H */ diff --git a/vhdlpp/sequential_debug.cc b/vhdlpp/sequential_debug.cc index 5c40b5012..149021440 100644 --- a/vhdlpp/sequential_debug.cc +++ b/vhdlpp/sequential_debug.cc @@ -187,3 +187,10 @@ void WaitForStmt::dump(ostream&out, int indent) const out << setw(indent+3) << "" << "delay: "; delay_->dump(out, indent+3); } + +void WaitStmt::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "WaitStmt at file=" << get_fileline() << endl; + out << setw(indent+3) << "" << "expression: "; + expr_->dump(out, indent+3); +} diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index a0cfafe6d..80e7b2584 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -19,6 +19,7 @@ # include "sequential.h" # include "expression.h" +# include "scope.h" int SequentialStmt::elaborate(Entity*, ScopeBase*) { @@ -202,3 +203,26 @@ int WaitForStmt::elaborate(Entity*ent, ScopeBase*scope) { return delay_->elaborate_expr(ent, scope, 0); } + +int WaitStmt::elaborate(Entity*ent, ScopeBase*scope) +{ + if(type_ == UNTIL) { + struct fill_sens_list_t : public ExprVisitor { + fill_sens_list_t(set& sig_list) + : sig_list_(sig_list) {}; + + void operator() (Expression*s) { + if(ExpName*name = dynamic_cast(s)) + sig_list_.insert(name); + } + + private: + set& sig_list_; + } fill_sens_list(sens_list_); + + // Fill the sensitivity list + expr_->visit(fill_sens_list); + } + + return expr_->elaborate_expr(ent, scope, 0); +} diff --git a/vhdlpp/sequential_emit.cc b/vhdlpp/sequential_emit.cc index f0e6f0b5c..619c0f5e5 100644 --- a/vhdlpp/sequential_emit.cc +++ b/vhdlpp/sequential_emit.cc @@ -529,3 +529,51 @@ void WaitForStmt::write_to_stream(std::ostream&fd) fd << "wait for "; delay_->write_to_stream(fd); } + +int WaitStmt::emit(ostream&out, Entity*ent, ScopeBase*scope) +{ + int errors = 0; + + switch(type_) { + case ON: + out << "@("; + break; + + case UNTIL: + if(!sens_list_.empty()) { + out << "@("; + for(std::set::iterator it = sens_list_.begin(); + it != sens_list_.end(); ++it) { + if(it != sens_list_.begin()) + out << ","; + + (*it)->emit(out, ent, scope); + } + + out << ");"; + } + + out << "wait("; + break; + } + + errors += expr_->emit(out, ent, scope); + out << ");" << endl; + + return errors; +} + +void WaitStmt::write_to_stream(std::ostream&fd) +{ + switch(type_) { + case ON: + fd << "wait on "; + break; + + case UNTIL: + fd << "wait until "; + break; + } + + expr_->write_to_stream(fd); +}