Emit code for the to_unsigned() bulit-in function.
This commit is contained in:
parent
557e331ce1
commit
88cce86c63
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue