Emit code for the to_unsigned() bulit-in function.

This commit is contained in:
Stephen Williams 2011-09-18 19:31:28 -07:00
parent 557e331ce1
commit 88cce86c63
4 changed files with 82 additions and 9 deletions

View File

@ -22,6 +22,7 @@
# include <iostream>
# include <typeinfo>
# include <cstring>
# include <ivl_assert.h>
# include <cassert>
using namespace std;
@ -86,6 +87,40 @@ ExpAttribute::~ExpAttribute()
delete base_;
}
bool ExpAttribute::evaluate(ScopeBase*, int64_t&val) const
{
/* Special Case: The length attribute can be calculated all
the down to a literal integer at compile time, and all it
needs is the type of the base expression. (The base
expression doesn't even need to be evaluated.) */
if (name_ == "length") {
const VType*base_type = base_->peek_type();
//if (base_type == 0)
// base_type = base_->probe_type(ent,arc);
ivl_assert(*this, base_type);
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(base_type);
if (arr == 0) {
cerr << get_fileline() << ": error: "
<< "Cannot apply the 'length attribute to non-array objects"
<< endl;
return false;
}
int64_t size = 1;
for (size_t idx = 0 ; idx < arr->dimensions() ; idx += 1) {
const VTypeArray::range_t&dim = arr->dimension(idx);
ivl_assert(*this, ! dim.is_box());
size *= 1 + labs(dim.msb() - dim.lsb());
}
val = size;
return true;
}
return false;
}
ExpBinary::ExpBinary(Expression*op1, Expression*op2)
: operand1_(op1), operand2_(op2)
{
@ -296,10 +331,15 @@ ExpFunc::ExpFunc(perm_string nn)
{
}
ExpFunc::ExpFunc(perm_string nn, Expression*arg)
: name_(nn), argv_(1)
ExpFunc::ExpFunc(perm_string nn, list<Expression*>*args)
: name_(nn), argv_(args->size())
{
argv_[0] = arg;
for (size_t idx = 0; idx < argv_.size() ; idx += 1) {
ivl_assert(*this, !args->empty());
argv_[idx] = args->front();
args->pop_front();
}
ivl_assert(*this, args->empty());
}
ExpFunc::~ExpFunc()
@ -337,9 +377,14 @@ ExpName::ExpName(perm_string nn)
{
}
ExpName::ExpName(perm_string nn, Expression*ix)
: name_(nn), index_(ix), lsb_(0)
ExpName::ExpName(perm_string nn, list<Expression*>*indices)
: name_(nn), index_(0), lsb_(0)
{
/* For now, assume a single index. */
ivl_assert(*this, indices->size() == 1);
index_ = indices->front();
indices->pop_front();
}
ExpName::ExpName(perm_string nn, Expression*msb, Expression*lsb)

View File

@ -96,6 +96,9 @@ class Expression : public LineInfo {
virtual void dump(ostream&out, int indent = 0) const =0;
protected:
// This function is called by the derived class during
// elaboration to set the type of the current expression that
// elaboration assigns to this expression.
void set_type(const VType*);
private:
@ -258,8 +261,11 @@ class ExpAttribute : public Expression {
inline perm_string peek_attribute() const { return name_; }
inline const ExpName* peek_base() const { return base_; }
const VType*probe_type(Entity*ent, Architecture*arc) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
int emit(ostream&out, Entity*ent, Architecture*arc);
// Some attributes can be evaluated at compile time
bool evaluate(ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const;
private:
@ -351,7 +357,7 @@ class ExpFunc : public Expression {
public:
explicit ExpFunc(perm_string nn);
ExpFunc(perm_string nn, Expression*arg);
ExpFunc(perm_string nn, std::list<Expression*>*args);
~ExpFunc();
public: // Base methods
@ -409,7 +415,7 @@ class ExpName : public Expression {
public:
explicit ExpName(perm_string nn);
ExpName(perm_string nn, Expression*index);
ExpName(perm_string nn, std::list<Expression*>*indices);
ExpName(perm_string nn, Expression*msb, Expression*lsb);
~ExpName();

View File

@ -354,6 +354,15 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
errors += argv_[0]->emit(out, ent, arc);
out << ")";
} else if (name_ == "to_unsigned" && argv_.size() == 2) {
int64_t use_size;
bool rc = argv_[1]->evaluate(arc, use_size);
ivl_assert(*this, rc);
out << "$unsigned(" << use_size << "'(";
errors += argv_[0]->emit(out, ent, arc);
out << "))";
} else {
out << "\\" << name_ << " (";
for (size_t idx = 0; idx < argv_.size() ; idx += 1) {

View File

@ -248,7 +248,7 @@ const VType*parse_type_by_name(perm_string name)
%type <expr> shift_expression simple_expression term waveform_element
%type <expr_list> waveform waveform_elements
%type <expr_list> name_list
%type <expr_list> name_list expression_list
%type <expr_list> process_sensitivity_list process_sensitivity_list_opt
%type <named_expr> association_element
@ -781,6 +781,19 @@ entity_header
{ $$ = $1; }
;
expression_list
: expression_list ',' expression
{ list<Expression*>*tmp = $1;
tmp->push_back($3);
$$ = tmp;
}
| expression
{ list<Expression*>*tmp = new list<Expression*>;
tmp->push_back($1);
$$ = tmp;
}
;
expression
: expression_logical
{ $$ = $1; }
@ -1171,7 +1184,7 @@ name
function calls. The only way we can tell the difference is from
left context, namely whether the name is a type name or function
name. If none of the above, treat it as a array element select. */
| IDENTIFIER '(' expression ')'
| IDENTIFIER '(' expression_list ')'
{ perm_string name = lex_strings.make($1);
delete[]$1;
if (active_scope->is_vector_name(name)) {