Add support for unary abs and not operators.
While I'm at it, do a little refactoring of the handling of binary expressions to reduce code duplication.
This commit is contained in:
parent
cbb213d79e
commit
e172b4d9bc
|
|
@ -145,13 +145,19 @@ void ExpArithmetic::dump(ostream&out, int indent) const
|
||||||
|
|
||||||
out << setw(indent) << "" << "Arithmetic " << fun_name
|
out << setw(indent) << "" << "Arithmetic " << fun_name
|
||||||
<< " at " << get_fileline() << endl;
|
<< " at " << get_fileline() << endl;
|
||||||
operand1()->dump(out, indent+4);
|
dump_operands(out, indent+4);
|
||||||
operand2()->dump(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
|
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
|
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
|
out << setw(indent) << "" << "Logical " << fun_name
|
||||||
<< " at " << get_fileline() << endl;
|
<< " at " << get_fileline() << endl;
|
||||||
operand1()->dump(out, indent+4);
|
dump_operands(out, indent+4);
|
||||||
operand2()->dump(out, indent+4);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExpName::dump(ostream&out, int indent) const
|
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_ << "\")"
|
out << setw(indent) << "" << "ExpName(\"" << name_ << "\")"
|
||||||
<< " at " << get_fileline() << endl;
|
<< " 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);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,16 @@ ExpBinary::~ExpBinary()
|
||||||
delete operand2_;
|
delete operand2_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExpUnary::ExpUnary(Expression*op1)
|
||||||
|
: operand1_(op1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpUnary::~ExpUnary()
|
||||||
|
{
|
||||||
|
delete operand1_;
|
||||||
|
}
|
||||||
|
|
||||||
ExpArithmetic::ExpArithmetic(ExpArithmetic::fun_t op, Expression*op1, Expression*op2)
|
ExpArithmetic::ExpArithmetic(ExpArithmetic::fun_t op, Expression*op1, Expression*op2)
|
||||||
: ExpBinary(op1, op2), fun_(op)
|
: ExpBinary(op1, op2), fun_(op)
|
||||||
{
|
{
|
||||||
|
|
@ -84,3 +94,21 @@ ExpName::ExpName(perm_string nn)
|
||||||
ExpName::~ExpName()
|
ExpName::~ExpName()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ExpUAbs::ExpUAbs(Expression*op1)
|
||||||
|
: ExpUnary(op1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpUAbs::~ExpUAbs()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpUNot::ExpUNot(Expression*op1)
|
||||||
|
: ExpUnary(op1)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ExpUNot::~ExpUNot()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,13 @@ class Expression : public LineInfo {
|
||||||
// cannot be done.
|
// cannot be done.
|
||||||
virtual bool evaluate(int64_t&val) const;
|
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.
|
// Debug dump of the expression.
|
||||||
virtual void dump(ostream&out, int indent) const =0;
|
virtual void dump(ostream&out, int indent) const =0;
|
||||||
|
|
||||||
|
|
@ -58,6 +65,20 @@ class Expression : public LineInfo {
|
||||||
Expression& operator = (const Expression&);
|
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
|
* This is an abstract class that collects some of the common features
|
||||||
* of binary operators.
|
* of binary operators.
|
||||||
|
|
@ -69,10 +90,11 @@ class ExpBinary : public Expression {
|
||||||
~ExpBinary();
|
~ExpBinary();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
inline Expression* operand1() { return operand1_; }
|
|
||||||
inline Expression* operand2() { return operand2_; }
|
int emit_operand1(ostream&out, Entity*ent, Architecture*arc);
|
||||||
inline const Expression* operand1() const { return operand1_; }
|
int emit_operand2(ostream&out, Entity*ent, Architecture*arc);
|
||||||
inline const Expression* operand2() const { return operand2_; }
|
|
||||||
|
void dump_operands(ostream&out, int indent) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Expression*operand1_;
|
Expression*operand1_;
|
||||||
|
|
@ -102,6 +124,7 @@ class ExpInteger : public Expression {
|
||||||
~ExpInteger();
|
~ExpInteger();
|
||||||
|
|
||||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||||
|
bool is_primary(void) const;
|
||||||
bool evaluate(int64_t&val) const;
|
bool evaluate(int64_t&val) const;
|
||||||
void dump(ostream&out, int indent) const;
|
void dump(ostream&out, int indent) const;
|
||||||
|
|
||||||
|
|
@ -136,11 +159,31 @@ class ExpName : public Expression {
|
||||||
~ExpName();
|
~ExpName();
|
||||||
|
|
||||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||||
|
bool is_primary(void) const;
|
||||||
void dump(ostream&out, int indent) const;
|
void dump(ostream&out, int indent) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
perm_string name_;
|
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
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -31,11 +31,43 @@ int Expression::emit(ostream&out, Entity*, Architecture*)
|
||||||
return 1;
|
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 ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||||
{
|
{
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
|
|
||||||
errors += operand1()->emit(out, ent, arc);
|
errors += emit_operand1(out, ent, arc);
|
||||||
|
|
||||||
switch (fun_) {
|
switch (fun_) {
|
||||||
case PLUS:
|
case PLUS:
|
||||||
|
|
@ -61,23 +93,27 @@ int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
errors += operand2()->emit(out, ent, arc);
|
errors += emit_operand2(out, ent, arc);
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ExpInteger::emit(ostream&out, Entity*, Architecture*)
|
int ExpInteger::emit(ostream&out, Entity*, Architecture*)
|
||||||
{
|
{
|
||||||
out << " /* " << get_fileline() << ": internal error: "
|
out << value_;
|
||||||
<< "INTEGER LITERAL */ ";
|
return 0;
|
||||||
return 1;
|
}
|
||||||
|
|
||||||
|
bool ExpInteger::is_primary(void) const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc)
|
int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||||
{
|
{
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
|
|
||||||
errors += operand1()->emit(out, ent, arc);
|
errors += emit_operand1(out, ent, arc);
|
||||||
|
|
||||||
switch (fun_) {
|
switch (fun_) {
|
||||||
case AND:
|
case AND:
|
||||||
|
|
@ -100,7 +136,7 @@ int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
errors += operand2()->emit(out, ent, arc);
|
errors += emit_operand2(out, ent, arc);
|
||||||
|
|
||||||
return errors;
|
return errors;
|
||||||
}
|
}
|
||||||
|
|
@ -112,3 +148,26 @@ int ExpName::emit(ostream&out, Entity*, Architecture*)
|
||||||
out << name_;
|
out << name_;
|
||||||
return errors;
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -294,6 +294,16 @@ factor
|
||||||
FILE_NAME(tmp, @2);
|
FILE_NAME(tmp, @2);
|
||||||
$$ = tmp;
|
$$ = 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; } ;
|
identifier_opt : IDENTIFIER { $$ = $1; } | { $$ = 0; } ;
|
||||||
|
|
@ -384,6 +394,8 @@ primary
|
||||||
FILE_NAME(tmp, @1);
|
FILE_NAME(tmp, @1);
|
||||||
$$ = tmp;
|
$$ = tmp;
|
||||||
}
|
}
|
||||||
|
| '(' expression ')'
|
||||||
|
{ $$ = $2; }
|
||||||
;
|
;
|
||||||
|
|
||||||
relation : shift_expression { $$ = $1; } ;
|
relation : shift_expression { $$ = $1; } ;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue