diff --git a/vhdlpp/debug.cc b/vhdlpp/debug.cc index 0ef95667e..e75835599 100644 --- a/vhdlpp/debug.cc +++ b/vhdlpp/debug.cc @@ -145,13 +145,19 @@ void ExpArithmetic::dump(ostream&out, int indent) const out << setw(indent) << "" << "Arithmetic " << fun_name << " at " << get_fileline() << endl; - operand1()->dump(out, indent+4); - operand2()->dump(out, indent+4); + dump_operands(out, indent+4); +} + +void ExpBinary::dump_operands(ostream&out, int indent) const +{ + operand1_->dump(out, indent); + operand2_->dump(out, indent); } void ExpInteger::dump(ostream&out, int indent) const { - out << setw(indent) << "" << "Integer" << endl; + out << setw(indent) << "" << "Integer " << value_ + << " at " << get_fileline() << endl; } void ExpLogical::dump(ostream&out, int indent) const @@ -180,8 +186,7 @@ void ExpLogical::dump(ostream&out, int indent) const out << setw(indent) << "" << "Logical " << fun_name << " at " << get_fileline() << endl; - operand1()->dump(out, indent+4); - operand2()->dump(out, indent+4); + dump_operands(out, indent+4); } void ExpName::dump(ostream&out, int indent) const @@ -189,3 +194,20 @@ void ExpName::dump(ostream&out, int indent) const out << setw(indent) << "" << "ExpName(\"" << name_ << "\")" << " at " << get_fileline() << endl; } + +void ExpUAbs::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "abs() at " << get_fileline() << endl; + dump_operand1(out, indent+4); +} + +void ExpUnary::dump_operand1(ostream&out, int indent) const +{ + operand1_->dump(out, indent); +} + +void ExpUNot::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "not() at " << get_fileline() << endl; + dump_operand1(out, indent+4); +} diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 3021cd833..823b52fff 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -43,6 +43,16 @@ ExpBinary::~ExpBinary() delete operand2_; } +ExpUnary::ExpUnary(Expression*op1) +: operand1_(op1) +{ +} + +ExpUnary::~ExpUnary() +{ + delete operand1_; +} + ExpArithmetic::ExpArithmetic(ExpArithmetic::fun_t op, Expression*op1, Expression*op2) : ExpBinary(op1, op2), fun_(op) { @@ -84,3 +94,21 @@ ExpName::ExpName(perm_string nn) ExpName::~ExpName() { } + +ExpUAbs::ExpUAbs(Expression*op1) +: ExpUnary(op1) +{ +} + +ExpUAbs::~ExpUAbs() +{ +} + +ExpUNot::ExpUNot(Expression*op1) +: ExpUnary(op1) +{ +} + +ExpUNot::~ExpUNot() +{ +} diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 2b7f197f9..ec540acd0 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -48,6 +48,13 @@ class Expression : public LineInfo { // cannot be done. virtual bool evaluate(int64_t&val) const; + // This method returns true if the drawn Verilog for this + // expression is a primary. A containing expressin can use + // this method to know if it needs to wrap parentheses. This + // is somewhile optional, so it is better to return false if + // not certain. The default implementation does return false. + virtual bool is_primary(void) const; + // Debug dump of the expression. virtual void dump(ostream&out, int indent) const =0; @@ -58,6 +65,20 @@ class Expression : public LineInfo { Expression& operator = (const Expression&); }; +class ExpUnary : public Expression { + + public: + ExpUnary(Expression*op1); + ~ExpUnary(); + + protected: + int emit_operand1(ostream&out, Entity*ent, Architecture*arc); + void dump_operand1(ostream&out, int indent) const; + + private: + Expression*operand1_; +}; + /* * This is an abstract class that collects some of the common features * of binary operators. @@ -69,10 +90,11 @@ class ExpBinary : public Expression { ~ExpBinary(); protected: - inline Expression* operand1() { return operand1_; } - inline Expression* operand2() { return operand2_; } - inline const Expression* operand1() const { return operand1_; } - inline const Expression* operand2() const { return operand2_; } + + int emit_operand1(ostream&out, Entity*ent, Architecture*arc); + int emit_operand2(ostream&out, Entity*ent, Architecture*arc); + + void dump_operands(ostream&out, int indent) const; private: Expression*operand1_; @@ -102,6 +124,7 @@ class ExpInteger : public Expression { ~ExpInteger(); int emit(ostream&out, Entity*ent, Architecture*arc); + bool is_primary(void) const; bool evaluate(int64_t&val) const; void dump(ostream&out, int indent) const; @@ -136,11 +159,31 @@ class ExpName : public Expression { ~ExpName(); int emit(ostream&out, Entity*ent, Architecture*arc); + bool is_primary(void) const; void dump(ostream&out, int indent) const; private: perm_string name_; }; +class ExpUAbs : public ExpUnary { + + public: + ExpUAbs(Expression*op1); + ~ExpUAbs(); + + int emit(ostream&out, Entity*ent, Architecture*arc); + void dump(ostream&out, int indent) const; +}; + +class ExpUNot : public ExpUnary { + + public: + ExpUNot(Expression*op1); + ~ExpUNot(); + + int emit(ostream&out, Entity*ent, Architecture*arc); + void dump(ostream&out, int indent) const; +}; #endif diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 0099fd163..9555a0941 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -31,11 +31,43 @@ int Expression::emit(ostream&out, Entity*, Architecture*) return 1; } +bool Expression::is_primary(void) const +{ + return false; +} + +int ExpBinary::emit_operand1(ostream&out, Entity*ent, Architecture*arc) +{ + int errors = 0; + bool oper_primary = operand1_->is_primary(); + if (! oper_primary) out << "("; + errors += operand1_->emit(out, ent, arc); + if (! oper_primary) out << ")"; + return errors; +} + +int ExpBinary::emit_operand2(ostream&out, Entity*ent, Architecture*arc) +{ + int errors = 0; + bool oper_primary = operand2_->is_primary(); + if (! oper_primary) out << "("; + errors += operand2_->emit(out, ent, arc); + if (! oper_primary) out << ")"; + return errors; +} + +int ExpUnary::emit_operand1(ostream&out, Entity*ent, Architecture*arc) +{ + int errors = 0; + errors += operand1_->emit(out, ent, arc); + return errors; +} + int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc) { int errors = 0; - errors += operand1()->emit(out, ent, arc); + errors += emit_operand1(out, ent, arc); switch (fun_) { case PLUS: @@ -61,23 +93,27 @@ int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc) break; } - errors += operand2()->emit(out, ent, arc); + errors += emit_operand2(out, ent, arc); return errors; } int ExpInteger::emit(ostream&out, Entity*, Architecture*) { - out << " /* " << get_fileline() << ": internal error: " - << "INTEGER LITERAL */ "; - return 1; + out << value_; + return 0; +} + +bool ExpInteger::is_primary(void) const +{ + return true; } int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc) { int errors = 0; - errors += operand1()->emit(out, ent, arc); + errors += emit_operand1(out, ent, arc); switch (fun_) { case AND: @@ -100,7 +136,7 @@ int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc) break; } - errors += operand2()->emit(out, ent, arc); + errors += emit_operand2(out, ent, arc); return errors; } @@ -112,3 +148,26 @@ int ExpName::emit(ostream&out, Entity*, Architecture*) out << name_; return errors; } + +bool ExpName::is_primary(void) const +{ + return true; +} + +int ExpUAbs::emit(ostream&out, Entity*ent, Architecture*arc) +{ + int errors = 0; + out << "abs("; + errors += emit_operand1(out, ent, arc); + out << ")"; + return errors; +} + +int ExpUNot::emit(ostream&out, Entity*ent, Architecture*arc) +{ + int errors = 0; + out << "~("; + errors += emit_operand1(out, ent, arc); + out << ")"; + return errors; +} diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 079ba521a..5dd1a49f6 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -294,6 +294,16 @@ factor FILE_NAME(tmp, @2); $$ = tmp; } + | K_abs primary + { ExpUAbs*tmp = new ExpUAbs($2); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | K_not primary + { ExpUNot*tmp = new ExpUNot($2); + FILE_NAME(tmp, @1); + $$ = tmp; + } ; identifier_opt : IDENTIFIER { $$ = $1; } | { $$ = 0; } ; @@ -384,6 +394,8 @@ primary FILE_NAME(tmp, @1); $$ = tmp; } + | '(' expression ')' + { $$ = $2; } ; relation : shift_expression { $$ = $1; } ;