commit
6a73de0c43
18
parse.y
18
parse.y
|
|
@ -1066,7 +1066,7 @@ data_type /* IEEE1800-2005: A.2.2.1 */
|
|||
| K_time
|
||||
{ list<pform_range_t>*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
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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<SequentialStmt*>::iterator cur = statements_list_.begin()
|
||||
|
|
|
|||
|
|
@ -69,6 +69,12 @@ Expression*ExpAttribute::clone() const
|
|||
return new ExpAttribute(static_cast<ExpName*>(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<element_t*>*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<element_t*>::iterator it = elements_.begin();
|
||||
it != elements_.end(); ++it) {
|
||||
(*it)->extract_expression()->visit(func);
|
||||
}
|
||||
|
||||
for(std::vector<choice_element>::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<Expression*>*tru,
|
||||
list<ExpConditional::else_t*>*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<Expression*>::iterator it = true_clause_.begin();
|
||||
it != true_clause_.end(); ++it) {
|
||||
(*it)->visit(func);
|
||||
}
|
||||
}
|
||||
|
||||
if(!else_clause_.empty()) {
|
||||
for(std::list<else_t*>::iterator it = else_clause_.begin();
|
||||
it != else_clause_.end(); ++it) {
|
||||
std::list<Expression*>& else_clause = (*it)->extract_true_clause();
|
||||
|
||||
for(std::list<Expression*>::iterator jt = else_clause.begin();
|
||||
jt != else_clause.end(); ++jt) {
|
||||
(*jt)->visit(func);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func(this);
|
||||
}
|
||||
|
||||
ExpConditional::else_t::else_t(Expression*cond, std::list<Expression*>*tru)
|
||||
: cond_(cond)
|
||||
{
|
||||
|
|
@ -378,6 +446,16 @@ Expression*ExpFunc::clone() const {
|
|||
return f;
|
||||
}
|
||||
|
||||
void ExpFunc::visit(ExprVisitor& func) {
|
||||
if(!argv_.empty()) {
|
||||
for(std::vector<Expression*>::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)
|
||||
{
|
||||
|
|
@ -564,3 +662,31 @@ 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)
|
||||
{
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<Expression*>& 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,9 +850,32 @@ 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_;
|
||||
};
|
||||
|
||||
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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@
|
|||
# include "expression.h"
|
||||
# include "architec.h"
|
||||
# include <ivl_assert.h>
|
||||
# include <limits>
|
||||
|
||||
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<int64_t>::max()) {
|
||||
val = std::numeric_limits<int64_t>::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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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] { ; }
|
||||
|
|
|
|||
|
|
@ -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<VTypeArray::range_t> (1));
|
||||
static const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector<VTypeArray::range_t> (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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
|||
%type <sequ> sequential_statement if_statement signal_assignment signal_assignment_statement
|
||||
%type <sequ> case_statement procedure_call procedure_call_statement
|
||||
%type <sequ> loop_statement variable_assignment variable_assignment_statement
|
||||
%type <sequ> assertion_statement report_statement return_statement
|
||||
%type <sequ> assertion_statement report_statement return_statement wait_statement
|
||||
|
||||
%type <range> range
|
||||
%type <range_list> range_list index_constraint
|
||||
|
|
@ -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 ')'
|
||||
|
|
@ -2175,6 +2201,7 @@ sequential_statement
|
|||
| return_statement { $$ = $1; }
|
||||
| report_statement { $$ = $1; }
|
||||
| assertion_statement { $$ = $1; }
|
||||
| wait_statement { $$ = $1; }
|
||||
| K_null ';' { $$ = 0; }
|
||||
| error ';'
|
||||
{ errormsg(@1, "Syntax error in sequential statement.\n");
|
||||
|
|
@ -2605,6 +2632,24 @@ variable_declaration /* IEEE 1076-2008 P6.4.2.4 */
|
|||
}
|
||||
;
|
||||
|
||||
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
|
||||
: waveform_elements
|
||||
{ $$ = $1; }
|
||||
|
|
|
|||
|
|
@ -284,3 +284,13 @@ 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)
|
||||
{
|
||||
}
|
||||
|
||||
WaitStmt::WaitStmt(wait_type_t type, Expression*expr)
|
||||
: type_(type), expr_(expr)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,7 @@
|
|||
|
||||
# include "LineInfo.h"
|
||||
# include "parse_types.h"
|
||||
# include <list>
|
||||
# include <functional>
|
||||
# include <set>
|
||||
|
||||
class ScopeBase;
|
||||
class Entity;
|
||||
|
|
@ -308,4 +307,34 @@ 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_;
|
||||
};
|
||||
|
||||
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<ExpName*> sens_list_;
|
||||
};
|
||||
|
||||
#endif /* IVL_sequential_H */
|
||||
|
|
|
|||
|
|
@ -180,3 +180,17 @@ 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
# include "sequential.h"
|
||||
# include "expression.h"
|
||||
# include "scope.h"
|
||||
|
||||
int SequentialStmt::elaborate(Entity*, ScopeBase*)
|
||||
{
|
||||
|
|
@ -197,3 +198,31 @@ 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);
|
||||
}
|
||||
|
||||
int WaitStmt::elaborate(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
if(type_ == UNTIL) {
|
||||
struct fill_sens_list_t : public ExprVisitor {
|
||||
fill_sens_list_t(set<ExpName*>& sig_list)
|
||||
: sig_list_(sig_list) {};
|
||||
|
||||
void operator() (Expression*s) {
|
||||
if(ExpName*name = dynamic_cast<ExpName*>(s))
|
||||
sig_list_.insert(name);
|
||||
}
|
||||
|
||||
private:
|
||||
set<ExpName*>& sig_list_;
|
||||
} fill_sens_list(sens_list_);
|
||||
|
||||
// Fill the sensitivity list
|
||||
expr_->visit(fill_sens_list);
|
||||
}
|
||||
|
||||
return expr_->elaborate_expr(ent, scope, 0);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -512,3 +512,68 @@ 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);
|
||||
}
|
||||
|
||||
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<ExpName*>::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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -76,6 +76,9 @@ void VTypePrimitive::show(ostream&out) const
|
|||
case STDLOGIC:
|
||||
out << "STD_LOGIC";
|
||||
break;
|
||||
case TIME:
|
||||
out << "TIME";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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_ << " */";
|
||||
|
|
|
|||
Loading…
Reference in New Issue