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_ << " */";