vhdlpp: Support for shift operators (SRL, SRR, SRA, SLA).

To be done: ROR & ROL.
This commit is contained in:
Maciej Suminski 2015-02-10 14:11:56 +01:00
parent 49b6ddf93c
commit 763c6fe3c9
8 changed files with 201 additions and 1 deletions

View File

@ -494,6 +494,11 @@ ExpRelation::~ExpRelation()
{
}
ExpShift::ExpShift(ExpShift::shift_t op, Expression*op1, Expression*op2)
: ExpBinary(op1, op2), shift_(op)
{
}
ExpString::ExpString(const char* value)
: value_(strlen(value))
{

View File

@ -692,6 +692,27 @@ class ExpRelation : public ExpBinary {
fun_t fun_;
};
class ExpShift : public ExpBinary {
public:
enum shift_t { SRL, SLL, SRA, SLA, ROL, ROR };
public:
ExpShift(ExpShift::shift_t op, Expression*op1, Expression*op2);
Expression*clone() const {
return new ExpShift(shift_, peek_operand1()->clone(), peek_operand2()->clone());
}
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const;
private:
shift_t shift_;
};
class ExpString : public Expression {
public:

View File

@ -82,3 +82,33 @@ void ExpNew::dump(ostream&out, int indent) const
out << "New dynamic array size: ";
size_->dump(out, indent);
}
void ExpShift::dump(ostream&out, int indent) const
{
const char*fun_name = "?";
switch (shift_) {
case SRL:
fun_name = "srl";
break;
case SLL:
fun_name = "sll";
break;
case SLA:
fun_name = "sla";
break;
case SRA:
fun_name = "sra";
break;
case ROR:
fun_name = "ror";
break;
case ROL:
fun_name = "rol";
break;
}
out << setw(indent) << "" << "Shift " << fun_name
<< " at " << get_fileline() << endl;
dump_operands(out, indent+4);
}

View File

@ -961,6 +961,19 @@ int ExpRelation::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
return errors;
}
int ExpShift::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{
int errors = 0;
if (ltype == 0) {
ltype = probe_type(ent, scope);
}
ivl_assert(*this, ltype != 0);
errors += elaborate_exprs(ent, scope, ltype);
return errors;
}
/*
* When a string appears in a concatenation, then the type of the
* string is an array with the same element type of the concatenation,

View File

@ -766,6 +766,36 @@ int ExpRelation::emit(ostream&out, Entity*ent, ScopeBase*scope)
return errors;
}
int ExpShift::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
errors += emit_operand1(out, ent, scope);
switch (shift_) {
case SRL:
out << " >> ";
break;
case SLL:
out << " << ";
break;
case SRA:
out << " >>> ";
break;
case SLA:
out << " <<< ";
break;
case ROR:
case ROL:
out << " /* ?ror/rol? */ ";
break;
}
errors += emit_operand2(out, ent, scope);
return errors;
}
bool ExpString::is_primary(void) const
{
return true;

View File

@ -216,3 +216,37 @@ bool ExpName::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
return evaluate(scope, val);
}
bool ExpShift::evaluate(ScopeBase*scope, int64_t&val) const
{
int64_t val1, val2;
bool rc;
rc = eval_operand1(scope, val1);
if (rc == false)
return false;
rc = eval_operand2(scope, val2);
if (rc == false)
return false;
switch (shift_) {
case SRL:
val = (uint64_t)val1 >> (uint64_t)val2;
break;
case SLL:
val = (uint64_t)val1 << (uint64_t)val2;
break;
case SRA:
val = (int64_t)val1 >> (int64_t)val2;
break;
case SLA:
val = (int64_t)val1 << (int64_t)val2;
break;
case ROR:
case ROL:
return false;
}
return true;
}

View File

@ -236,6 +236,39 @@ void ExpRelation::write_to_stream(ostream&fd) const
peek_operand2()->write_to_stream(fd);
}
void ExpShift::write_to_stream(ostream&out) const
{
out << "(";
write_to_stream_operand1(out);
out << ")";
switch (shift_) {
case SRL:
out << "srl";
break;
case SLL:
out << "sll";
break;
case SLA:
out << "sla";
break;
case SRA:
out << "sra";
break;
case ROR:
out << "ror";
break;
case ROL:
out << "rol";
break;
}
out << "(";
write_to_stream_operand2(out);
out << ")";
}
void ExpString::write_to_stream(ostream&fd) const
{
fd << "\"";

View File

@ -2139,7 +2139,41 @@ sequential_statement
}
;
shift_expression : simple_expression { $$ = $1; } ;
shift_expression
: simple_expression
| simple_expression K_srl simple_expression
{ ExpShift*tmp = new ExpShift(ExpShift::SRL, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| simple_expression K_sll simple_expression
{ ExpShift*tmp = new ExpShift(ExpShift::SLL, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| simple_expression K_sra simple_expression
{ ExpShift*tmp = new ExpShift(ExpShift::SRA, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| simple_expression K_sla simple_expression
{ ExpShift*tmp = new ExpShift(ExpShift::SLA, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| simple_expression K_ror simple_expression
{ sorrymsg(@2, "ROR is not supported.\n");
ExpShift*tmp = new ExpShift(ExpShift::ROR, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
| simple_expression K_rol simple_expression
{ sorrymsg(@2, "ROL is not supported.\n");
ExpShift*tmp = new ExpShift(ExpShift::ROL, $1, $3);
FILE_NAME(tmp, @2);
$$ = tmp;
}
;
sign
: '+'