Merge pull request #52 from orsonmmz/unbounded_function

Unbounded vectors in VHDL functions.
This commit is contained in:
Stephen Williams 2015-02-20 10:36:19 -08:00
commit d47afb588b
37 changed files with 1662 additions and 647 deletions

View File

@ -999,6 +999,9 @@ class PECastType : public PExpr {
void dump(ostream &out) const; void dump(ostream &out) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned flags) const;
virtual NetExpr*elaborate_expr(Design*des, NetScope*scope, virtual NetExpr*elaborate_expr(Design*des, NetScope*scope,
unsigned expr_wid, unsigned flags) const; unsigned expr_wid, unsigned flags) const;

View File

@ -2536,11 +2536,44 @@ unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid)
expr_width_ = t->packed_width(); expr_width_ = t->packed_width();
} }
signed_flag_= t->get_signed(); signed_flag_ = t->get_signed();
min_width_ = expr_width_; min_width_ = expr_width_;
return expr_width_; return expr_width_;
} }
NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
ivl_type_t type, unsigned) const
{
const netdarray_t*darray = NULL;
const netvector_t*vector = NULL;
// Casting array of vectors to dynamic array type
if((darray = dynamic_cast<const netdarray_t*>(type)) &&
(vector = dynamic_cast<const netvector_t*>(darray->element_type()))) {
PExpr::width_mode_t mode = PExpr::SIZED;
unsigned use_wid = base_->test_width(des, scope, mode);
NetExpr*base = base_->elaborate_expr(des, scope, use_wid, NO_FLAGS);
assert(vector->packed_width() > 0);
assert(base->expr_width() > 0);
// Find rounded up length that can fit the whole casted array of vectors
int len = base->expr_width() + vector->packed_width() - 1;
if(base->expr_width() > vector->packed_width()) {
len /= vector->packed_width();
} else {
len /= base->expr_width();
}
// Number of words in the created dynamic array
NetEConst*len_expr = new NetEConst(verinum(len));
return new NetENew(type, len_expr, base);
}
// Fallback
return elaborate_expr(des, scope, (unsigned) 0, 0);
}
NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope,
unsigned, unsigned) const unsigned, unsigned) const
{ {

View File

@ -2661,7 +2661,6 @@ vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
} }
delete range; delete range;
delete names;
return res; return res;
} }
@ -2690,7 +2689,6 @@ static vector<pform_tf_port_t>*do_make_task_ports(const struct vlltype&loc,
res->push_back(pform_tf_port_t(curw)); res->push_back(pform_tf_port_t(curw));
} }
delete names;
return res; return res;
} }
@ -2699,35 +2697,54 @@ vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
data_type_t*vtype, data_type_t*vtype,
list<perm_string>*names) list<perm_string>*names)
{ {
vector<pform_tf_port_t>*ret = NULL;
std::list<pform_range_t>*unpacked_dims = NULL;
if (uarray_type_t*uarray = dynamic_cast<uarray_type_t*> (vtype)) {
unpacked_dims = uarray->dims.get();
vtype = uarray->base_type;
}
if (atom2_type_t*atype = dynamic_cast<atom2_type_t*> (vtype)) { if (atom2_type_t*atype = dynamic_cast<atom2_type_t*> (vtype)) {
list<pform_range_t>*range_tmp = make_range_from_width(atype->type_code); list<pform_range_t>*range_tmp = make_range_from_width(atype->type_code);
return pform_make_task_ports(loc, pt, IVL_VT_BOOL, ret = pform_make_task_ports(loc, pt, IVL_VT_BOOL,
atype->signed_flag, atype->signed_flag,
range_tmp, names); range_tmp, names);
} }
if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (vtype)) { if (vector_type_t*vec_type = dynamic_cast<vector_type_t*> (vtype)) {
return pform_make_task_ports(loc, pt, vec_type->base_type, ret = pform_make_task_ports(loc, pt, vec_type->base_type,
vec_type->signed_flag, vec_type->signed_flag,
copy_range(vec_type->pdims.get()), copy_range(vec_type->pdims.get()),
names, vec_type->integer_flag); names, vec_type->integer_flag);
} }
if (/*real_type_t*real_type = */ dynamic_cast<real_type_t*> (vtype)) { if (/*real_type_t*real_type = */ dynamic_cast<real_type_t*> (vtype)) {
return pform_make_task_ports(loc, pt, IVL_VT_REAL, ret = pform_make_task_ports(loc, pt, IVL_VT_REAL,
true, 0, names); true, 0, names);
} }
if (dynamic_cast<string_type_t*> (vtype)) { if (dynamic_cast<string_type_t*> (vtype)) {
return pform_make_task_ports(loc, pt, IVL_VT_STRING, ret = pform_make_task_ports(loc, pt, IVL_VT_STRING,
false, 0, names); false, 0, names);
} }
if (class_type_t*class_type = dynamic_cast<class_type_t*> (vtype)) { if (class_type_t*class_type = dynamic_cast<class_type_t*> (vtype)) {
return do_make_task_ports(loc, pt, IVL_VT_CLASS, class_type, names); ret = do_make_task_ports(loc, pt, IVL_VT_CLASS, class_type, names);
} }
return do_make_task_ports(loc, pt, IVL_VT_NO_TYPE, vtype, names); ret = do_make_task_ports(loc, pt, IVL_VT_NO_TYPE, vtype, names);
if (unpacked_dims) {
for (list<perm_string>::iterator cur = names->begin()
; cur != names->end() ; ++ cur ) {
PWire*wire = pform_get_wire_in_scope(*cur);
wire->set_unpacked_idx(*unpacked_dims);
}
}
delete names;
return ret;
} }
/* /*

View File

@ -129,12 +129,15 @@ static int eval_darray_new(ivl_expr_t ex)
unsigned wid; unsigned wid;
switch (ivl_type_base(element_type)) { switch (ivl_type_base(element_type)) {
case IVL_VT_BOOL: case IVL_VT_BOOL:
case IVL_VT_LOGIC:
wid = width_of_packed_type(element_type); wid = width_of_packed_type(element_type);
draw_eval_vec4(init_expr);
resize_vec4_wid(init_expr, wid);
for (idx = 0 ; idx < cnt ; idx += 1) { for (idx = 0 ; idx < cnt ; idx += 1) {
fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", idx); draw_eval_vec4(init_expr);
fprintf(vvp_out, " %%parti/%c %d, %ld, 6;\n",
ivl_expr_signed(init_expr) ? 's' : 'u', wid, idx * wid);
fprintf(vvp_out, " %%ix/load 3, %ld, 0;\n", cnt - idx - 1);
fprintf(vvp_out, " %%set/dar/obj/vec4 3;\n"); fprintf(vvp_out, " %%set/dar/obj/vec4 3;\n");
fprintf(vvp_out, " %%pop/vec4 1;\n");
} }
break; break;
case IVL_VT_REAL: case IVL_VT_REAL:

View File

@ -444,7 +444,7 @@ static int show_stmt_assign_vector(ivl_statement_t net)
fprintf(vvp_out, " %%cvt/vr %u;\n", wid); fprintf(vvp_out, " %%cvt/vr %u;\n", wid);
} else if (ivl_expr_value(rval) == IVL_VT_STRING) { } else if (ivl_expr_value(rval) == IVL_VT_STRING) {
/* Special case: vector to string casting */ /* Special case: string to vector casting */
ivl_lval_t lval = ivl_stmt_lval(net, 0); ivl_lval_t lval = ivl_stmt_lval(net, 0);
fprintf(vvp_out, " %%vpi_call %u %u \"$ivl_string_method$to_vec\", v%p_0, v%p_0 {0 0 0};\n", fprintf(vvp_out, " %%vpi_call %u %u \"$ivl_string_method$to_vec\", v%p_0, v%p_0 {0 0 0};\n",
ivl_file_table_index(ivl_stmt_file(net)), ivl_stmt_lineno(net), ivl_file_table_index(ivl_stmt_file(net)), ivl_stmt_lineno(net),
@ -452,6 +452,28 @@ static int show_stmt_assign_vector(ivl_statement_t net)
if (slices) free(slices); if (slices) free(slices);
return 0; return 0;
} else if (ivl_expr_value(rval) == IVL_VT_DARRAY) {
/* Special case: dynamic array to vector casting */
ivl_lval_t lval = ivl_stmt_lval(net, 0);
void*rval_addr = NULL;
/* Even more special case: function call returning dynamic array */
if(ivl_expr_type(rval) == IVL_EX_UFUNC) {
rval_addr = ivl_scope_port(ivl_expr_def(rval), 0);
draw_ufunc_object(rval);
/* We do not need to store the result, it is going to be
converted to vector quite soon. */
fprintf(vvp_out, " %%pop/obj 1, 0; drop the result\n");
} else {
rval_addr = ivl_expr_signal(rval);
}
fprintf(vvp_out, " %%vpi_call %u %u \"$ivl_darray_method$to_vec\", v%p_0, v%p_0 {0 0 0};\n",
ivl_file_table_index(ivl_stmt_file(net)), ivl_stmt_lineno(net),
rval_addr, ivl_lval_sig(lval));
if (slices) free(slices);
return 0;
} else { } else {
unsigned wid = ivl_stmt_lwidth(net); unsigned wid = ivl_stmt_lwidth(net);
draw_eval_vec4(rval); draw_eval_vec4(rval);

View File

@ -368,9 +368,11 @@ int SignalAssignment::elaborate(Entity*ent, Architecture*arc)
return errors; return errors;
} }
for (list<Expression*>::const_iterator cur = rval_.begin() for (list<Expression*>::iterator cur = rval_.begin()
; cur != rval_.end() ; ++cur) { ; cur != rval_.end() ; ++cur) {
(*cur)->elaborate_expr(ent, arc, lval_type); (*cur)->elaborate_expr(ent, arc, lval_type);
// Handle functions that return unbounded arrays
} }
return errors; return errors;

View File

@ -103,7 +103,9 @@ int Architecture::emit(ostream&out, Entity*entity)
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin() for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin()
; cur != cur_subprograms_.end() ; ++ cur) { ; cur != cur_subprograms_.end() ; ++ cur) {
errors += cur->second->emit_package(out); // Do not emit unbounded functions, we will just need fixed instances later
if(!cur->second->unbounded())
errors += cur->second->emit_package(out);
} }
for (list<Architecture::Statement*>::iterator cur = statements_.begin() for (list<Architecture::Statement*>::iterator cur = statements_.begin()

View File

@ -20,6 +20,7 @@
*/ */
# include "expression.h" # include "expression.h"
# include "subprogram.h"
# include "parse_types.h" # include "parse_types.h"
# include "scope.h" # include "scope.h"
# include <iostream> # include <iostream>
@ -63,6 +64,11 @@ ExpAttribute::~ExpAttribute()
delete base_; delete base_;
} }
Expression*ExpAttribute::clone() const
{
return new ExpAttribute(static_cast<ExpName*>(base_->clone()), name_);
}
ExpBinary::ExpBinary(Expression*op1, Expression*op2) ExpBinary::ExpBinary(Expression*op1, Expression*op2)
: operand1_(op1), operand2_(op2) : operand1_(op1), operand2_(op2)
{ {
@ -112,6 +118,23 @@ ExpAggregate::~ExpAggregate()
delete elements_[idx]; delete elements_[idx];
} }
Expression* ExpAggregate::clone() const
{
std::list<element_t*>*new_elements = NULL;
if(!elements_.empty()) {
new_elements = new std::list<element_t*>();
for(std::vector<element_t*>::const_iterator it = elements_.begin();
it != elements_.end(); ++it) {
new_elements->push_back(new element_t(**it));
}
}
assert(aggregate_.empty()); // cloning should not happen after elab
return new ExpAggregate(new_elements);
}
ExpAggregate::choice_t::choice_t(Expression*exp) ExpAggregate::choice_t::choice_t(Expression*exp)
: expr_(exp) : expr_(exp)
{ {
@ -126,6 +149,15 @@ ExpAggregate::choice_t::choice_t(prange_t*rang)
{ {
} }
ExpAggregate::choice_t::choice_t(const choice_t&other)
{
if(Expression*e = other.expr_.get())
expr_.reset(e->clone());
if(other.range_.get())
range_.reset(new prange_t(*other.range_.get()));
}
ExpAggregate::choice_t::~choice_t() ExpAggregate::choice_t::~choice_t()
{ {
} }
@ -159,6 +191,18 @@ ExpAggregate::element_t::element_t(list<choice_t*>*fields, Expression*val)
} }
} }
ExpAggregate::element_t::element_t(const ExpAggregate::element_t&other)
{
fields_.reserve(other.fields_.size());
for(std::vector<choice_t*>::const_iterator it = other.fields_.begin();
it != other.fields_.end(); ++it) {
fields_.push_back(*it);
}
val_ = other.val_->clone();
}
ExpAggregate::element_t::~element_t() ExpAggregate::element_t::~element_t()
{ {
for (size_t idx = 0 ; idx < fields_.size() ; idx += 1) for (size_t idx = 0 ; idx < fields_.size() ; idx += 1)
@ -235,12 +279,46 @@ ExpConditional::~ExpConditional()
} }
} }
Expression*ExpConditional::clone() const
{
std::list<Expression*>*new_true_clause = NULL;
if(!true_clause_.empty()) {
new_true_clause = new std::list<Expression*>();
for(std::list<Expression*>::const_iterator it = true_clause_.begin();
it != true_clause_.end(); ++it) {
new_true_clause->push_back((*it)->clone());
}
}
std::list<else_t*>*new_else_clause = NULL;
if(!else_clause_.empty()) {
new_else_clause = new std::list<else_t*>();
for(std::list<else_t*>::const_iterator it = else_clause_.begin();
it != else_clause_.end(); ++it) {
new_else_clause->push_back(new else_t(**it));
}
}
return new ExpConditional(cond_->clone(), new_true_clause, new_else_clause);
}
ExpConditional::else_t::else_t(Expression*cond, std::list<Expression*>*tru) ExpConditional::else_t::else_t(Expression*cond, std::list<Expression*>*tru)
: cond_(cond) : cond_(cond)
{ {
if (tru) true_clause_.splice(true_clause_.end(), *tru); if (tru) true_clause_.splice(true_clause_.end(), *tru);
} }
ExpConditional::else_t::else_t(const else_t&other)
{
cond_ = other.cond_->clone();
for(std::list<Expression*>::const_iterator it = other.true_clause_.begin();
it != other.true_clause_.end(); ++it) {
true_clause_.push_back((*it)->clone());
}
}
ExpConditional::else_t::~else_t() ExpConditional::else_t::~else_t()
{ {
delete cond_; delete cond_;
@ -283,6 +361,27 @@ ExpFunc::~ExpFunc()
delete argv_[idx]; delete argv_[idx];
} }
Expression*ExpFunc::clone() const {
std::list<Expression*>*new_args = NULL;
if(!argv_.empty()) {
new_args = new std::list<Expression*>();
for(std::vector<Expression*>::const_iterator it = argv_.begin();
it != argv_.end(); ++it)
new_args->push_back((*it)->clone());
}
ExpFunc*f = new ExpFunc(name_, new_args);
f->def_ = def_;
return f;
}
const VType* ExpFunc::func_ret_type() const
{
return def_ ? def_->peek_return_type() : NULL;
}
ExpInteger::ExpInteger(int64_t val) ExpInteger::ExpInteger(int64_t val)
: value_(val) : value_(val)
{ {
@ -423,3 +522,22 @@ ExpUNot::ExpUNot(Expression*op1)
ExpUNot::~ExpUNot() ExpUNot::~ExpUNot()
{ {
} }
ExpCast::ExpCast(Expression*base, const VType*type) :
base_(base), type_(type)
{
}
ExpCast::~ExpCast()
{
}
ExpNew::ExpNew(Expression*size) :
size_(size)
{
}
ExpNew::~ExpNew()
{
delete size_;
}

View File

@ -31,13 +31,11 @@
class prange_t; class prange_t;
class Entity; class Entity;
class Architecture;
class ScopeBase; class ScopeBase;
class Subprogram; class Subprogram;
class VType; class VType;
class VTypeArray; class VTypeArray;
class VTypePrimitive; class VTypePrimitive;
class ExpName; class ExpName;
/* /*
@ -51,18 +49,21 @@ class Expression : public LineInfo {
Expression(); Expression();
virtual ~Expression() =0; virtual ~Expression() =0;
// Returns a deep copy of the expression.
virtual Expression*clone() const =0;
// This virtual method handles the special case of elaborating // This virtual method handles the special case of elaborating
// an expression that is the l-value of a sequential variable // an expression that is the l-value of a sequential variable
// assignment. This generates an error for most cases, but // assignment. This generates an error for most cases, but
// expressions that are valid l-values return 0 and set any // expressions that are valid l-values return 0 and set any
// flags needed to indicate their status as writable variables. // flags needed to indicate their status as writable variables.
virtual int elaborate_lval(Entity*ent, Architecture*arc, virtual int elaborate_lval(Entity*ent, ScopeBase*scope,
bool is_sequ); bool is_sequ);
// This virtual method probes the expression to get the most // This virtual method probes the expression to get the most
// constrained type for the expression. For a given instance, // constrained type for the expression. For a given instance,
// this may be called before the elaborate_expr method. // this may be called before the elaborate_expr method.
virtual const VType*probe_type(Entity*ent, Architecture*arc) const; virtual const VType*probe_type(Entity*ent, ScopeBase*scope) const;
// The fit_type virtual method is used by the ExpConcat class // The fit_type virtual method is used by the ExpConcat class
// to probe the type of operands. The atype argument is the // to probe the type of operands. The atype argument is the
@ -70,13 +71,13 @@ class Expression : public LineInfo {
// returns its type as interpreted in this context. Really, // returns its type as interpreted in this context. Really,
// this is mostly about helping aggregate expressions within // this is mostly about helping aggregate expressions within
// concatenations to figure out their type. // concatenations to figure out their type.
virtual const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const; virtual const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
// This virtual method elaborates an expression. The ltype is // This virtual method elaborates an expression. The ltype is
// the type of the lvalue expression, if known, and can be // the type of the lvalue expression, if known, and can be
// used to calculate the type for the expression being // used to calculate the type for the expression being
// elaborated. // elaborated.
virtual int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); virtual int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
// Return the type that this expression would be if it were an // Return the type that this expression would be if it were an
// l-value. This should only be called after elaborate_lval is // l-value. This should only be called after elaborate_lval is
@ -86,12 +87,12 @@ class Expression : public LineInfo {
// This virtual method writes a VHDL-accurate representation // This virtual method writes a VHDL-accurate representation
// of this expression to the designated stream. This is used // of this expression to the designated stream. This is used
// for writing parsed types to library files. // for writing parsed types to library files.
virtual void write_to_stream(std::ostream&fd) =0; virtual void write_to_stream(std::ostream&fd) const =0;
// The emit virtual method is called by architecture emit to // The emit virtual method is called by architecture emit to
// output the generated code for the expression. The derived // output the generated code for the expression. The derived
// class fills in the details of what exactly happened. // class fills in the details of what exactly happened.
virtual int emit(ostream&out, Entity*ent, Architecture*arc) =0; virtual int emit(ostream&out, Entity*ent, ScopeBase*scope) =0;
// The emit_package virtual message is similar, but is called // The emit_package virtual message is similar, but is called
// in a package context and to emit SV packages. // in a package context and to emit SV packages.
@ -102,7 +103,7 @@ class Expression : public LineInfo {
// argument if the evaluation works, or return false if it // argument if the evaluation works, or return false if it
// cannot be done. // cannot be done.
virtual bool evaluate(ScopeBase*scope, int64_t&val) const; virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
virtual bool evaluate(Entity*ent, Architecture*arc, int64_t&val) const; virtual bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
// The symbolic compare returns true if the two expressions // The symbolic compare returns true if the two expressions
@ -134,6 +135,13 @@ class Expression : public LineInfo {
Expression& operator = (const Expression&); Expression& operator = (const Expression&);
}; };
/*
* Checks before cloning if the other expression actually exists (!=NULL).
*/
static inline Expression*safe_clone(const Expression*other) {
return (other ? other->clone() : NULL);
}
static inline void FILE_NAME(Expression*tgt, const LineInfo*src) static inline void FILE_NAME(Expression*tgt, const LineInfo*src)
{ {
tgt->set_line(*src); tgt->set_line(*src);
@ -150,13 +158,15 @@ class ExpUnary : public Expression {
ExpUnary(Expression*op1); ExpUnary(Expression*op1);
virtual ~ExpUnary() =0; virtual ~ExpUnary() =0;
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const; inline const Expression*peek_operand() const { return operand1_; }
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
protected: protected:
inline void write_to_stream_operand1(std::ostream&fd) inline void write_to_stream_operand1(std::ostream&fd) const
{ operand1_->write_to_stream(fd); } { operand1_->write_to_stream(fd); }
int emit_operand1(ostream&out, Entity*ent, Architecture*arc); int emit_operand1(ostream&out, Entity*ent, ScopeBase*scope);
void dump_operand1(ostream&out, int indent = 0) const; void dump_operand1(ostream&out, int indent = 0) const;
private: private:
@ -173,23 +183,23 @@ class ExpBinary : public Expression {
ExpBinary(Expression*op1, Expression*op2); ExpBinary(Expression*op1, Expression*op2);
virtual ~ExpBinary() =0; virtual ~ExpBinary() =0;
const Expression* peek_operand1(void) const { return operand1_; } inline const Expression* peek_operand1(void) const { return operand1_; }
const Expression* peek_operand2(void) const { return operand2_; } inline const Expression* peek_operand2(void) const { return operand2_; }
const VType*probe_type(Entity*ent, Architecture*arc) const; const VType*probe_type(Entity*ent, ScopeBase*scope) const;
protected: protected:
int elaborate_exprs(Entity*, Architecture*, const VType*); int elaborate_exprs(Entity*, ScopeBase*, const VType*);
int emit_operand1(ostream&out, Entity*ent, Architecture*arc); int emit_operand1(ostream&out, Entity*ent, ScopeBase*scope);
int emit_operand2(ostream&out, Entity*ent, Architecture*arc); int emit_operand2(ostream&out, Entity*ent, ScopeBase*scope);
bool eval_operand1(ScopeBase*scope, int64_t&val) const; bool eval_operand1(ScopeBase*scope, int64_t&val) const;
bool eval_operand2(ScopeBase*scope, int64_t&val) const; bool eval_operand2(ScopeBase*scope, int64_t&val) const;
inline void write_to_stream_operand1(std::ostream&out) inline void write_to_stream_operand1(std::ostream&out) const
{ operand1_->write_to_stream(out); } { operand1_->write_to_stream(out); }
inline void write_to_stream_operand2(std::ostream&out) inline void write_to_stream_operand2(std::ostream&out) const
{ operand2_->write_to_stream(out); } { operand2_->write_to_stream(out); }
void dump_operands(ostream&out, int indent = 0) const; void dump_operands(ostream&out, int indent = 0) const;
@ -219,6 +229,9 @@ class ExpAggregate : public Expression {
explicit choice_t(perm_string name); explicit choice_t(perm_string name);
// discreate_range choice // discreate_range choice
explicit choice_t(prange_t*ran); explicit choice_t(prange_t*ran);
choice_t(const choice_t&other);
~choice_t(); ~choice_t();
// true if this represents an "others" choice // true if this represents an "others" choice
@ -235,11 +248,17 @@ class ExpAggregate : public Expression {
std::auto_ptr<Expression>expr_; std::auto_ptr<Expression>expr_;
std::auto_ptr<prange_t> range_; std::auto_ptr<prange_t> range_;
private: // not implemented private: // not implemented
choice_t(const choice_t&);
choice_t& operator= (const choice_t&); choice_t& operator= (const choice_t&);
}; };
struct choice_element { struct choice_element {
choice_element() : choice(), expr() {}
choice_element(const choice_element&other) {
choice = other.choice ? new choice_t(*other.choice) : NULL;
expr = safe_clone(other.expr);
}
choice_t*choice; choice_t*choice;
Expression*expr; Expression*expr;
bool alias_flag; bool alias_flag;
@ -251,6 +270,7 @@ class ExpAggregate : public Expression {
class element_t { class element_t {
public: public:
explicit element_t(std::list<choice_t*>*fields, Expression*val); explicit element_t(std::list<choice_t*>*fields, Expression*val);
element_t(const element_t&other);
~element_t(); ~element_t();
size_t count_choices() const { return fields_.size(); } size_t count_choices() const { return fields_.size(); }
@ -265,7 +285,6 @@ class ExpAggregate : public Expression {
std::vector<choice_t*>fields_; std::vector<choice_t*>fields_;
Expression*val_; Expression*val_;
private: // not implemented private: // not implemented
element_t(const element_t&);
element_t& operator = (const element_t&); element_t& operator = (const element_t&);
}; };
@ -273,19 +292,20 @@ class ExpAggregate : public Expression {
ExpAggregate(std::list<element_t*>*el); ExpAggregate(std::list<element_t*>*el);
~ExpAggregate(); ~ExpAggregate();
Expression*clone() const;
const VType*probe_type(Entity*ent, Architecture*arc) const; const VType*probe_type(Entity*ent, ScopeBase*scope) const;
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const; const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd); void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, Architecture*arc); int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
private: private:
int elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype); int elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype);
int elaborate_expr_record_(Entity*ent, Architecture*arc, const VTypeRecord*ltype); int elaborate_expr_record_(Entity*ent, ScopeBase*scope, const VTypeRecord*ltype);
int emit_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*ltype); int emit_array_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeArray*ltype);
int emit_record_(ostream&out, Entity*ent, Architecture*arc, const VTypeRecord*ltype); int emit_record_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeRecord*ltype);
private: private:
// This is the elements as directly parsed. // This is the elements as directly parsed.
@ -305,9 +325,13 @@ class ExpArithmetic : public ExpBinary {
ExpArithmetic(ExpArithmetic::fun_t op, Expression*op1, Expression*op2); ExpArithmetic(ExpArithmetic::fun_t op, Expression*op1, Expression*op2);
~ExpArithmetic(); ~ExpArithmetic();
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); Expression*clone() const {
void write_to_stream(std::ostream&fd); return new ExpArithmetic(fun_, peek_operand1()->clone(), peek_operand2()->clone());
int emit(ostream&out, Entity*ent, Architecture*arc); }
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; virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
@ -324,16 +348,18 @@ class ExpAttribute : public Expression {
ExpAttribute(ExpName*base, perm_string name); ExpAttribute(ExpName*base, perm_string name);
~ExpAttribute(); ~ExpAttribute();
Expression*clone() const;
inline perm_string peek_attribute() const { return name_; } inline perm_string peek_attribute() const { return name_; }
inline const ExpName* peek_base() const { return base_; } inline const ExpName* peek_base() const { return base_; }
const VType*probe_type(Entity*ent, Architecture*arc) const; const VType*probe_type(Entity*ent, ScopeBase*scope) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd); void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, Architecture*arc); int emit(ostream&out, Entity*ent, ScopeBase*scope);
// Some attributes can be evaluated at compile time // Some attributes can be evaluated at compile time
bool evaluate(ScopeBase*scope, int64_t&val) const; bool evaluate(ScopeBase*scope, int64_t&val) const;
bool evaluate(Entity*ent, Architecture*arc, int64_t&val) const; bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
private: private:
@ -345,12 +371,15 @@ class ExpBitstring : public Expression {
public: public:
explicit ExpBitstring(const char*); explicit ExpBitstring(const char*);
ExpBitstring(const ExpBitstring&other) : Expression() { value_ = other.value_; }
~ExpBitstring(); ~ExpBitstring();
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const; Expression*clone() const { return new ExpBitstring(*this); }
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd); const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
int emit(ostream&out, Entity*ent, Architecture*arc); 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);
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
private: private:
@ -362,19 +391,22 @@ class ExpCharacter : public Expression {
public: public:
ExpCharacter(char val); ExpCharacter(char val);
ExpCharacter(const ExpCharacter&other) : Expression() { value_ = other.value_; }
~ExpCharacter(); ~ExpCharacter();
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const; Expression*clone() const { return new ExpCharacter(*this); }
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd); const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
int emit(ostream&out, Entity*ent, Architecture*arc); 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);
bool is_primary(void) const; bool is_primary(void) const;
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
char value() const { return value_; } char value() const { return value_; }
private: private:
int emit_primitive_bit_(ostream&out, Entity*ent, Architecture*arc, int emit_primitive_bit_(ostream&out, Entity*ent, ScopeBase*scope,
const VTypePrimitive*etype); const VTypePrimitive*etype);
private: private:
@ -387,17 +419,21 @@ class ExpConcat : public Expression {
ExpConcat(Expression*op1, Expression*op2); ExpConcat(Expression*op1, Expression*op2);
~ExpConcat(); ~ExpConcat();
const VType*probe_type(Entity*ent, Architecture*arc) const; Expression*clone() const {
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const; return new ExpConcat(operand1_->clone(), operand2_->clone());
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); }
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc); const VType*probe_type(Entity*ent, ScopeBase*scope) const;
const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
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; virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
bool is_primary(void) const; bool is_primary(void) const;
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
private: private:
int elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype); int elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype);
private: private:
Expression*operand1_; Expression*operand1_;
@ -415,11 +451,12 @@ class ExpConditional : public Expression {
class else_t : public LineInfo { class else_t : public LineInfo {
public: public:
else_t(Expression*cond, std::list<Expression*>*tru); else_t(Expression*cond, std::list<Expression*>*tru);
else_t(const else_t&other);
~else_t(); ~else_t();
int elaborate_expr(Entity*ent, Architecture*arc, const VType*lt); int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*lt);
int emit_when_else(ostream&out, Entity*ent, Architecture*arc); int emit_when_else(ostream&out, Entity*ent, ScopeBase*scope);
int emit_else(ostream&out, Entity*ent, Architecture*arc); int emit_else(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
private: private:
@ -432,10 +469,12 @@ class ExpConditional : public Expression {
std::list<else_t*>*fal); std::list<else_t*>*fal);
~ExpConditional(); ~ExpConditional();
const VType*probe_type(Entity*ent, Architecture*arc) const; Expression*clone() const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd); const VType*probe_type(Entity*ent, ScopeBase*scope) const;
int emit(ostream&out, Entity*ent, Architecture*arc); 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);
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
private: private:
@ -457,10 +496,12 @@ class ExpEdge : public ExpUnary {
explicit ExpEdge(ExpEdge::fun_t ty, Expression*op); explicit ExpEdge(ExpEdge::fun_t ty, Expression*op);
~ExpEdge(); ~ExpEdge();
Expression*clone() const { return new ExpEdge(fun_, peek_operand()->clone()); }
inline fun_t edge_fun() const { return fun_; } inline fun_t edge_fun() const { return fun_; }
void write_to_stream(std::ostream&fd); void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, Architecture*arc); int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
private: private:
@ -474,14 +515,17 @@ class ExpFunc : public Expression {
ExpFunc(perm_string nn, std::list<Expression*>*args); ExpFunc(perm_string nn, std::list<Expression*>*args);
~ExpFunc(); ~ExpFunc();
Expression*clone() const;
inline perm_string func_name() const { return name_; } inline perm_string func_name() const { return name_; }
inline size_t func_args() const { return argv_.size(); } inline size_t func_args() const { return argv_.size(); }
inline const Expression*func_arg(size_t idx) const { return argv_[idx]; } inline const Expression*func_arg(size_t idx) const { return argv_[idx]; }
const VType*func_ret_type() const;
public: // Base methods public: // Base methods
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd); void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, Architecture*arc); int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
private: private:
@ -494,14 +538,17 @@ class ExpInteger : public Expression {
public: public:
ExpInteger(int64_t val); ExpInteger(int64_t val);
ExpInteger(const ExpInteger&other) : Expression(), value_(other.value_) {}
~ExpInteger(); ~ExpInteger();
const VType*probe_type(Entity*ent, Architecture*arc) const; Expression*clone() const { return new ExpInteger(*this); }
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd); const VType*probe_type(Entity*ent, ScopeBase*scope) const;
int emit(ostream&out, Entity*ent, Architecture*arc); 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);
int emit_package(std::ostream&out); int emit_package(std::ostream&out);
bool is_primary(void) const; bool is_primary(void) const { return true; }
bool evaluate(ScopeBase*scope, int64_t&val) const; bool evaluate(ScopeBase*scope, int64_t&val) const;
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
virtual ostream& dump_inline(ostream&out) const; virtual ostream& dump_inline(ostream&out) const;
@ -514,12 +561,15 @@ class ExpReal : public Expression {
public: public:
ExpReal(double val); ExpReal(double val);
ExpReal(const ExpReal&other) : Expression(), value_(other.value_) {}
~ExpReal(); ~ExpReal();
const VType*probe_type(Entity*ent, Architecture*arc) const; Expression*clone() const { return new ExpReal(*this); }
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd); const VType*probe_type(Entity*ent, ScopeBase*scope) const;
int emit(ostream&out, Entity*ent, Architecture*arc); 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);
int emit_package(std::ostream&out); int emit_package(std::ostream&out);
bool is_primary(void) const; bool is_primary(void) const;
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
@ -538,11 +588,15 @@ class ExpLogical : public ExpBinary {
ExpLogical(ExpLogical::fun_t ty, Expression*op1, Expression*op2); ExpLogical(ExpLogical::fun_t ty, Expression*op1, Expression*op2);
~ExpLogical(); ~ExpLogical();
Expression*clone() const {
return new ExpLogical(fun_, peek_operand1()->clone(), peek_operand2()->clone());
}
inline fun_t logic_fun() const { return fun_; } inline fun_t logic_fun() const { return fun_; }
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
void write_to_stream(std::ostream&fd); void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, Architecture*arc); int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
private: private:
@ -565,31 +619,35 @@ class ExpName : public Expression {
~ExpName(); ~ExpName();
public: // Base methods public: // Base methods
int elaborate_lval(Entity*ent, Architecture*arc, bool); Expression*clone() const {
int elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*); return new ExpName(static_cast<ExpName*>(safe_clone(prefix_.get())),
const VType* probe_type(Entity*ent, Architecture*arc) const; name_, safe_clone(index_), safe_clone(lsb_));
const VType* fit_type(Entity*ent, Architecture*arc, const VTypeArray*host) const; }
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); int elaborate_lval(Entity*ent, ScopeBase*scope, bool);
void write_to_stream(std::ostream&fd); int elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*);
int emit(ostream&out, Entity*ent, Architecture*arc); const VType* probe_type(Entity*ent, ScopeBase*scope) const;
const VType* fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*host) const;
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);
bool is_primary(void) const; bool is_primary(void) const;
bool evaluate(ScopeBase*scope, int64_t&val) const; bool evaluate(ScopeBase*scope, int64_t&val) const;
bool evaluate(Entity*ent, Architecture*arc, int64_t&val) const; bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const;
bool symbolic_compare(const Expression*that) const; bool symbolic_compare(const Expression*that) const;
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
const char* name() const; const char* name() const;
inline perm_string peek_name() const { return name_; } inline const perm_string& peek_name() const { return name_; }
void set_range(Expression*msb, Expression*lsb); void set_range(Expression*msb, Expression*lsb);
private: private:
const VType* elaborate_adjust_type_with_range_(Entity*ent, Architecture*arc, const VType*type); const VType* elaborate_adjust_type_with_range_(Entity*ent, ScopeBase*scope, const VType*type);
int elaborate_lval_(Entity*ent, Architecture*arc, bool, ExpName*suffix); int elaborate_lval_(Entity*ent, ScopeBase*scope, bool, ExpName*suffix);
const VType* probe_prefix_type_(Entity*ent, Architecture*arc) const; const VType* probe_prefix_type_(Entity*ent, ScopeBase*scope) const;
const VType* probe_prefixed_type_(Entity*ent, Architecture*arc) const; const VType* probe_prefixed_type_(Entity*ent, ScopeBase*scope) const;
int emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc); int emit_as_prefix_(ostream&out, Entity*ent, ScopeBase*scope);
private: private:
std::auto_ptr<ExpName> prefix_; std::auto_ptr<ExpName> prefix_;
@ -604,8 +662,8 @@ class ExpNameALL : public ExpName {
ExpNameALL() : ExpName(perm_string()) { } ExpNameALL() : ExpName(perm_string()) { }
public: public:
int elaborate_lval(Entity*ent, Architecture*arc, bool); int elaborate_lval(Entity*ent, ScopeBase*scope, bool);
const VType* probe_type(Entity*ent, Architecture*arc) const; const VType* probe_type(Entity*ent, ScopeBase*scope) const;
void dump(ostream&out, int indent =0) const; void dump(ostream&out, int indent =0) const;
}; };
@ -620,10 +678,14 @@ class ExpRelation : public ExpBinary {
ExpRelation(ExpRelation::fun_t ty, Expression*op1, Expression*op2); ExpRelation(ExpRelation::fun_t ty, Expression*op1, Expression*op2);
~ExpRelation(); ~ExpRelation();
const VType* probe_type(Entity*ent, Architecture*arc) const; Expression*clone() const {
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); return new ExpRelation(fun_, peek_operand1()->clone(), peek_operand2()->clone());
void write_to_stream(std::ostream&fd); }
int emit(ostream&out, Entity*ent, Architecture*arc);
const VType* probe_type(Entity*ent, ScopeBase*scope) const;
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);
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
private: private:
@ -634,18 +696,21 @@ class ExpString : public Expression {
public: public:
explicit ExpString(const char*); explicit ExpString(const char*);
ExpString(const ExpString&other) : Expression(), value_(other.value_) {}
~ExpString(); ~ExpString();
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const; Expression*clone() const { return new ExpString(*this); }
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
void write_to_stream(std::ostream&fd); const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const;
int emit(ostream&out, Entity*ent, Architecture*arc); 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);
bool is_primary(void) const; bool is_primary(void) const;
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
const std::vector<char>& get_value() const { return value_; } const std::vector<char>& get_value() const { return value_; }
private: private:
int emit_as_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*arr); int emit_as_array_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeArray*arr);
private: private:
std::vector<char> value_; std::vector<char> value_;
@ -657,8 +722,10 @@ class ExpUAbs : public ExpUnary {
ExpUAbs(Expression*op1); ExpUAbs(Expression*op1);
~ExpUAbs(); ~ExpUAbs();
void write_to_stream(std::ostream&fd); Expression*clone() const { return new ExpUAbs(peek_operand()->clone()); }
int emit(ostream&out, Entity*ent, Architecture*arc);
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
}; };
@ -668,10 +735,56 @@ class ExpUNot : public ExpUnary {
ExpUNot(Expression*op1); ExpUNot(Expression*op1);
~ExpUNot(); ~ExpUNot();
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); Expression*clone() const { return new ExpUNot(peek_operand()->clone()); }
void write_to_stream(std::ostream&fd);
int emit(ostream&out, Entity*ent, Architecture*arc); 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);
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
}; };
/*
* Class that wraps other expressions to cast them to other types.
*/
class ExpCast : public Expression {
public:
ExpCast(Expression*base, const VType*type);
~ExpCast();
Expression*clone() const { return new ExpCast(base_->clone(), type_->clone()); }
inline int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*) {
return base_->elaborate_expr(ent, scope, type_);
}
void write_to_stream(std::ostream&fd) const;
int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const;
private:
Expression*base_;
const VType*type_;
};
/*
* Class that handles 'new' statement. VHDL is not capable of dynamic memory
* allocation, but it is useful for emitting some cases.
*/
class ExpNew : public Expression {
public:
ExpNew(Expression*size);
~ExpNew();
Expression*clone() const { return new ExpNew(size_->clone()); }
// There is no 'new' in VHDL - do not emit anything
void write_to_stream(std::ostream&) const {};
int emit(ostream&out, Entity*ent, ScopeBase*scope);
void dump(ostream&out, int indent = 0) const;
private:
Expression*size_;
};
#endif /* IVL_expression_H */ #endif /* IVL_expression_H */

View File

@ -68,3 +68,17 @@ void ExpConcat::dump(ostream&out, int indent) const
operand1_->dump(out, indent); operand1_->dump(out, indent);
operand2_->dump(out, indent); operand2_->dump(out, indent);
} }
void ExpCast::dump(ostream&out, int indent) const
{
out << "Casting ";
base_->dump(out, indent+4);
out << " to ";
type_->emit_def(out, empty_perm_string);
}
void ExpNew::dump(ostream&out, int indent) const
{
out << "New dynamic array size: ";
size_->dump(out, indent);
}

View File

@ -33,20 +33,20 @@
using namespace std; using namespace std;
int Expression::elaborate_lval(Entity*, Architecture*, bool) int Expression::elaborate_lval(Entity*, ScopeBase*, bool)
{ {
cerr << get_fileline() << ": error: Expression is not a valid l-value." << endl; cerr << get_fileline() << ": error: Expression is not a valid l-value." << endl;
return 1; return 1;
} }
const VType* Expression::probe_type(Entity*, Architecture*) const const VType* Expression::probe_type(Entity*, ScopeBase*) const
{ {
return 0; return 0;
} }
const VType* Expression::fit_type(Entity*ent, Architecture*arc, const VTypeArray*) const const VType* Expression::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) const
{ {
const VType*res = probe_type(ent,arc); const VType*res = probe_type(ent,scope);
if (res == 0) { if (res == 0) {
cerr << get_fileline() << ": internal error: " cerr << get_fileline() << ": internal error: "
<< "fit_type for " << typeid(*this).name() << "fit_type for " << typeid(*this).name()
@ -56,7 +56,7 @@ const VType* Expression::fit_type(Entity*ent, Architecture*arc, const VTypeArray
return res; return res;
} }
const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, Architecture*arc, const VType*type) const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, ScopeBase*scope, const VType*type)
{ {
// Unfold typedefs // Unfold typedefs
while (const VTypeDef*tdef = dynamic_cast<const VTypeDef*>(type)) { while (const VTypeDef*tdef = dynamic_cast<const VTypeDef*>(type)) {
@ -75,9 +75,9 @@ const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, Architecture*arc
int64_t use_msb, use_lsb; int64_t use_msb, use_lsb;
bool flag; bool flag;
flag = index_->evaluate(arc, use_msb); flag = index_->evaluate(scope, use_msb);
ivl_assert(*this, flag); ivl_assert(*this, flag);
flag = lsb_->evaluate(arc, use_lsb); flag = lsb_->evaluate(scope, use_lsb);
ivl_assert(*this, flag); ivl_assert(*this, flag);
Expression*exp_msb = new ExpInteger(use_msb); Expression*exp_msb = new ExpInteger(use_msb);
@ -91,7 +91,7 @@ const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, Architecture*arc
return type; return type;
} }
int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName*suffix) int ExpName::elaborate_lval_(Entity*ent, ScopeBase*scope, bool is_sequ, ExpName*suffix)
{ {
int errors = 0; int errors = 0;
@ -134,13 +134,13 @@ int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName
<< ent->get_name() << "." << endl; << ent->get_name() << "." << endl;
return errors + 1; return errors + 1;
} else if (Signal*sig = arc->find_signal(name_)) { } else if (Signal*sig = scope->find_signal(name_)) {
// Tell the target signal that this may be a sequential l-value. // Tell the target signal that this may be a sequential l-value.
if (is_sequ) sig->count_ref_sequ(); if (is_sequ) sig->count_ref_sequ();
found_type = sig->peek_type(); found_type = sig->peek_type();
} else if (Variable*var = arc->find_variable(name_)) { } else if (Variable*var = scope->find_variable(name_)) {
// Tell the target signal that this may be a sequential l-value. // Tell the target signal that this may be a sequential l-value.
if (is_sequ) var->count_ref_sequ(); if (is_sequ) var->count_ref_sequ();
@ -201,7 +201,7 @@ int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName
return errors; return errors;
} }
suffix_type = suffix->elaborate_adjust_type_with_range_(ent, arc, suffix_type); suffix_type = suffix->elaborate_adjust_type_with_range_(ent, scope, suffix_type);
ivl_assert(*this, suffix_type); ivl_assert(*this, suffix_type);
suffix->set_type(suffix_type); suffix->set_type(suffix_type);
@ -209,12 +209,12 @@ int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName
return errors; return errors;
} }
int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ) int ExpName::elaborate_lval(Entity*ent, ScopeBase*scope, bool is_sequ)
{ {
int errors = 0; int errors = 0;
if (prefix_.get()) { if (prefix_.get()) {
return prefix_->elaborate_lval_(ent, arc, is_sequ, this); return prefix_->elaborate_lval_(ent, scope, is_sequ, this);
} }
const VType*found_type = 0; const VType*found_type = 0;
@ -238,13 +238,13 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ)
<< ent->get_name() << "." << endl; << ent->get_name() << "." << endl;
return 1; return 1;
} else if (Signal*sig = arc->find_signal(name_)) { } else if (Signal*sig = scope->find_signal(name_)) {
// Tell the target signal that this may be a sequential l-value. // Tell the target signal that this may be a sequential l-value.
if (is_sequ) sig->count_ref_sequ(); if (is_sequ) sig->count_ref_sequ();
found_type = sig->peek_type(); found_type = sig->peek_type();
} else if (Variable*var = arc->find_variable(name_)) { } else if (Variable*var = scope->find_variable(name_)) {
// Tell the target signal that this may be a sequential l-value. // Tell the target signal that this may be a sequential l-value.
if (is_sequ) var->count_ref_sequ(); if (is_sequ) var->count_ref_sequ();
@ -257,13 +257,13 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ)
return errors + 1; return errors + 1;
} }
found_type = elaborate_adjust_type_with_range_(ent, arc, found_type); found_type = elaborate_adjust_type_with_range_(ent, scope, found_type);
set_type(found_type); set_type(found_type);
return errors; return errors;
} }
int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lval) int ExpName::elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*lval)
{ {
int errors = 0; int errors = 0;
@ -295,7 +295,7 @@ int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lv
default: default:
break; break;
} }
} else if (arc->find_signal(name_)) { } else if (scope->find_signal(name_)) {
/* OK */ /* OK */
} else if (ent->find_generic(name_)) { } else if (ent->find_generic(name_)) {
@ -310,21 +310,21 @@ int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lv
return errors; return errors;
} }
int ExpNameALL::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ) int ExpNameALL::elaborate_lval(Entity*ent, ScopeBase*scope, bool is_sequ)
{ {
return Expression::elaborate_lval(ent, arc, is_sequ); return Expression::elaborate_lval(ent, scope, is_sequ);
} }
int Expression::elaborate_expr(Entity*, Architecture*, const VType*) int Expression::elaborate_expr(Entity*, ScopeBase*, const VType*)
{ {
cerr << get_fileline() << ": internal error: I don't know how to elaborate expression type=" << typeid(*this).name() << endl; cerr << get_fileline() << ": internal error: I don't know how to elaborate expression type=" << typeid(*this).name() << endl;
return 1; return 1;
} }
const VType* ExpBinary::probe_type(Entity*ent, Architecture*arc) const const VType* ExpBinary::probe_type(Entity*ent, ScopeBase*scope) const
{ {
const VType*t1 = operand1_->probe_type(ent, arc); const VType*t1 = operand1_->probe_type(ent, scope);
const VType*t2 = operand2_->probe_type(ent, arc); const VType*t2 = operand2_->probe_type(ent, scope);
if (t1 == 0) if (t1 == 0)
return t2; return t2;
@ -351,12 +351,12 @@ const VType*ExpBinary::resolve_operand_types_(const VType*, const VType*) const
return 0; return 0;
} }
int ExpBinary::elaborate_exprs(Entity*ent, Architecture*arc, const VType*ltype) int ExpBinary::elaborate_exprs(Entity*ent, ScopeBase*scope, const VType*ltype)
{ {
int errors = 0; int errors = 0;
errors += operand1_->elaborate_expr(ent, arc, ltype); errors += operand1_->elaborate_expr(ent, scope, ltype);
errors += operand2_->elaborate_expr(ent, arc, ltype); errors += operand2_->elaborate_expr(ent, scope, ltype);
return errors; return errors;
} }
@ -365,17 +365,17 @@ int ExpBinary::elaborate_exprs(Entity*ent, Architecture*arc, const VType*ltype)
* return the fit_type for the operand. The assumption is that the * return the fit_type for the operand. The assumption is that the
* operator doesn't change the type. * operator doesn't change the type.
*/ */
const VType*ExpUnary::fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const const VType*ExpUnary::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const
{ {
return operand1_->fit_type(ent, arc, atype); return operand1_->fit_type(ent, scope, atype);
} }
const VType*ExpAggregate::probe_type(Entity*ent, Architecture*arc) const const VType*ExpAggregate::probe_type(Entity*ent, ScopeBase*scope) const
{ {
return Expression::probe_type(ent, arc); return Expression::probe_type(ent, scope);
} }
const VType*ExpAggregate::fit_type(Entity*, Architecture*, const VTypeArray*host) const const VType*ExpAggregate::fit_type(Entity*, ScopeBase*, const VTypeArray*host) const
{ {
ivl_assert(*this, elements_.size() == 1); ivl_assert(*this, elements_.size() == 1);
size_t choice_count = elements_[0]->count_choices(); size_t choice_count = elements_[0]->count_choices();
@ -401,7 +401,7 @@ const VType*ExpAggregate::fit_type(Entity*, Architecture*, const VTypeArray*host
return res; return res;
} }
int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) int ExpAggregate::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{ {
if (ltype == 0) { if (ltype == 0) {
cerr << get_fileline() << ": error: Elaboration of aggregate types needs well known type context?" << endl; cerr << get_fileline() << ": error: Elaboration of aggregate types needs well known type context?" << endl;
@ -415,10 +415,10 @@ int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype
} }
if (const VTypeArray*larray = dynamic_cast<const VTypeArray*>(ltype)) { if (const VTypeArray*larray = dynamic_cast<const VTypeArray*>(ltype)) {
return elaborate_expr_array_(ent, arc, larray); return elaborate_expr_array_(ent, scope, larray);
} }
else if(const VTypeRecord*lrecord = dynamic_cast<const VTypeRecord*>(ltype)) { else if(const VTypeRecord*lrecord = dynamic_cast<const VTypeRecord*>(ltype)) {
return elaborate_expr_record_(ent, arc, lrecord); return elaborate_expr_record_(ent, scope, lrecord);
} }
cerr << get_fileline() << ": internal error: I don't know how to elaborate aggregate expressions. type=" << typeid(*ltype).name() << endl; cerr << get_fileline() << ": internal error: I don't know how to elaborate aggregate expressions. type=" << typeid(*ltype).name() << endl;
@ -430,7 +430,7 @@ int ExpAggregate::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype
* expressions (the elements_ member) using the element type as the * expressions (the elements_ member) using the element type as the
* ltype for the subexpression. * ltype for the subexpression.
*/ */
int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype) int ExpAggregate::elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype)
{ {
const VType*element_type = ltype->element_type(); const VType*element_type = ltype->element_type();
int errors = 0; int errors = 0;
@ -476,7 +476,7 @@ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTyp
if (aggregate_[idx].alias_flag) if (aggregate_[idx].alias_flag)
continue; continue;
errors += aggregate_[idx].expr->elaborate_expr(ent, arc, element_type); errors += aggregate_[idx].expr->elaborate_expr(ent, scope, element_type);
} }
// done with the obsolete elements_ vector. // done with the obsolete elements_ vector.
@ -485,7 +485,7 @@ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTyp
return errors; return errors;
} }
int ExpAggregate::elaborate_expr_record_(Entity*ent, Architecture*arc, const VTypeRecord*ltype) int ExpAggregate::elaborate_expr_record_(Entity*ent, ScopeBase*scope, const VTypeRecord*ltype)
{ {
int errors = 0; int errors = 0;
@ -513,10 +513,12 @@ int ExpAggregate::elaborate_expr_record_(Entity*ent, Architecture*arc, const VTy
ivl_assert(*this, field); ivl_assert(*this, field);
perm_string field_name = field->peek_name(); perm_string field_name = field->peek_name();
idx = -1;
const VTypeRecord::element_t*el = ltype->element_by_name(field_name, &idx); const VTypeRecord::element_t*el = ltype->element_by_name(field_name, &idx);
ivl_assert(*this, idx >= 0);
aggregate_[idx] = tmp; aggregate_[idx] = tmp;
errors += aggregate_[idx].expr->elaborate_expr(ent, arc, el->peek_type()); errors += aggregate_[idx].expr->elaborate_expr(ent, scope, el->peek_type());
} }
// done with the obsolete elements_ vector. // done with the obsolete elements_ vector.
@ -535,16 +537,16 @@ void ExpAggregate::element_t::map_choices(ExpAggregate::choice_element*dst)
} }
} }
int ExpArithmetic::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) int ExpArithmetic::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{ {
int errors = 0; int errors = 0;
if (ltype == 0) { if (ltype == 0) {
ltype = probe_type(ent, arc); ltype = probe_type(ent, scope);
} }
ivl_assert(*this, ltype != 0); ivl_assert(*this, ltype != 0);
errors += elaborate_exprs(ent, arc, ltype); errors += elaborate_exprs(ent, scope, ltype);
return errors; return errors;
} }
@ -563,9 +565,9 @@ const VType* ExpArithmetic::resolve_operand_types_(const VType*t1, const VType*t
return 0; return 0;
} }
const VType* ExpAttribute::probe_type(Entity*ent, Architecture*arc) const const VType* ExpAttribute::probe_type(Entity*ent, ScopeBase*scope) const
{ {
base_->probe_type(ent, arc); base_->probe_type(ent, scope);
if (name_ == "length" || name_ == "left" || name_ == "right") { if (name_ == "length" || name_ == "left" || name_ == "right") {
return &primitive_INTEGER; return &primitive_INTEGER;
@ -574,42 +576,46 @@ const VType* ExpAttribute::probe_type(Entity*ent, Architecture*arc) const
return 0; return 0;
} }
int ExpAttribute::elaborate_expr(Entity*ent, Architecture*arc, const VType*) int ExpAttribute::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
{ {
int errors = 0; int errors = 0;
const VType*sub_type = base_->probe_type(ent, arc); const VType*sub_type = base_->probe_type(ent, scope);
errors += base_->elaborate_expr(ent, arc, sub_type); errors += base_->elaborate_expr(ent, scope, sub_type);
return errors; return errors;
} }
const VType*ExpBitstring::fit_type(Entity*, Architecture*, const VTypeArray*atype) const const VType*ExpBitstring::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) const
{ {
// Really should check that this string can work with the // Really should check that this string can work with the
// array element type? // array element type?
return atype->element_type(); return atype->element_type();
} }
int ExpBitstring::elaborate_expr(Entity*, Architecture*, const VType*) int ExpBitstring::elaborate_expr(Entity*, ScopeBase*, const VType*)
{ {
int errors = 0; int errors = 0;
std::vector<VTypeArray::range_t> range;
range.push_back(VTypeArray::range_t(new ExpInteger(value_.size() - 1), new ExpInteger(0)));
const VTypeArray*type = new VTypeArray(&primitive_STDLOGIC, range);
set_type(type);
return errors; return errors;
} }
const VType*ExpCharacter::fit_type(Entity*, Architecture*, const VTypeArray*atype) const const VType*ExpCharacter::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) const
{ {
// Really should check that this character can work with the // Really should check that this character can work with the
// array element type? // array element type?
return atype->element_type(); return atype->element_type();
} }
int ExpCharacter::elaborate_expr(Entity*, Architecture*, const VType*ltype) int ExpCharacter::elaborate_expr(Entity*, ScopeBase*, const VType*ltype)
{ {
ivl_assert(*this, ltype != 0); ivl_assert(*this, ltype != 0);
set_type(ltype); set_type(ltype);
return 0; return 0;
} }
const VType*ExpConcat::fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const const VType*ExpConcat::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const
{ {
Expression*operands[2] = {operand1_, operand2_}; Expression*operands[2] = {operand1_, operand2_};
const VType*types[2] = {NULL, NULL}; const VType*types[2] = {NULL, NULL};
@ -617,7 +623,7 @@ const VType*ExpConcat::fit_type(Entity*ent, Architecture*arc, const VTypeArray*a
// determine the type and size of concatenated expressions // determine the type and size of concatenated expressions
for(int i = 0; i < 2; ++i) { for(int i = 0; i < 2; ++i) {
types[i] = operands[i]->fit_type(ent, arc, atype); types[i] = operands[i]->fit_type(ent, scope, atype);
if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(types[i])) { if(const VTypeArray*arr = dynamic_cast<const VTypeArray*>(types[i])) {
types[i] = arr->element_type(); types[i] = arr->element_type();
@ -645,62 +651,62 @@ const VType*ExpConcat::fit_type(Entity*ent, Architecture*arc, const VTypeArray*a
/* /*
* I don't know how to probe the type of a concatenation, quite yet. * I don't know how to probe the type of a concatenation, quite yet.
*/ */
const VType*ExpConcat::probe_type(Entity*, Architecture*) const const VType*ExpConcat::probe_type(Entity*, ScopeBase*) const
{ {
ivl_assert(*this, 0); ivl_assert(*this, 0);
return 0; return 0;
} }
int ExpConcat::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) int ExpConcat::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{ {
int errors = 0; int errors = 0;
if (ltype == 0) { if (ltype == 0) {
ltype = probe_type(ent, arc); ltype = probe_type(ent, scope);
} }
ivl_assert(*this, ltype != 0); ivl_assert(*this, ltype != 0);
if (const VTypeArray*atype = dynamic_cast<const VTypeArray*>(ltype)) { if (const VTypeArray*atype = dynamic_cast<const VTypeArray*>(ltype)) {
errors += elaborate_expr_array_(ent, arc, atype); errors += elaborate_expr_array_(ent, scope, atype);
} else { } else {
errors += operand1_->elaborate_expr(ent, arc, ltype); errors += operand1_->elaborate_expr(ent, scope, ltype);
errors += operand2_->elaborate_expr(ent, arc, ltype); errors += operand2_->elaborate_expr(ent, scope, ltype);
} }
return errors; return errors;
} }
int ExpConcat::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*atype) int ExpConcat::elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*atype)
{ {
int errors = 0; int errors = 0;
// For now, only support single-dimension arrays here. // For now, only support single-dimension arrays here.
ivl_assert(*this, atype->dimensions() == 1); ivl_assert(*this, atype->dimensions() == 1);
const VType*type1 = operand1_->fit_type(ent, arc, atype); const VType*type1 = operand1_->fit_type(ent, scope, atype);
ivl_assert(*this, type1); ivl_assert(*this, type1);
const VType*type2 = operand2_->fit_type(ent, arc, atype); const VType*type2 = operand2_->fit_type(ent, scope, atype);
ivl_assert(*this, type2); ivl_assert(*this, type2);
errors += operand1_->elaborate_expr(ent, arc, type1); errors += operand1_->elaborate_expr(ent, scope, type1);
errors += operand2_->elaborate_expr(ent, arc, type2); errors += operand2_->elaborate_expr(ent, scope, type2);
return errors; return errors;
} }
const VType* ExpConditional::probe_type(Entity*, Architecture*) const const VType* ExpConditional::probe_type(Entity*, ScopeBase*) const
{ {
return 0; return 0;
} }
int ExpConditional::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) int ExpConditional::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{ {
int errors = 0; int errors = 0;
if (ltype == 0) if (ltype == 0)
ltype = probe_type(ent, arc); ltype = probe_type(ent, scope);
ivl_assert(*this, ltype); ivl_assert(*this, ltype);
@ -708,42 +714,42 @@ int ExpConditional::elaborate_expr(Entity*ent, Architecture*arc, const VType*lty
/* Note that the type for the condition expression need not /* Note that the type for the condition expression need not
have anything to do with the type of this expression. */ have anything to do with the type of this expression. */
errors += cond_->elaborate_expr(ent, arc, 0); errors += cond_->elaborate_expr(ent, scope, 0);
for (list<Expression*>::const_iterator cur = true_clause_.begin() for (list<Expression*>::const_iterator cur = true_clause_.begin()
; cur != true_clause_.end() ; ++cur) { ; cur != true_clause_.end() ; ++cur) {
errors += (*cur)->elaborate_expr(ent, arc, ltype); errors += (*cur)->elaborate_expr(ent, scope, ltype);
} }
for (list<else_t*>::const_iterator cur = else_clause_.begin() for (list<else_t*>::const_iterator cur = else_clause_.begin()
; cur != else_clause_.end() ; ++cur) { ; cur != else_clause_.end() ; ++cur) {
errors += (*cur)->elaborate_expr(ent, arc, ltype); errors += (*cur)->elaborate_expr(ent, scope, ltype);
} }
return errors; return errors;
} }
int ExpConditional::else_t::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) int ExpConditional::else_t::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{ {
int errors = 0; int errors = 0;
if (cond_) if (cond_)
errors += cond_->elaborate_expr(ent, arc, 0); errors += cond_->elaborate_expr(ent, scope, 0);
for (list<Expression*>::const_iterator cur = true_clause_.begin() for (list<Expression*>::const_iterator cur = true_clause_.begin()
; cur != true_clause_.end() ; ++cur) { ; cur != true_clause_.end() ; ++cur) {
errors += (*cur)->elaborate_expr(ent, arc, ltype); errors += (*cur)->elaborate_expr(ent, scope, ltype);
} }
return errors; return errors;
} }
int ExpFunc::elaborate_expr(Entity*ent, Architecture*arc, const VType*) int ExpFunc::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
{ {
int errors = 0; int errors = 0;
ivl_assert(*this, arc); ivl_assert(*this, scope);
Subprogram*prog = arc->find_subprogram(name_); Subprogram*prog = scope->find_subprogram(name_);
if(!prog) if(!prog)
prog = library_find_subprogram(name_); prog = library_find_subprogram(name_);
@ -751,27 +757,36 @@ int ExpFunc::elaborate_expr(Entity*ent, Architecture*arc, const VType*)
ivl_assert(*this, def_==0); ivl_assert(*this, def_==0);
def_ = prog; def_ = prog;
// Elaborate arguments
for (size_t idx = 0 ; idx < argv_.size() ; idx += 1) { for (size_t idx = 0 ; idx < argv_.size() ; idx += 1) {
const VType*tmp = argv_[idx]->probe_type(ent, arc); const VType*tmp = argv_[idx]->probe_type(ent, scope);
if(!tmp && prog) const VType*param_type = prog ? prog->peek_param_type(idx) : NULL;
tmp = prog->peek_param_type(idx);
errors += argv_[idx]->elaborate_expr(ent, arc, tmp); if(!tmp && param_type)
tmp = param_type;
errors += argv_[idx]->elaborate_expr(ent, scope, tmp);
}
if(def_ && def_->unbounded()) {
def_ = prog->make_instance(argv_, scope);
name_ = def_->name();
} }
return errors; return errors;
} }
const VType* ExpInteger::probe_type(Entity*, Architecture*) const const VType* ExpInteger::probe_type(Entity*, ScopeBase*) const
{ {
return &primitive_INTEGER; return &primitive_INTEGER;
} }
int ExpInteger::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) int ExpInteger::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{ {
int errors = 0; int errors = 0;
if (ltype == 0) { if (ltype == 0) {
ltype = probe_type(ent, arc); ltype = probe_type(ent, scope);
} }
ivl_assert(*this, ltype != 0); ivl_assert(*this, ltype != 0);
@ -779,17 +794,17 @@ int ExpInteger::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
return errors; return errors;
} }
const VType* ExpReal::probe_type(Entity*, Architecture*) const const VType* ExpReal::probe_type(Entity*, ScopeBase*) const
{ {
return &primitive_REAL; return &primitive_REAL;
} }
int ExpReal::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) int ExpReal::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{ {
int errors = 0; int errors = 0;
if (ltype == 0) { if (ltype == 0) {
ltype = probe_type(ent, arc); ltype = probe_type(ent, scope);
} }
ivl_assert(*this, ltype != 0); ivl_assert(*this, ltype != 0);
@ -797,27 +812,27 @@ int ExpReal::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
return errors; return errors;
} }
int ExpLogical::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) int ExpLogical::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{ {
int errors = 0; int errors = 0;
if (ltype == 0) { if (ltype == 0) {
ltype = probe_type(ent, arc); ltype = probe_type(ent, scope);
} }
ivl_assert(*this, ltype != 0); ivl_assert(*this, ltype != 0);
errors += elaborate_exprs(ent, arc, ltype); errors += elaborate_exprs(ent, scope, ltype);
return errors; return errors;
} }
const VType* ExpName::probe_prefix_type_(Entity*ent, Architecture*arc) const const VType* ExpName::probe_prefix_type_(Entity*ent, ScopeBase*scope) const
{ {
if (prefix_.get()) { if (prefix_.get()) {
cerr << get_fileline() << ": sorry: I do not know how to support nested prefix parts." << endl; cerr << get_fileline() << ": sorry: I do not know how to support nested prefix parts." << endl;
return 0; return 0;
} }
const VType*type = probe_type(ent, arc); const VType*type = probe_type(ent, scope);
return type; return type;
} }
@ -826,10 +841,10 @@ const VType* ExpName::probe_prefix_type_(Entity*ent, Architecture*arc) const
* that have prefix parts. In this case we try to get the type of the * that have prefix parts. In this case we try to get the type of the
* prefix and interpret the name in that context. * prefix and interpret the name in that context.
*/ */
const VType* ExpName::probe_prefixed_type_(Entity*ent, Architecture*arc) const const VType* ExpName::probe_prefixed_type_(Entity*ent, ScopeBase*scope) const
{ {
// First, get the type of the prefix. // First, get the type of the prefix.
const VType*prefix_type = prefix_->probe_prefix_type_(ent, arc); const VType*prefix_type = prefix_->probe_prefix_type_(ent, scope);
if (prefix_type == 0) { if (prefix_type == 0) {
return 0; return 0;
} }
@ -857,34 +872,40 @@ const VType* ExpName::probe_prefixed_type_(Entity*ent, Architecture*arc) const
return 0; return 0;
} }
const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const const VType* ExpName::probe_type(Entity*ent, ScopeBase*scope) const
{ {
if (prefix_.get()) if (prefix_.get())
return probe_prefixed_type_(ent, arc); return probe_prefixed_type_(ent, scope);
if (const InterfacePort*cur = ent->find_port(name_)) { if(ent) {
ivl_assert(*this, cur->type); if (const InterfacePort*cur = ent->find_port(name_)) {
return cur->type; ivl_assert(*this, cur->type);
return cur->type;
}
if (const InterfacePort*cur = ent->find_generic(name_)) {
ivl_assert(*this, cur->type);
return cur->type;
}
} }
if (const InterfacePort*cur = ent->find_generic(name_)) { if(scope) {
ivl_assert(*this, cur->type); if (Signal*sig = scope->find_signal(name_))
return cur->type; return sig->peek_type();
}
if (Signal*sig = arc->find_signal(name_)) if (Variable*var = scope->find_variable(name_))
return sig->peek_type(); return var->peek_type();
if (Variable*var = arc->find_variable(name_)) const VType*ctype = 0;
return var->peek_type(); Expression*cval = 0;
if (scope->find_constant(name_, ctype, cval))
return ctype;
const VType*ctype = 0; const VType*gtype = 0;
Expression*cval = 0; Architecture*arc = dynamic_cast<Architecture*>(scope);
if (arc->find_constant(name_, ctype, cval)) if (arc && (gtype = arc->probe_genvar_type(name_))) {
return ctype; return gtype;
}
if (const VType*gtype = arc->probe_genvar_type(name_)) {
return gtype;
} }
cerr << get_fileline() << ": error: Signal/variable " << name_ cerr << get_fileline() << ": error: Signal/variable " << name_
@ -892,12 +913,12 @@ const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const
return 0; return 0;
} }
const VType* ExpName::fit_type(Entity*ent, Architecture*arc, const VTypeArray*)const const VType* ExpName::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*)const
{ {
return probe_type(ent, arc); return probe_type(ent, scope);
} }
int ExpName::elaborate_expr(Entity*, Architecture*, const VType*ltype) int ExpName::elaborate_expr(Entity*, ScopeBase*, const VType*ltype)
{ {
if (ltype) { if (ltype) {
ivl_assert(*this, ltype != 0); ivl_assert(*this, ltype != 0);
@ -907,22 +928,22 @@ int ExpName::elaborate_expr(Entity*, Architecture*, const VType*ltype)
return 0; return 0;
} }
const VType* ExpNameALL::probe_type(Entity*, Architecture*) const const VType* ExpNameALL::probe_type(Entity*, ScopeBase*) const
{ {
return 0; return 0;
} }
const VType* ExpRelation::probe_type(Entity*, Architecture*) const const VType* ExpRelation::probe_type(Entity*, ScopeBase*) const
{ {
return &primitive_BOOLEAN; return &primitive_BOOLEAN;
} }
int ExpRelation::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) int ExpRelation::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{ {
int errors = 0; int errors = 0;
if (ltype == 0) { if (ltype == 0) {
ltype = probe_type(ent, arc); ltype = probe_type(ent, scope);
} }
ivl_assert(*this, ltype != 0); ivl_assert(*this, ltype != 0);
@ -930,8 +951,8 @@ int ExpRelation::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
// The type of the operands must match, but need not match the // The type of the operands must match, but need not match the
// type for the ExpRelation itself. So get the operand type // type for the ExpRelation itself. So get the operand type
// separately. // separately.
const VType*otype = ExpBinary::probe_type(ent, arc); const VType*otype = ExpBinary::probe_type(ent, scope);
errors += elaborate_exprs(ent, arc, otype); errors += elaborate_exprs(ent, scope, otype);
return errors; return errors;
} }
@ -941,7 +962,7 @@ int ExpRelation::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
* string is an array with the same element type of the concatenation, * string is an array with the same element type of the concatenation,
* but with elements for each character of the string. * but with elements for each character of the string.
*/ */
const VType*ExpString::fit_type(Entity*, Architecture*, const VTypeArray*atype) const const VType*ExpString::fit_type(Entity*, ScopeBase*, const VTypeArray*atype) const
{ {
vector<VTypeArray::range_t> range (atype->dimensions()); vector<VTypeArray::range_t> range (atype->dimensions());
@ -957,14 +978,14 @@ const VType*ExpString::fit_type(Entity*, Architecture*, const VTypeArray*atype)
return type; return type;
} }
int ExpString::elaborate_expr(Entity*, Architecture*, const VType*ltype) int ExpString::elaborate_expr(Entity*, ScopeBase*, const VType*ltype)
{ {
ivl_assert(*this, ltype != 0); ivl_assert(*this, ltype != 0);
set_type(ltype); set_type(ltype);
return 0; return 0;
} }
int ExpUNot::elaborate_expr(Entity*, Architecture*, const VType*ltype) int ExpUNot::elaborate_expr(Entity*, ScopeBase*, const VType*ltype)
{ {
ivl_assert(*this, ltype != 0); ivl_assert(*this, ltype != 0);
set_type(ltype); set_type(ltype);

View File

@ -33,7 +33,7 @@
using namespace std; using namespace std;
int Expression::emit(ostream&out, Entity*, Architecture*) int Expression::emit(ostream&out, Entity*, ScopeBase*)
{ {
out << " /* " << get_fileline() << ": internal error: " out << " /* " << get_fileline() << ": internal error: "
<< "I don't know how to emit this expression! " << "I don't know how to emit this expression! "
@ -54,34 +54,34 @@ bool Expression::is_primary(void) const
return false; return false;
} }
int ExpBinary::emit_operand1(ostream&out, Entity*ent, Architecture*arc) int ExpBinary::emit_operand1(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
bool oper_primary = operand1_->is_primary(); bool oper_primary = operand1_->is_primary();
if (! oper_primary) out << "("; if (! oper_primary) out << "(";
errors += operand1_->emit(out, ent, arc); errors += operand1_->emit(out, ent, scope);
if (! oper_primary) out << ")"; if (! oper_primary) out << ")";
return errors; return errors;
} }
int ExpBinary::emit_operand2(ostream&out, Entity*ent, Architecture*arc) int ExpBinary::emit_operand2(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
bool oper_primary = operand2_->is_primary(); bool oper_primary = operand2_->is_primary();
if (! oper_primary) out << "("; if (! oper_primary) out << "(";
errors += operand2_->emit(out, ent, arc); errors += operand2_->emit(out, ent, scope);
if (! oper_primary) out << ")"; if (! oper_primary) out << ")";
return errors; return errors;
} }
int ExpUnary::emit_operand1(ostream&out, Entity*ent, Architecture*arc) int ExpUnary::emit_operand1(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
errors += operand1_->emit(out, ent, arc); errors += operand1_->emit(out, ent, scope);
return errors; return errors;
} }
int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc) int ExpAggregate::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
if (peek_type() == 0) { if (peek_type() == 0) {
out << "/* " << get_fileline() << ": internal error: " out << "/* " << get_fileline() << ": internal error: "
@ -95,9 +95,9 @@ int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc)
} }
if (const VTypeArray*atype = dynamic_cast<const VTypeArray*> (use_type)) if (const VTypeArray*atype = dynamic_cast<const VTypeArray*> (use_type))
return emit_array_(out, ent, arc, atype); return emit_array_(out, ent, scope, atype);
else if (const VTypeRecord*arecord = dynamic_cast<const VTypeRecord*> (use_type)) else if (const VTypeRecord*arecord = dynamic_cast<const VTypeRecord*> (use_type))
return emit_record_(out, ent, arc, arecord); return emit_record_(out, ent, scope, arecord);
out << "/* " << get_fileline() << ": internal error: " out << "/* " << get_fileline() << ": internal error: "
<< "I don't know how to elab/emit aggregate in " << typeid(use_type).name() << "I don't know how to elab/emit aggregate in " << typeid(use_type).name()
@ -105,7 +105,7 @@ int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc)
return 1; return 1;
} }
int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*atype) int ExpAggregate::emit_array_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeArray*atype)
{ {
int errors = 0; int errors = 0;
@ -119,14 +119,14 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
int64_t use_msb; int64_t use_msb;
int64_t use_lsb; int64_t use_lsb;
bool rc_msb, rc_lsb; bool rc_msb, rc_lsb;
rc_msb = rang.msb()->evaluate(ent, arc, use_msb); rc_msb = rang.msb()->evaluate(ent, scope, use_msb);
rc_lsb = rang.lsb()->evaluate(ent, arc, use_lsb); rc_lsb = rang.lsb()->evaluate(ent, scope, use_lsb);
if (rc_msb && rc_lsb) { if (rc_msb && rc_lsb) {
int asize = (use_msb >= use_lsb) ? (use_msb - use_lsb) + 1 : int asize = (use_msb >= use_lsb) ? (use_msb - use_lsb) + 1 :
(use_lsb - use_msb) + 1; (use_lsb - use_msb) + 1;
out << "{" << asize << "{"; out << "{" << asize << "{";
errors += aggregate_[0].expr->emit(out, ent, arc); errors += aggregate_[0].expr->emit(out, ent, scope);
out << "}}"; out << "}}";
} else { } else {
out << "{("; out << "{(";
@ -134,7 +134,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
out << use_msb; out << use_msb;
} else { } else {
out << "("; out << "(";
errors += rang.msb()->emit(out, ent, arc); errors += rang.msb()->emit(out, ent, scope);
out << ")"; out << ")";
} }
if (rc_lsb && use_lsb==0) { if (rc_lsb && use_lsb==0) {
@ -142,11 +142,11 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
out << "-" << use_lsb; out << "-" << use_lsb;
} else { } else {
out << "-("; out << "-(";
errors += rang.lsb()->emit(out, ent, arc); errors += rang.lsb()->emit(out, ent, scope);
out << ")"; out << ")";
} }
out << "+1){"; out << "+1){";
errors += aggregate_[0].expr->emit(out, ent, arc); errors += aggregate_[0].expr->emit(out, ent, scope);
out << "}}"; out << "}}";
} }
return errors; return errors;
@ -158,9 +158,9 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
// Fully calculate the range numbers. // Fully calculate the range numbers.
int64_t use_msb, use_lsb; int64_t use_msb, use_lsb;
bool rc; bool rc;
rc = rang.msb()->evaluate(ent, arc, use_msb); rc = rang.msb()->evaluate(ent, scope, use_msb);
ivl_assert(*this, rc); ivl_assert(*this, rc);
rc = rang.lsb()->evaluate(ent, arc, use_lsb); rc = rang.lsb()->evaluate(ent, scope, use_lsb);
ivl_assert(*this, rc); ivl_assert(*this, rc);
if(use_msb < use_lsb) if(use_msb < use_lsb)
swap(use_msb, use_lsb); swap(use_msb, use_lsb);
@ -198,14 +198,14 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
if (prange_t*range = aggregate_[idx].choice->range_expressions()) { if (prange_t*range = aggregate_[idx].choice->range_expressions()) {
int64_t begin_val, end_val; int64_t begin_val, end_val;
if (! range->msb()->evaluate(ent, arc, begin_val)) { if (! range->msb()->evaluate(ent, scope, begin_val)) {
cerr << range->msb()->get_fileline() << ": error: " cerr << range->msb()->get_fileline() << ": error: "
<< "Unable to evaluate aggregate choice expression." << endl; << "Unable to evaluate aggregate choice expression." << endl;
errors += 1; errors += 1;
continue; continue;
} }
if (! range->lsb()->evaluate(ent, arc, end_val)) { if (! range->lsb()->evaluate(ent, scope, end_val)) {
cerr << range->msb()->get_fileline() << ": error: " cerr << range->msb()->get_fileline() << ": error: "
<< "Unable to evaluate aggregate choice expression." << endl; << "Unable to evaluate aggregate choice expression." << endl;
errors += 1; errors += 1;
@ -235,7 +235,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
// elements so disable further positional // elements so disable further positional
// processing. // processing.
positional_section = false; positional_section = false;
if (! tmp->evaluate(ent, arc, tmp_val)) { if (! tmp->evaluate(ent, scope, tmp_val)) {
cerr << tmp->get_fileline() << ": error: " cerr << tmp->get_fileline() << ": error: "
<< "Unable to evaluate aggregate choice expression." << endl; << "Unable to evaluate aggregate choice expression." << endl;
errors += 1; errors += 1;
@ -266,7 +266,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
<< "Missing element " << idx << "." << endl; << "Missing element " << idx << "." << endl;
errors += 1; errors += 1;
} else { } else {
errors += cur->expr->emit(out, ent, arc); errors += cur->expr->emit(out, ent, scope);
} }
} }
out << "}"; out << "}";
@ -274,7 +274,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
return errors; return errors;
} }
int ExpAggregate::emit_record_(ostream&out, Entity*ent, Architecture*arc, const VTypeRecord*) int ExpAggregate::emit_record_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeRecord*)
{ {
int errors = 0; int errors = 0;
@ -292,9 +292,9 @@ int ExpAggregate::emit_record_(ostream&out, Entity*ent, Architecture*arc, const
if(idx != 0) if(idx != 0)
out << ","; out << ",";
//errors += name->emit(out, ent, arc); //errors += name->emit(out, ent, scope);
//out << ": "; //out << ": ";
errors += val->emit(out, ent, arc); errors += val->emit(out, ent, scope);
} }
out << "}"; out << "}";
@ -302,13 +302,13 @@ int ExpAggregate::emit_record_(ostream&out, Entity*ent, Architecture*arc, const
return errors; return errors;
} }
int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc) int ExpAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
if (name_ == "event") { if (name_ == "event") {
out << "$ivlh_attribute_event("; out << "$ivlh_attribute_event(";
errors += base_->emit(out, ent, arc); errors += base_->emit(out, ent, scope);
out << ")"; out << ")";
return errors; return errors;
} }
@ -319,27 +319,27 @@ int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc)
expression doesn't even need to be evaluated.) */ expression doesn't even need to be evaluated.) */
if (name_=="length") { if (name_=="length") {
out << "$bits("; out << "$bits(";
errors += base_->emit(out, ent, arc); errors += base_->emit(out, ent, scope);
out << ")"; out << ")";
return errors; return errors;
} else if (name_=="left" || name_=="right") { } else if (name_=="left" || name_=="right") {
out << "$" << name_ << "("; out << "$" << name_ << "(";
errors += base_->emit(out, ent, arc); errors += base_->emit(out, ent, scope);
out << ")"; out << ")";
return errors; return errors;
} }
out << "$ivl_attribute("; out << "$ivl_attribute(";
errors += base_->emit(out, ent, arc); errors += base_->emit(out, ent, scope);
out << ", \"" << name_ << "\")"; out << ", \"" << name_ << "\")";
return errors; return errors;
} }
int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc) int ExpArithmetic::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
errors += emit_operand1(out, ent, arc); errors += emit_operand1(out, ent, scope);
switch (fun_) { switch (fun_) {
case PLUS: case PLUS:
@ -369,12 +369,12 @@ int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc)
break; break;
} }
errors += emit_operand2(out, ent, arc); errors += emit_operand2(out, ent, scope);
return errors; return errors;
} }
int ExpBitstring::emit(ostream&out, Entity*, Architecture*) int ExpBitstring::emit(ostream&out, Entity*, ScopeBase*)
{ {
int errors = 0; int errors = 0;
@ -385,7 +385,7 @@ int ExpBitstring::emit(ostream&out, Entity*, Architecture*)
return errors; return errors;
} }
int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, Architecture*, int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, ScopeBase*,
const VTypePrimitive*etype) const VTypePrimitive*etype)
{ {
switch (etype->type()) { switch (etype->type()) {
@ -407,17 +407,17 @@ int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, Architecture*,
return 1; return 1;
} }
int ExpCharacter::emit(ostream&out, Entity*ent, Architecture*arc) int ExpCharacter::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
const VType*etype = peek_type(); const VType*etype = peek_type();
if (const VTypePrimitive*use_type = dynamic_cast<const VTypePrimitive*>(etype)) { if (const VTypePrimitive*use_type = dynamic_cast<const VTypePrimitive*>(etype)) {
return emit_primitive_bit_(out, ent, arc, use_type); return emit_primitive_bit_(out, ent, scope, use_type);
} }
if (const VTypeArray*array = dynamic_cast<const VTypeArray*>(etype)) { if (const VTypeArray*array = dynamic_cast<const VTypeArray*>(etype)) {
if (const VTypePrimitive*use_type = dynamic_cast<const VTypePrimitive*>(array->element_type())) { if (const VTypePrimitive*use_type = dynamic_cast<const VTypePrimitive*>(array->element_type())) {
return emit_primitive_bit_(out, ent, arc, use_type); return emit_primitive_bit_(out, ent, scope, use_type);
} }
} }
@ -439,22 +439,22 @@ bool ExpConcat::is_primary(void) const
return true; return true;
} }
int ExpConcat::emit(ostream&out, Entity*ent, Architecture*arc) int ExpConcat::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
out << "{"; out << "{";
errors += operand1_->emit(out, ent, arc); errors += operand1_->emit(out, ent, scope);
out << ", "; out << ", ";
errors += operand2_->emit(out, ent, arc); errors += operand2_->emit(out, ent, scope);
out << "}"; out << "}";
return errors; return errors;
} }
int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc) int ExpConditional::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
out << "("; out << "(";
errors += cond_->emit(out, ent, arc); errors += cond_->emit(out, ent, scope);
out << ")? ("; out << ")? (";
if (true_clause_.size() > 1) { if (true_clause_.size() > 1) {
@ -463,7 +463,7 @@ int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc)
} }
Expression*tmp = true_clause_.front(); Expression*tmp = true_clause_.front();
errors += tmp->emit(out, ent, arc); errors += tmp->emit(out, ent, scope);
out << ") : ("; out << ") : (";
@ -475,11 +475,11 @@ int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc)
for (list<else_t*>::iterator cur = else_clause_.begin() for (list<else_t*>::iterator cur = else_clause_.begin()
; cur != last ; ++cur) { ; cur != last ; ++cur) {
errors += (*cur) ->emit_when_else(out, ent, arc); errors += (*cur) ->emit_when_else(out, ent, scope);
} }
} }
errors += else_clause_.back()->emit_else(out, ent, arc); errors += else_clause_.back()->emit_else(out, ent, scope);
out << ")"; out << ")";
// The emit_when_else() functions do not close the last // The emit_when_else() functions do not close the last
@ -492,13 +492,13 @@ int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc)
return errors; return errors;
} }
int ExpConditional::else_t::emit_when_else(ostream&out, Entity*ent, Architecture*arc) int ExpConditional::else_t::emit_when_else(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
assert(cond_ != 0); assert(cond_ != 0);
out << "("; out << "(";
errors += cond_->emit(out, ent, arc); errors += cond_->emit(out, ent, scope);
out << ")? ("; out << ")? (";
if (true_clause_.size() > 1) { if (true_clause_.size() > 1) {
@ -507,14 +507,14 @@ int ExpConditional::else_t::emit_when_else(ostream&out, Entity*ent, Architecture
} }
Expression*tmp = true_clause_.front(); Expression*tmp = true_clause_.front();
errors += tmp->emit(out, ent, arc); errors += tmp->emit(out, ent, scope);
out << ") : ("; out << ") : (";
return errors; return errors;
} }
int ExpConditional::else_t::emit_else(ostream&out, Entity*ent, Architecture*arc) int ExpConditional::else_t::emit_else(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
// Trailing else must have no condition. // Trailing else must have no condition.
@ -526,12 +526,12 @@ int ExpConditional::else_t::emit_else(ostream&out, Entity*ent, Architecture*arc)
} }
Expression*tmp = true_clause_.front(); Expression*tmp = true_clause_.front();
errors += tmp->emit(out, ent, arc); errors += tmp->emit(out, ent, scope);
return errors; return errors;
} }
int ExpEdge::emit(ostream&out, Entity*ent, Architecture*arc) int ExpEdge::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
switch (fun_) { switch (fun_) {
@ -544,11 +544,11 @@ int ExpEdge::emit(ostream&out, Entity*ent, Architecture*arc)
case ANYEDGE: case ANYEDGE:
break; break;
} }
errors += emit_operand1(out, ent, arc); errors += emit_operand1(out, ent, scope);
return errors; return errors;
} }
int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc) int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
@ -558,46 +558,46 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
// std numeric library, but we interpret it as the same // std numeric library, but we interpret it as the same
// as the $unsigned function. // as the $unsigned function.
out << "$unsigned("; out << "$unsigned(";
errors += argv_[0]->emit(out, ent, arc); errors += argv_[0]->emit(out, ent, scope);
out << ")"; out << ")";
} else if (name_ == "integer" && argv_.size() == 1) { } else if (name_ == "integer" && argv_.size() == 1) {
// Simply skip the function name, SystemVerilog takes care of out << "$signed(";
// rounding real numbers errors += argv_[0]->emit(out, ent, scope);
errors += argv_[0]->emit(out, ent, arc); out << ")";
} else if (name_ == "std_logic_vector" && argv_.size() == 1) { } else if (name_ == "std_logic_vector" && argv_.size() == 1) {
// Special case: The std_logic_vector function casts its // Special case: The std_logic_vector function casts its
// argument to std_logic_vector. Internally, we don't // argument to std_logic_vector. Internally, we don't
// have to do anything for that to work. // have to do anything for that to work.
out << "("; out << "(";
errors += argv_[0]->emit(out, ent, arc); errors += argv_[0]->emit(out, ent, scope);
out << ")"; out << ")";
} else if (name_ == "to_unsigned" && argv_.size() == 2) { } else if (name_ == "to_unsigned" && argv_.size() == 2) {
out << "$ivlh_to_unsigned("; out << "$ivlh_to_unsigned(";
errors += argv_[0]->emit(out, ent, arc); errors += argv_[0]->emit(out, ent, scope);
out << ", "; out << ", ";
errors += argv_[1]->emit(out, ent, arc); errors += argv_[1]->emit(out, ent, scope);
out << ")"; out << ")";
} else if (name_ == "conv_std_logic_vector" && argv_.size() == 2) { } else if (name_ == "conv_std_logic_vector" && argv_.size() == 2) {
int64_t use_size; int64_t use_size;
bool rc = argv_[1]->evaluate(ent, arc, use_size); bool rc = argv_[1]->evaluate(ent, scope, use_size);
ivl_assert(*this, rc); ivl_assert(*this, rc);
out << use_size << "'("; out << use_size << "'(";
errors += argv_[0]->emit(out, ent, arc); errors += argv_[0]->emit(out, ent, scope);
out << ")"; out << ")";
} else if (name_ == "rising_edge" && argv_.size()==1) { } else if (name_ == "rising_edge" && argv_.size()==1) {
out << "$ivlh_rising_edge("; out << "$ivlh_rising_edge(";
errors += argv_[0]->emit(out, ent, arc); errors += argv_[0]->emit(out, ent, scope);
out << ")"; out << ")";
} else if (name_ == "falling_edge" && argv_.size()==1) { } else if (name_ == "falling_edge" && argv_.size()==1) {
out << "$ivlh_falling_edge("; out << "$ivlh_falling_edge(";
errors += argv_[0]->emit(out, ent, arc); errors += argv_[0]->emit(out, ent, scope);
out << ")"; out << ")";
} else { } else {
@ -615,7 +615,7 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
out << "\\" << name_ << " ("; out << "\\" << name_ << " (";
for (size_t idx = 0; idx < argv_.size() ; idx += 1) { for (size_t idx = 0; idx < argv_.size() ; idx += 1) {
if (idx > 0) out << ", "; if (idx > 0) out << ", ";
errors += argv_[idx]->emit(out, ent, arc); errors += argv_[idx]->emit(out, ent, scope);
} }
out << ")"; out << ")";
} }
@ -623,7 +623,7 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
return errors; return errors;
} }
int ExpInteger::emit(ostream&out, Entity*, Architecture*) int ExpInteger::emit(ostream&out, Entity*, ScopeBase*)
{ {
out << value_; out << value_;
return 0; return 0;
@ -635,12 +635,7 @@ int ExpInteger::emit_package(ostream&out)
return 0; return 0;
} }
bool ExpInteger::is_primary(void) const int ExpReal::emit(ostream&out, Entity*, ScopeBase*)
{
return true;
}
int ExpReal::emit(ostream&out, Entity*, Architecture*)
{ {
out << value_; out << value_;
return 0; return 0;
@ -657,11 +652,11 @@ bool ExpReal::is_primary(void) const
return true; return true;
} }
int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc) int ExpLogical::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
errors += emit_operand1(out, ent, arc); errors += emit_operand1(out, ent, scope);
switch (fun_) { switch (fun_) {
case AND: case AND:
@ -684,22 +679,22 @@ int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc)
break; break;
} }
errors += emit_operand2(out, ent, arc); errors += emit_operand2(out, ent, scope);
return errors; return errors;
} }
int ExpName::emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc) int ExpName::emit_as_prefix_(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
if (prefix_.get()) { if (prefix_.get()) {
errors += prefix_->emit_as_prefix_(out, ent, arc); errors += prefix_->emit_as_prefix_(out, ent, scope);
} }
out << "\\" << name_ << " "; out << "\\" << name_ << " ";
if (index_) { if (index_) {
out << "["; out << "[";
errors += index_->emit(out, ent, arc); errors += index_->emit(out, ent, scope);
out << "]"; out << "]";
ivl_assert(*this, lsb_ == 0); ivl_assert(*this, lsb_ == 0);
} }
@ -707,27 +702,28 @@ int ExpName::emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc)
return errors; return errors;
} }
int ExpName::emit(ostream&out, Entity*ent, Architecture*arc) int ExpName::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
if (prefix_.get()) { if (prefix_.get()) {
errors += prefix_->emit_as_prefix_(out, ent, arc); errors += prefix_->emit_as_prefix_(out, ent, scope);
} }
const GenerateStatement*gs = 0; const GenerateStatement*gs = 0;
Architecture*arc = dynamic_cast<Architecture*>(scope);
if (arc && (gs = arc->probe_genvar_emit(name_))) if (arc && (gs = arc->probe_genvar_emit(name_)))
out << "\\" << gs->get_name() << ":" << name_ << " "; out << "\\" << gs->get_name() << ":" << name_ << " ";
else else
out << "\\" << name_ << " "; out << "\\" << name_ << " ";
if (index_) { if (index_) {
out << "["; out << "[";
errors += index_->emit(out, ent, arc); errors += index_->emit(out, ent, scope);
if (lsb_) { if (lsb_) {
out << ":"; out << ":";
errors += lsb_->emit(out, ent, arc); errors += lsb_->emit(out, ent, scope);
} }
out << "]"; out << "]";
} }
@ -740,10 +736,10 @@ bool ExpName::is_primary(void) const
return true; return true;
} }
int ExpRelation::emit(ostream&out, Entity*ent, Architecture*arc) int ExpRelation::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
errors += emit_operand1(out, ent, arc); errors += emit_operand1(out, ent, scope);
switch (fun_) { switch (fun_) {
case EQ: case EQ:
@ -766,7 +762,7 @@ int ExpRelation::emit(ostream&out, Entity*ent, Architecture*arc)
break; break;
} }
errors += emit_operand2(out, ent, arc); errors += emit_operand2(out, ent, scope);
return errors; return errors;
} }
@ -775,13 +771,13 @@ bool ExpString::is_primary(void) const
return true; return true;
} }
int ExpString::emit(ostream& out, Entity*ent, Architecture*arc) int ExpString::emit(ostream& out, Entity*ent, ScopeBase*scope)
{ {
const VType*type = peek_type(); const VType*type = peek_type();
assert(type != 0); assert(type != 0);
if (const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type)) { if (const VTypeArray*arr = dynamic_cast<const VTypeArray*>(type)) {
return emit_as_array_(out, ent, arc, arr); return emit_as_array_(out, ent, scope, arr);
} }
out << "\""; out << "\"";
@ -792,7 +788,7 @@ int ExpString::emit(ostream& out, Entity*ent, Architecture*arc)
return 0; return 0;
} }
int ExpString::emit_as_array_(ostream& out, Entity*, Architecture*, const VTypeArray*arr) int ExpString::emit_as_array_(ostream& out, Entity*, ScopeBase*, const VTypeArray*arr)
{ {
int errors = 0; int errors = 0;
assert(arr->dimensions() == 1); assert(arr->dimensions() == 1);
@ -843,20 +839,39 @@ int ExpString::emit_as_array_(ostream& out, Entity*, Architecture*, const VTypeA
return errors; return errors;
} }
int ExpUAbs::emit(ostream&out, Entity*ent, Architecture*arc) int ExpUAbs::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
out << "abs("; out << "abs(";
errors += emit_operand1(out, ent, arc); errors += emit_operand1(out, ent, scope);
out << ")"; out << ")";
return errors; return errors;
} }
int ExpUNot::emit(ostream&out, Entity*ent, Architecture*arc) int ExpUNot::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
out << "~("; out << "~(";
errors += emit_operand1(out, ent, arc); errors += emit_operand1(out, ent, scope);
out << ")"; out << ")";
return errors; return errors;
} }
int ExpCast::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
errors += type_->emit_def(out, empty_perm_string);
out << "'(";
errors += base_->emit(out, ent, scope);
out << ")";
return errors;
}
int ExpNew::emit(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
out << "new[";
errors += size_->emit(out, ent, scope);
out << "]";
return errors;
}

View File

@ -1,5 +1,7 @@
/* /*
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com) * Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
* Copyright CERN 2015
* @author Maciej Suminski (maciej.suminski@cern.ch)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -26,9 +28,9 @@ bool Expression::evaluate(ScopeBase*, int64_t&) const
return false; return false;
} }
bool Expression::evaluate(Entity*, Architecture*arc, int64_t&val) const bool Expression::evaluate(Entity*, ScopeBase*scope, int64_t&val) const
{ {
return evaluate(arc, val); return evaluate(scope, val);
} }
@ -76,18 +78,31 @@ bool ExpArithmetic::evaluate(ScopeBase*scope, int64_t&val) const
return true; return true;
} }
bool ExpAttribute::evaluate(ScopeBase*, int64_t&val) const bool ExpAttribute::evaluate(ScopeBase*scope, int64_t&val) const
{ {
/* Special Case: The length attribute can be calculated all /* Special Case: The array attributes can sometimes be calculated all
the down to a literal integer at compile time, and all it the down to a literal integer at compile time, and all it
needs is the type of the base expression. (The base needs is the type of the base expression. (The base
expression doesn't even need to be evaluated.) */ expression doesn't even need to be evaluated.) */
if (name_ == "length") { if (name_ == "length" || name_ == "right" || name_ == "left") {
const VType*base_type = base_->peek_type(); const VType*base_type = base_->peek_type();
//if (base_type == 0)
// base_type = base_->probe_type(ent,arc);
ivl_assert(*this, base_type); if(!base_type) {
const ExpName*name = NULL;
if(scope && (name = dynamic_cast<const ExpName*>(base_))) {
const perm_string& n = name->peek_name();
if(const Variable*var = scope->find_variable(n))
base_type = var->peek_type();
else if(const Signal*sig = scope->find_signal(n))
base_type = sig->peek_type();
else if(const InterfacePort*port = scope->find_param(n))
base_type = port->type;
}
}
if(!base_type)
return false; // I tried really hard, sorry
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(base_type); const VTypeArray*arr = dynamic_cast<const VTypeArray*>(base_type);
if (arr == 0) { if (arr == 0) {
@ -97,25 +112,43 @@ bool ExpAttribute::evaluate(ScopeBase*, int64_t&val) const
return false; return false;
} }
int64_t size = 1; if(name_ == "length") {
for (size_t idx = 0 ; idx < arr->dimensions() ; idx += 1) { int64_t size = 1;
const VTypeArray::range_t&dim = arr->dimension(idx); for (size_t idx = 0 ; idx < arr->dimensions() ; idx += 1) {
ivl_assert(*this, ! dim.is_box()); const VTypeArray::range_t&dim = arr->dimension(idx);
size *= 1 + labs(dim.msb() - dim.lsb()); int64_t msb_val, lsb_val;
}
val = size; if(dim.is_box())
return false;
dim.msb()->evaluate(scope, msb_val);
dim.lsb()->evaluate(scope, lsb_val);
size *= 1 + labs(msb_val - lsb_val);
}
val = size;
} else if(name_ == "left") {
arr->dimension(0).msb()->evaluate(scope, val);
} else if(name_ == "right") {
arr->dimension(0).lsb()->evaluate(scope, val);
} else ivl_assert(*this, false);
return true; return true;
} }
return false; return false;
} }
bool ExpAttribute::evaluate(Entity*ent, Architecture*arc, int64_t&val) const bool ExpAttribute::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{ {
if (!ent || !scope) { // it's impossible to evaluate, probably it is inside a subprogram
return false;
}
if (name_ == "left" || name_ == "right") { if (name_ == "left" || name_ == "right") {
const VType*base_type = base_->peek_type(); const VType*base_type = base_->peek_type();
if (base_type == 0) if (base_type == 0)
base_type = base_->probe_type(ent,arc); base_type = base_->probe_type(ent, scope);
ivl_assert(*this, base_type); ivl_assert(*this, base_type);
@ -129,14 +162,14 @@ bool ExpAttribute::evaluate(Entity*ent, Architecture*arc, int64_t&val) const
ivl_assert(*this, arr->dimensions() == 1); ivl_assert(*this, arr->dimensions() == 1);
if(name_ == "left") if(name_ == "left")
arr->dimension(0).msb()->evaluate(ent, arc, val); arr->dimension(0).msb()->evaluate(ent, scope, val);
else else // "right"
arr->dimension(0).lsb()->evaluate(ent, arc, val); arr->dimension(0).lsb()->evaluate(ent, scope, val);
return true; return true;
} }
return evaluate(arc, val); return evaluate(scope, val);
} }
/* /*
@ -165,7 +198,7 @@ bool ExpName::evaluate(ScopeBase*scope, int64_t&val) const
return exp->evaluate(scope, val); return exp->evaluate(scope, val);
} }
bool ExpName::evaluate(Entity*ent, Architecture*arc, int64_t&val) const bool ExpName::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const
{ {
if (prefix_.get()) { if (prefix_.get()) {
cerr << get_fileline() << ": sorry: I don't know how to evaluate ExpName prefix parts." << endl; cerr << get_fileline() << ": sorry: I don't know how to evaluate ExpName prefix parts." << endl;
@ -178,8 +211,8 @@ bool ExpName::evaluate(Entity*ent, Architecture*arc, int64_t&val) const
// Evaluate the default expression and use that. // Evaluate the default expression and use that.
if (gen->expr) if (gen->expr)
return gen->expr->evaluate(ent, arc, val); return gen->expr->evaluate(ent, scope, val);
} }
return evaluate(arc, val); return evaluate(scope, val);
} }

View File

@ -24,7 +24,7 @@
using namespace std; using namespace std;
void ExpAggregate::write_to_stream(ostream&fd) void ExpAggregate::write_to_stream(ostream&fd) const
{ {
fd << "("; fd << "(";
for (vector<element_t*>::const_iterator cur = elements_.begin() for (vector<element_t*>::const_iterator cur = elements_.begin()
@ -73,7 +73,7 @@ void ExpAggregate::choice_t::write_to_stream(ostream&fd)
fd << "/* ERROR */"; fd << "/* ERROR */";
} }
void ExpArithmetic::write_to_stream(ostream&out) void ExpArithmetic::write_to_stream(ostream&out) const
{ {
out << "("; out << "(";
write_to_stream_operand1(out); write_to_stream_operand1(out);
@ -111,23 +111,23 @@ void ExpArithmetic::write_to_stream(ostream&out)
out << ")"; out << ")";
} }
void ExpAttribute::write_to_stream(ostream&fd) void ExpAttribute::write_to_stream(ostream&fd) const
{ {
base_->write_to_stream(fd); base_->write_to_stream(fd);
fd << "'" << name_; fd << "'" << name_;
} }
void ExpBitstring::write_to_stream(ostream&fd) void ExpBitstring::write_to_stream(ostream&fd) const
{ {
fd << "\""; fd << "B\"";
for(vector<char>::const_iterator it = value_.begin(); for(vector<char>::const_reverse_iterator it = value_.rbegin();
it != value_.end(); ++it) { it != value_.rend(); ++it) {
fd << *it; fd << *it;
} }
fd << "\""; fd << "\"";
} }
void ExpCharacter::write_to_stream(ostream&fd) void ExpCharacter::write_to_stream(ostream&fd) const
{ {
char buf[4]; char buf[4];
buf[0] = '\''; buf[0] = '\'';
@ -137,7 +137,7 @@ void ExpCharacter::write_to_stream(ostream&fd)
fd << buf; fd << buf;
} }
void ExpConcat::write_to_stream(ostream&fd) void ExpConcat::write_to_stream(ostream&fd) const
{ {
fd << "("; fd << "(";
operand1_->write_to_stream(fd); operand1_->write_to_stream(fd);
@ -146,21 +146,21 @@ void ExpConcat::write_to_stream(ostream&fd)
fd << ")"; fd << ")";
} }
void ExpConditional::write_to_stream(ostream&) void ExpConditional::write_to_stream(ostream&) const
{ {
ivl_assert(*this, !"Not supported"); ivl_assert(*this, !"Not supported");
} }
void ExpEdge::write_to_stream(ostream&) void ExpEdge::write_to_stream(ostream&) const
{ {
ivl_assert(*this, !"Not supported"); ivl_assert(*this, !"Not supported");
} }
void ExpFunc::write_to_stream(ostream&fd) void ExpFunc::write_to_stream(ostream&fd) const
{ {
const char*comma = ""; const char*comma = "";
fd << name_ << "("; fd << name_ << "(";
for (vector<Expression*>::iterator cur = argv_.begin() for (vector<Expression*>::const_iterator cur = argv_.begin()
; cur != argv_.end() ; ++cur) { ; cur != argv_.end() ; ++cur) {
fd << comma; fd << comma;
(*cur)->write_to_stream(fd); (*cur)->write_to_stream(fd);
@ -169,22 +169,22 @@ void ExpFunc::write_to_stream(ostream&fd)
fd << ")"; fd << ")";
} }
void ExpInteger::write_to_stream(ostream&fd) void ExpInteger::write_to_stream(ostream&fd) const
{ {
fd << value_; fd << value_;
} }
void ExpReal::write_to_stream(ostream&fd) void ExpReal::write_to_stream(ostream&fd) const
{ {
fd << value_; fd << value_;
} }
void ExpLogical::write_to_stream(ostream&) void ExpLogical::write_to_stream(ostream&) const
{ {
ivl_assert(*this, !"Not supported"); ivl_assert(*this, !"Not supported");
} }
void ExpName::write_to_stream(ostream&fd) void ExpName::write_to_stream(ostream&fd) const
{ {
if (prefix_.get()) { if (prefix_.get()) {
prefix_->write_to_stream(fd); prefix_->write_to_stream(fd);
@ -203,12 +203,40 @@ void ExpName::write_to_stream(ostream&fd)
} }
} }
void ExpRelation::write_to_stream(ostream&) void ExpRelation::write_to_stream(ostream&fd) const
{ {
ivl_assert(*this, !"Not supported"); peek_operand1()->write_to_stream(fd);
switch(fun_) {
case EQ:
fd << " = ";
break;
case LT:
fd << " < ";
break;
case GT:
fd << " > ";
break;
case NEQ:
fd << " != ";
break;
case LE:
fd << " <= ";
break;
case GE:
fd << " >= ";
break;
}
peek_operand2()->write_to_stream(fd);
} }
void ExpString::write_to_stream(ostream&fd) void ExpString::write_to_stream(ostream&fd) const
{ {
fd << "\""; fd << "\"";
for(vector<char>::const_iterator it = value_.begin(); for(vector<char>::const_iterator it = value_.begin();
@ -218,15 +246,21 @@ void ExpString::write_to_stream(ostream&fd)
fd << "\""; fd << "\"";
} }
void ExpUAbs::write_to_stream(ostream&fd) void ExpUAbs::write_to_stream(ostream&fd) const
{ {
fd << "abs "; fd << "abs ";
write_to_stream_operand1(fd); write_to_stream_operand1(fd);
} }
void ExpUNot::write_to_stream(ostream&fd) void ExpUNot::write_to_stream(ostream&fd) const
{ {
fd << "not "; fd << "not ";
write_to_stream_operand1(fd); write_to_stream_operand1(fd);
} }
void ExpCast::write_to_stream(ostream&fd) const
{
// Type casting is introduced only for a few specific cases in
// SystemVerilog, so no need to use it here
base_->write_to_stream(fd);
}

View File

@ -430,13 +430,10 @@ void library_set_work_path(const char*path)
library_work_path = path; library_work_path = path;
} }
list<const Package*> work_packages;
static void store_package_in_work(const Package*pack) static void store_package_in_work(const Package*pack)
{ {
string path = make_work_package_path(pack->name()); work_packages.push_back(pack);
ofstream file (path.c_str(), ios_base::out);
pack->write_to_stream(file);
} }
static int emit_packages(perm_string, const map<perm_string,Package*>&packages) static int emit_packages(perm_string, const map<perm_string,Package*>&packages)
@ -447,6 +444,13 @@ static int emit_packages(perm_string, const map<perm_string,Package*>&packages)
errors += cur->second->emit_package(cout); errors += cur->second->emit_package(cout);
} }
for (list<const Package*>::const_iterator cur = work_packages.begin()
; cur != work_packages.end(); ++cur) {
string path = make_work_package_path((*cur)->name());
ofstream file (path.c_str(), ios_base::out);
(*cur)->write_to_stream(file);
}
return errors; return errors;
} }

View File

@ -130,4 +130,11 @@ void Package::write_to_stream(ostream&fd) const
} }
fd << "end package " << name_ << ";" << endl; fd << "end package " << name_ << ";" << endl;
fd << "package body " << name_ << " is" << endl;
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin()
; cur != cur_subprograms_.end() ; ++cur) {
cur->second->write_to_stream_body(fd);
}
fd << "end " << name_ << ";" << endl;
} }

View File

@ -49,7 +49,8 @@ int Package::emit_package(ostream&fd) const
for (map<perm_string,const VType*>::const_iterator cur = cur_types_.begin() for (map<perm_string,const VType*>::const_iterator cur = cur_types_.begin()
; cur != cur_types_.end() ; ++ cur) { ; cur != cur_types_.end() ; ++ cur) {
fd << "typedef "; fd << "typedef ";
errors += cur->second->emit_def(fd, cur->first); errors += cur->second->emit_def(fd,
dynamic_cast<const VTypeDef*>(cur->second) ? empty_perm_string : cur->first);
fd << " ;" << endl; fd << " ;" << endl;
} }
@ -68,7 +69,9 @@ int Package::emit_package(ostream&fd) const
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin() for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin()
; cur != cur_subprograms_.end() ; ++ cur) { ; cur != cur_subprograms_.end() ; ++ cur) {
errors += cur->second->emit_package(fd); // Do not emit unbounded functions, we will just need fixed instances later
if(!cur->second->unbounded())
errors += cur->second->emit_package(fd);
} }
fd << "endpackage" << endl; fd << "endpackage" << endl;

View File

@ -573,20 +573,40 @@ case_statement_alternative_list
* statement alternative and pass that up instead. * statement alternative and pass that up instead.
*/ */
case_statement_alternative case_statement_alternative
: K_when choice ARROW sequence_of_statements : K_when choices ARROW sequence_of_statements
{ CaseSeqStmt::CaseStmtAlternative* tmp; { CaseSeqStmt::CaseStmtAlternative* tmp;
if ($2->others()) { std::list<ExpAggregate::choice_t*>*choices = $2;
tmp = new CaseSeqStmt::CaseStmtAlternative(0, $4); std::list<Expression*>*exp_list = new std::list<Expression*>;
} else if (Expression*ex = $2->simple_expression()) { bool others = false;
tmp = new CaseSeqStmt::CaseStmtAlternative(ex, $4);
} else { for(std::list<ExpAggregate::choice_t*>::iterator it = choices->begin();
errormsg(@2, "I don't know what to make of the case choice\n"); it != choices->end(); ++it) {
tmp = 0; if((*it)->others() || others)
} // If there is one "others", then it also covers all other alternatives
if (tmp) FILE_NAME(tmp, @1); // Continue the loop to delete every choice_t, but do not
delete $2; // bother to add the expressions to the exp_list (we are going to
delete $4; // delete them very soon)
$$ = tmp; others = true;
else
exp_list->push_back((*it)->simple_expression());
delete (*it);
}
if(others) {
tmp = new CaseSeqStmt::CaseStmtAlternative(0, $4);
for(std::list<Expression*>::iterator it = exp_list->begin();
it != exp_list->end(); ++it) {
delete (*it);
}
} else {
tmp = new CaseSeqStmt::CaseStmtAlternative(exp_list, $4);
}
if (tmp) FILE_NAME(tmp, @1);
delete choices;
delete $4;
$$ = tmp;
} }
; ;
@ -2504,9 +2524,9 @@ K_postponed_opt : K_postponed | ;
K_shared_opt : K_shared | ; K_shared_opt : K_shared | ;
%% %%
static void yyerror(YYLTYPE*, yyscan_t, const char*, bool, const char* /*msg*/) static void yyerror(YYLTYPE*loc, yyscan_t, const char*, bool, const char*msg)
{ {
//fprintf(stderr, "%s\n", msg); fprintf(stderr, "%s:%u: %s\n", loc->text, loc->first_line, msg);
parse_errors += 1; parse_errors += 1;
} }

View File

@ -105,6 +105,7 @@ static const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_n
VTypeArray*subtype = new VTypeArray(element, range, VTypeArray*subtype = new VTypeArray(element, range,
base_array->signed_vector()); base_array->signed_vector());
subtype->set_parent_type(base_array);
return subtype; return subtype;
} }

View File

@ -72,6 +72,9 @@ class prange_t {
public: public:
prange_t(Expression* left, Expression* right, bool dir) prange_t(Expression* left, Expression* right, bool dir)
: left_(left), right_(right), direction_(dir), auto_dir_(false) {} : left_(left), right_(right), direction_(dir), auto_dir_(false) {}
prange_t(const prange_t&other) :
left_(other.left_->clone()), right_(other.right_->clone()),
direction_(other.direction_), auto_dir_(other.auto_dir_) {}
~prange_t() { delete left_; delete right_; } ~prange_t() { delete left_; delete right_; }
void dump(ostream&out, int indent) const; void dump(ostream&out, int indent) const;
@ -91,7 +94,6 @@ class prange_t {
bool auto_dir_; bool auto_dir_;
private: //not implemented private: //not implemented
prange_t(const prange_t&);
prange_t operator=(const prange_t&); prange_t operator=(const prange_t&);
}; };

View File

@ -21,6 +21,7 @@
# include "scope.h" # include "scope.h"
# include "package.h" # include "package.h"
# include "subprogram.h" # include "subprogram.h"
# include "entity.h"
# include <algorithm> # include <algorithm>
# include <iostream> # include <iostream>
# include <iterator> # include <iterator>
@ -148,6 +149,23 @@ Variable* ScopeBase::find_variable(perm_string by_name) const
} }
} }
const InterfacePort* ScopeBase::find_param(perm_string by_name) const
{
for(map<perm_string,Subprogram*>::const_iterator it = use_subprograms_.begin();
it != use_subprograms_.end(); ++it) {
if(const InterfacePort*port = it->second->find_param(by_name))
return port;
}
for(map<perm_string,Subprogram*>::const_iterator it = cur_subprograms_.begin();
it != cur_subprograms_.end(); ++it) {
if(const InterfacePort*port = it->second->find_param(by_name))
return port;
}
return NULL;
}
Subprogram* ScopeBase::find_subprogram(perm_string name) const Subprogram* ScopeBase::find_subprogram(perm_string name) const
{ {
map<perm_string,Subprogram*>::const_iterator cur; map<perm_string,Subprogram*>::const_iterator cur;

View File

@ -56,11 +56,19 @@ class ScopeBase {
bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp); bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp);
Signal* find_signal(perm_string by_name) const; Signal* find_signal(perm_string by_name) const;
Variable* find_variable(perm_string by_name) const; Variable* find_variable(perm_string by_name) const;
virtual const InterfacePort* find_param(perm_string by_name) const;
Subprogram* find_subprogram(perm_string by_name) const; Subprogram* find_subprogram(perm_string by_name) const;
// Moves all signals, variables and components from another scope to // Moves all signals, variables and components from another scope to
// this one. After the transfer new_* maps are emptied in the another scope. // this one. After the transfer new_* maps are emptied in the another scope.
void transfer_from(ScopeBase&ref); void transfer_from(ScopeBase&ref);
inline void bind_subprogram(perm_string name, Subprogram*obj)
{ map<perm_string, Subprogram*>::iterator it;
if((it = use_subprograms_.find(name)) != use_subprograms_.end() )
use_subprograms_.erase(it);
cur_subprograms_[name] = obj;
}
protected: protected:
void cleanup(); void cleanup();

View File

@ -19,6 +19,15 @@
# include "sequential.h" # include "sequential.h"
# include "expression.h" # include "expression.h"
# include <cassert>
template<typename T>
inline static void visit_stmt_list(std::list<T*>& stmts, SeqStmtVisitor& func)
{
for(typename std::list<T*>::iterator it = stmts.begin(); it != stmts.end(); ++it) {
(*it)->visit(func);
}
}
SequentialStmt::SequentialStmt() SequentialStmt::SequentialStmt()
{ {
@ -75,6 +84,14 @@ void IfSequential::extract_false(std::list<SequentialStmt*>&that)
} }
} }
void IfSequential::visit(SeqStmtVisitor& func)
{
visit_stmt_list(if_, func);
visit_stmt_list(elsif_, func);
visit_stmt_list(else_, func);
func(this);
}
IfSequential::Elsif::Elsif(Expression*cond, std::list<SequentialStmt*>*tr) IfSequential::Elsif::Elsif(Expression*cond, std::list<SequentialStmt*>*tr)
: cond_(cond) : cond_(cond)
{ {
@ -91,6 +108,11 @@ IfSequential::Elsif::~Elsif()
} }
} }
void IfSequential::Elsif::visit(SeqStmtVisitor& func)
{
visit_stmt_list(if_, func);
}
SignalSeqAssignment::SignalSeqAssignment(Expression*sig, std::list<Expression*>*wav) SignalSeqAssignment::SignalSeqAssignment(Expression*sig, std::list<Expression*>*wav)
{ {
lval_ = sig; lval_ = sig;
@ -118,7 +140,14 @@ CaseSeqStmt::~CaseSeqStmt()
} }
} }
CaseSeqStmt::CaseStmtAlternative::CaseStmtAlternative(Expression* exp, list<SequentialStmt*>* stmts) void CaseSeqStmt::visit(SeqStmtVisitor& func)
{
visit_stmt_list(alt_, func);
func(this);
}
CaseSeqStmt::CaseStmtAlternative::CaseStmtAlternative(std::list<Expression*>*exp,
list<SequentialStmt*>*stmts)
: exp_(exp) : exp_(exp)
{ {
if (stmts) stmts_.splice(stmts_.end(), *stmts); if (stmts) stmts_.splice(stmts_.end(), *stmts);
@ -134,6 +163,11 @@ CaseSeqStmt::CaseStmtAlternative::~CaseStmtAlternative()
} }
} }
void CaseSeqStmt::CaseStmtAlternative::visit(SeqStmtVisitor& func)
{
visit_stmt_list(stmts_, func);
}
ProcedureCall::ProcedureCall(perm_string name) ProcedureCall::ProcedureCall(perm_string name)
: name_(name), param_list_(0) : name_(name), param_list_(0)
{ {
@ -163,6 +197,12 @@ ReturnStmt::~ReturnStmt()
delete val_; delete val_;
} }
void ReturnStmt::cast_to(const VType*type)
{
assert(val_);
val_ = new ExpCast(val_, type);
}
LoopStatement::LoopStatement(perm_string name, list<SequentialStmt*>* stmts) LoopStatement::LoopStatement(perm_string name, list<SequentialStmt*>* stmts)
: name_(name) : name_(name)
{ {
@ -178,6 +218,12 @@ LoopStatement::~LoopStatement()
} }
} }
void LoopStatement::visit(SeqStmtVisitor& func)
{
visit_stmt_list(stmts_, func);
func(this);
}
ForLoopStatement::ForLoopStatement(perm_string scope_name, perm_string it, prange_t* range, list<SequentialStmt*>* stmts) ForLoopStatement::ForLoopStatement(perm_string scope_name, perm_string it, prange_t* range, list<SequentialStmt*>* stmts)
: LoopStatement(scope_name, stmts), it_(it), range_(range) : LoopStatement(scope_name, stmts), it_(it), range_(range)
{ {

View File

@ -23,10 +23,17 @@
# include "LineInfo.h" # include "LineInfo.h"
# include "parse_types.h" # include "parse_types.h"
# include <list> # include <list>
# include <functional>
class Architecture; class ScopeBase;
class Entity; class Entity;
class Expression; class Expression;
class SequentialStmt;
struct SeqStmtVisitor {
virtual ~SeqStmtVisitor() {};
virtual void operator() (SequentialStmt*s) = 0;
};
class SequentialStmt : public LineInfo { class SequentialStmt : public LineInfo {
@ -35,9 +42,13 @@ class SequentialStmt : public LineInfo {
virtual ~SequentialStmt() =0; virtual ~SequentialStmt() =0;
public: public:
virtual int elaborate(Entity*ent, Architecture*arc); virtual int elaborate(Entity*ent, ScopeBase*scope);
virtual int emit(ostream&out, Entity*entity, Architecture*arc); virtual int emit(ostream&out, Entity*entity, ScopeBase*scope);
virtual void dump(ostream&out, int indent) const; virtual void dump(ostream&out, int indent) const;
virtual void write_to_stream(std::ostream&fd);
// Recursively visits a tree of sequential statements.
virtual void visit(SeqStmtVisitor& func) { func(this); }
}; };
/* /*
@ -52,10 +63,12 @@ class LoopStatement : public SequentialStmt {
inline perm_string loop_name() const { return name_; } inline perm_string loop_name() const { return name_; }
void dump(ostream&out, int indent) const; void dump(ostream&out, int indent) const;
void visit(SeqStmtVisitor& func);
protected: protected:
int elaborate_substatements(Entity*ent, Architecture*arc); int elaborate_substatements(Entity*ent, ScopeBase*scope);
int emit_substatements(std::ostream&out, Entity*ent, Architecture*arc); int emit_substatements(std::ostream&out, Entity*ent, ScopeBase*scope);
void write_to_stream_substatements(ostream&fd);
private: private:
perm_string name_; perm_string name_;
@ -70,11 +83,15 @@ class IfSequential : public SequentialStmt {
Elsif(Expression*cond, std::list<SequentialStmt*>*tr); Elsif(Expression*cond, std::list<SequentialStmt*>*tr);
~Elsif(); ~Elsif();
int elaborate(Entity*entity, Architecture*arc); int elaborate(Entity*entity, ScopeBase*scope);
int condition_emit(ostream&out, Entity*entity, Architecture*arc); int condition_emit(ostream&out, Entity*entity, ScopeBase*scope);
int statement_emit(ostream&out, Entity*entity, Architecture*arc); int statement_emit(ostream&out, Entity*entity, ScopeBase*scope);
void condition_write_to_stream(ostream&fd);
void statement_write_to_stream(ostream&fd);
void dump(ostream&out, int indent) const; void dump(ostream&out, int indent) const;
void visit(SeqStmtVisitor& func);
private: private:
Expression*cond_; Expression*cond_;
@ -91,9 +108,11 @@ class IfSequential : public SequentialStmt {
~IfSequential(); ~IfSequential();
public: public:
int elaborate(Entity*ent, Architecture*arc); int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, Architecture*arc); int emit(ostream&out, Entity*entity, ScopeBase*scope);
void write_to_stream(std::ostream&fd);
void dump(ostream&out, int indent) const; void dump(ostream&out, int indent) const;
void visit(SeqStmtVisitor& func);
const Expression*peek_condition() const { return cond_; } const Expression*peek_condition() const { return cond_; }
@ -117,10 +136,12 @@ class ReturnStmt : public SequentialStmt {
~ReturnStmt(); ~ReturnStmt();
public: public:
int emit(ostream&out, Entity*entity, Architecture*arc); int emit(ostream&out, Entity*entity, ScopeBase*scope);
void write_to_stream(std::ostream&fd);
void dump(ostream&out, int indent) const; void dump(ostream&out, int indent) const;
const Expression*peek_expr() const { return val_; }; const Expression*peek_expr() const { return val_; };
void cast_to(const VType*type);
private: private:
Expression*val_; Expression*val_;
@ -132,8 +153,9 @@ class SignalSeqAssignment : public SequentialStmt {
~SignalSeqAssignment(); ~SignalSeqAssignment();
public: public:
int elaborate(Entity*ent, Architecture*arc); int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, Architecture*arc); int emit(ostream&out, Entity*entity, ScopeBase*scope);
void write_to_stream(std::ostream&fd);
void dump(ostream&out, int indent) const; void dump(ostream&out, int indent) const;
private: private:
@ -145,15 +167,17 @@ class CaseSeqStmt : public SequentialStmt {
public: public:
class CaseStmtAlternative : public LineInfo { class CaseStmtAlternative : public LineInfo {
public: public:
CaseStmtAlternative(Expression* exp, std::list<SequentialStmt*>* stmts); CaseStmtAlternative(std::list<Expression*>*exp, std::list<SequentialStmt*>*stmts);
~CaseStmtAlternative(); ~CaseStmtAlternative();
void dump(std::ostream& out, int indent) const; void dump(std::ostream& out, int indent) const;
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype); int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
int elaborate(Entity*ent, Architecture*arc); int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, Architecture*arc); int emit(ostream&out, Entity*entity, ScopeBase*scope);
void write_to_stream(std::ostream&fd);
void visit(SeqStmtVisitor& func);
private: private:
Expression* exp_; std::list<Expression*>*exp_;
std::list<SequentialStmt*> stmts_; std::list<SequentialStmt*> stmts_;
private: // not implemented private: // not implemented
CaseStmtAlternative(const CaseStmtAlternative&); CaseStmtAlternative(const CaseStmtAlternative&);
@ -166,8 +190,10 @@ class CaseSeqStmt : public SequentialStmt {
public: public:
void dump(ostream&out, int indent) const; void dump(ostream&out, int indent) const;
int elaborate(Entity*ent, Architecture*arc); int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, Architecture*arc); int emit(ostream&out, Entity*entity, ScopeBase*scope);
void write_to_stream(std::ostream&fd);
void visit(SeqStmtVisitor& func);
private: private:
Expression* cond_; Expression* cond_;
@ -180,8 +206,8 @@ class ProcedureCall : public SequentialStmt {
ProcedureCall(perm_string name, std::list<named_expr_t*>* param_list); ProcedureCall(perm_string name, std::list<named_expr_t*>* param_list);
~ProcedureCall(); ~ProcedureCall();
int elaborate(Entity*ent, Architecture*arc); int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, Architecture*arc); int emit(ostream&out, Entity*entity, ScopeBase*scope);
void dump(ostream&out, int indent) const; void dump(ostream&out, int indent) const;
private: private:
@ -195,8 +221,9 @@ class VariableSeqAssignment : public SequentialStmt {
~VariableSeqAssignment(); ~VariableSeqAssignment();
public: public:
int elaborate(Entity*ent, Architecture*arc); int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, Architecture*arc); int emit(ostream&out, Entity*entity, ScopeBase*scope);
void write_to_stream(std::ostream&fd);
void dump(ostream&out, int indent) const; void dump(ostream&out, int indent) const;
private: private:
@ -210,8 +237,7 @@ class WhileLoopStatement : public LoopStatement {
ExpLogical*, list<SequentialStmt*>*); ExpLogical*, list<SequentialStmt*>*);
~WhileLoopStatement(); ~WhileLoopStatement();
int elaborate(Entity*ent, Architecture*arc); int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, Architecture*arc);
void dump(ostream&out, int indent) const; void dump(ostream&out, int indent) const;
private: private:
@ -224,11 +250,16 @@ class ForLoopStatement : public LoopStatement {
perm_string index, prange_t*, list<SequentialStmt*>*); perm_string index, prange_t*, list<SequentialStmt*>*);
~ForLoopStatement(); ~ForLoopStatement();
int elaborate(Entity*ent, Architecture*arc); int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, Architecture*arc); int emit(ostream&out, Entity*ent, ScopeBase*scope);
void write_to_stream(std::ostream&fd);
void dump(ostream&out, int indent) const; void dump(ostream&out, int indent) const;
private: private:
// Emits for-loop which direction is determined at run-time.
// It is used for 'range & 'reverse_range attributes.
int emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope);
perm_string it_; perm_string it_;
prange_t* range_; prange_t* range_;
}; };
@ -238,8 +269,7 @@ class BasicLoopStatement : public LoopStatement {
BasicLoopStatement(perm_string lname, list<SequentialStmt*>*); BasicLoopStatement(perm_string lname, list<SequentialStmt*>*);
~BasicLoopStatement(); ~BasicLoopStatement();
int elaborate(Entity*ent, Architecture*arc); int elaborate(Entity*ent, ScopeBase*scope);
int emit(ostream&out, Entity*entity, Architecture*arc);
void dump(ostream&out, int indent) const; void dump(ostream&out, int indent) const;
}; };

View File

@ -105,7 +105,9 @@ void CaseSeqStmt::CaseStmtAlternative::dump(ostream& out, int indent) const
out << setw(indent) << "" << "when "; out << setw(indent) << "" << "when ";
if (exp_) if (exp_)
exp_->dump(out, 0); for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end(); ++it) {
(*it)->dump(out, 0);
}
else else
out << "others" << endl; out << "others" << endl;

View File

@ -20,35 +20,35 @@
# include "sequential.h" # include "sequential.h"
# include "expression.h" # include "expression.h"
int SequentialStmt::elaborate(Entity*, Architecture*) int SequentialStmt::elaborate(Entity*, ScopeBase*)
{ {
return 0; return 0;
} }
int LoopStatement::elaborate_substatements(Entity*ent, Architecture*arc) int LoopStatement::elaborate_substatements(Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
for (list<SequentialStmt*>::iterator cur = stmts_.begin() for (list<SequentialStmt*>::iterator cur = stmts_.begin()
; cur != stmts_.end() ; ++cur) { ; cur != stmts_.end() ; ++cur) {
errors += (*cur)->elaborate(ent, arc); errors += (*cur)->elaborate(ent, scope);
} }
return errors; return errors;
} }
int CaseSeqStmt::elaborate(Entity*ent, Architecture*arc) int CaseSeqStmt::elaborate(Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
const VType*ctype = cond_->probe_type(ent, arc); const VType*ctype = cond_->probe_type(ent, scope);
errors += cond_->elaborate_expr(ent, arc, ctype); errors += cond_->elaborate_expr(ent, scope, ctype);
for (list<CaseStmtAlternative*>::iterator cur = alt_.begin() for (list<CaseStmtAlternative*>::iterator cur = alt_.begin()
; cur != alt_.end() ; ++cur) { ; cur != alt_.end() ; ++cur) {
CaseStmtAlternative*curp = *cur; CaseStmtAlternative*curp = *cur;
errors += curp->elaborate_expr(ent, arc, ctype); errors += curp->elaborate_expr(ent, scope, ctype);
errors += curp->elaborate(ent, arc); errors += curp->elaborate(ent, scope);
} }
return errors; return errors;
@ -59,79 +59,82 @@ int CaseSeqStmt::elaborate(Entity*ent, Architecture*arc)
* ltype is the probed type for the main case condition. The * ltype is the probed type for the main case condition. The
* expression needs to elaborate itself in that context. * expression needs to elaborate itself in that context.
*/ */
int CaseSeqStmt::CaseStmtAlternative::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype) int CaseSeqStmt::CaseStmtAlternative::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype)
{ {
int errors = 0; int errors = 0;
if (exp_) if (exp_) {
errors += exp_->elaborate_expr(ent, arc, ltype); for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end();
++it) {
errors += (*it)->elaborate_expr(ent, scope, ltype);
}
}
return errors; return errors;
} }
int CaseSeqStmt::CaseStmtAlternative::elaborate(Entity*ent, Architecture*arc) int CaseSeqStmt::CaseStmtAlternative::elaborate(Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
for (list<SequentialStmt*>::iterator cur = stmts_.begin() for (list<SequentialStmt*>::iterator cur = stmts_.begin()
; cur != stmts_.end() ; ++cur) { ; cur != stmts_.end() ; ++cur) {
SequentialStmt*curp = *cur; SequentialStmt*curp = *cur;
errors += curp->elaborate(ent, arc); errors += curp->elaborate(ent, scope);
} }
return errors; return errors;
} }
int ForLoopStatement::elaborate(Entity*ent, ScopeBase*scope)
int ForLoopStatement::elaborate(Entity*ent, Architecture*arc)
{ {
int errors = 0; int errors = 0;
errors += elaborate_substatements(ent, arc); errors += elaborate_substatements(ent, scope);
return errors; return errors;
} }
int IfSequential::elaborate(Entity*ent, Architecture*arc) int IfSequential::elaborate(Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
errors += cond_->elaborate_expr(ent, arc, 0); errors += cond_->elaborate_expr(ent, scope, 0);
for (list<SequentialStmt*>::iterator cur = if_.begin() for (list<SequentialStmt*>::iterator cur = if_.begin()
; cur != if_.end() ; ++cur) { ; cur != if_.end() ; ++cur) {
errors += (*cur)->elaborate(ent, arc); errors += (*cur)->elaborate(ent, scope);
} }
for (list<IfSequential::Elsif*>::iterator cur = elsif_.begin() for (list<IfSequential::Elsif*>::iterator cur = elsif_.begin()
; cur != elsif_.end() ; ++cur) { ; cur != elsif_.end() ; ++cur) {
errors += (*cur)->elaborate(ent, arc); errors += (*cur)->elaborate(ent, scope);
} }
for (list<SequentialStmt*>::iterator cur = else_.begin() for (list<SequentialStmt*>::iterator cur = else_.begin()
; cur != else_.end() ; ++cur) { ; cur != else_.end() ; ++cur) {
errors += (*cur)->elaborate(ent, arc); errors += (*cur)->elaborate(ent, scope);
} }
return errors; return errors;
} }
int IfSequential::Elsif::elaborate(Entity*ent, Architecture*arc) int IfSequential::Elsif::elaborate(Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
errors += cond_->elaborate_expr(ent, arc, 0); errors += cond_->elaborate_expr(ent, scope, 0);
for (list<SequentialStmt*>::iterator cur = if_.begin() for (list<SequentialStmt*>::iterator cur = if_.begin()
; cur != if_.end() ; ++cur) { ; cur != if_.end() ; ++cur) {
errors += (*cur)->elaborate(ent, arc); errors += (*cur)->elaborate(ent, scope);
} }
return errors; return errors;
} }
int SignalSeqAssignment::elaborate(Entity*ent, Architecture*arc) int SignalSeqAssignment::elaborate(Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
// Elaborate the l-value expression. // Elaborate the l-value expression.
errors += lval_->elaborate_lval(ent, arc, true); errors += lval_->elaborate_lval(ent, scope, true);
// The elaborate_lval should have resolved the type of the // The elaborate_lval should have resolved the type of the
// l-value expression. We'll use that type to elaborate the // l-value expression. We'll use that type to elaborate the
@ -146,23 +149,23 @@ int SignalSeqAssignment::elaborate(Entity*ent, Architecture*arc)
for (list<Expression*>::iterator cur = waveform_.begin() for (list<Expression*>::iterator cur = waveform_.begin()
; cur != waveform_.end() ; ++cur) { ; cur != waveform_.end() ; ++cur) {
errors += (*cur)->elaborate_expr(ent, arc, lval_type); errors += (*cur)->elaborate_expr(ent, scope, lval_type);
} }
return errors; return errors;
} }
int ProcedureCall::elaborate(Entity*, Architecture*) int ProcedureCall::elaborate(Entity*, ScopeBase*)
{ {
return 0; return 0;
} }
int VariableSeqAssignment::elaborate(Entity*ent, Architecture*arc) int VariableSeqAssignment::elaborate(Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
// Elaborate the l-value expression. // Elaborate the l-value expression.
errors += lval_->elaborate_lval(ent, arc, true); errors += lval_->elaborate_lval(ent, scope, true);
// The elaborate_lval should have resolved the type of the // The elaborate_lval should have resolved the type of the
// l-value expression. We'll use that type to elaborate the // l-value expression. We'll use that type to elaborate the
@ -174,18 +177,18 @@ int VariableSeqAssignment::elaborate(Entity*ent, Architecture*arc)
} }
// Elaborate the r-value expression. // Elaborate the r-value expression.
errors += rval_->elaborate_expr(ent, arc, lval_type); errors += rval_->elaborate_expr(ent, scope, lval_type);
return errors; return errors;
} }
int WhileLoopStatement::elaborate(Entity*, Architecture*) int WhileLoopStatement::elaborate(Entity*, ScopeBase*)
{ {
//TODO:check whether there is any wait statement in the statements (there should be) //TODO:check whether there is any wait statement in the statements (there should be)
return 0; return 0;
} }
int BasicLoopStatement::elaborate(Entity*, Architecture*) int BasicLoopStatement::elaborate(Entity*, ScopeBase*)
{ {
return 0; return 0;
} }

View File

@ -1,6 +1,8 @@
/* /*
* Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com) * Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
* Copyright CERN 2015
* @author Maciej Suminski (maciej.suminski@cern.ch)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -27,7 +29,7 @@
# include <typeinfo> # include <typeinfo>
# include <ivl_assert.h> # include <ivl_assert.h>
int SequentialStmt::emit(ostream&out, Entity*, Architecture*) int SequentialStmt::emit(ostream&out, Entity*, ScopeBase*)
{ {
out << " // " << get_fileline() << ": internal error: " out << " // " << get_fileline() << ": internal error: "
<< "I don't know how to emit this sequential statement! " << "I don't know how to emit this sequential statement! "
@ -35,23 +37,30 @@ int SequentialStmt::emit(ostream&out, Entity*, Architecture*)
return 1; return 1;
} }
int IfSequential::emit(ostream&out, Entity*ent, Architecture*arc) void SequentialStmt::write_to_stream(std::ostream&fd)
{
fd << " // " << get_fileline() << ": internal error: "
<< "I don't know how to write_to_stream this sequential statement! "
<< "type=" << typeid(*this).name() << endl;
}
int IfSequential::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
out << "if ("; out << "if (";
errors += cond_->emit(out, ent, arc); errors += cond_->emit(out, ent, scope);
out << ") begin" << endl; out << ") begin" << endl;
for (list<SequentialStmt*>::iterator cur = if_.begin() for (list<SequentialStmt*>::iterator cur = if_.begin()
; cur != if_.end() ; ++cur) ; cur != if_.end() ; ++cur)
errors += (*cur)->emit(out, ent, arc); errors += (*cur)->emit(out, ent, scope);
for (list<IfSequential::Elsif*>::iterator cur = elsif_.begin() for (list<IfSequential::Elsif*>::iterator cur = elsif_.begin()
; cur != elsif_.end() ; ++cur) { ; cur != elsif_.end() ; ++cur) {
out << "end else if ("; out << "end else if (";
errors += (*cur)->condition_emit(out, ent, arc); errors += (*cur)->condition_emit(out, ent, scope);
out << ") begin" << endl; out << ") begin" << endl;
errors += (*cur)->statement_emit(out, ent, arc); errors += (*cur)->statement_emit(out, ent, scope);
} }
if (! else_.empty()) { if (! else_.empty()) {
@ -59,7 +68,7 @@ int IfSequential::emit(ostream&out, Entity*ent, Architecture*arc)
for (list<SequentialStmt*>::iterator cur = else_.begin() for (list<SequentialStmt*>::iterator cur = else_.begin()
; cur != else_.end() ; ++cur) ; cur != else_.end() ; ++cur)
errors += (*cur)->emit(out, ent, arc); errors += (*cur)->emit(out, ent, scope);
} }
@ -67,36 +76,84 @@ int IfSequential::emit(ostream&out, Entity*ent, Architecture*arc)
return errors; return errors;
} }
int IfSequential::Elsif::condition_emit(ostream&out, Entity*ent, Architecture*arc) void IfSequential::write_to_stream(std::ostream&fd)
{ {
return cond_->emit(out, ent, arc); fd << "if ";
cond_->write_to_stream(fd);
fd << " then " << endl;
for (list<SequentialStmt*>::iterator cur = if_.begin()
; cur != if_.end() ; ++cur)
(*cur)->write_to_stream(fd);
for (list<IfSequential::Elsif*>::iterator cur = elsif_.begin()
; cur != elsif_.end() ; ++cur) {
fd << "elsif ";
(*cur)->condition_write_to_stream(fd);
fd << " " << endl;
(*cur)->statement_write_to_stream(fd);
}
if (! else_.empty()) {
fd << " else " << endl;
for (list<SequentialStmt*>::iterator cur = else_.begin()
; cur != else_.end() ; ++cur)
(*cur)->write_to_stream(fd);
}
fd << "end if;" << endl;
} }
int IfSequential::Elsif::statement_emit(ostream&out, Entity*ent, Architecture*arc) int IfSequential::Elsif::condition_emit(ostream&out, Entity*ent, ScopeBase*scope)
{
return cond_->emit(out, ent, scope);
}
int IfSequential::Elsif::statement_emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
for (list<SequentialStmt*>::iterator cur = if_.begin() for (list<SequentialStmt*>::iterator cur = if_.begin()
; cur != if_.end() ; ++cur) ; cur != if_.end() ; ++cur)
errors += (*cur)->emit(out, ent, arc); errors += (*cur)->emit(out, ent, scope);
return errors; return errors;
} }
int ReturnStmt::emit(ostream&out, Entity*ent, Architecture*arc) void IfSequential::Elsif::condition_write_to_stream(ostream&fd)
{
cond_->write_to_stream(fd);
}
void IfSequential::Elsif::statement_write_to_stream(ostream&fd)
{
for (list<SequentialStmt*>::iterator cur = if_.begin()
; cur != if_.end() ; ++cur)
(*cur)->write_to_stream(fd);
}
int ReturnStmt::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
out << "return "; out << "return ";
errors += val_->emit(out, ent, arc); errors += val_->emit(out, ent, scope);
out << ";" << endl; out << ";" << endl;
return errors; return errors;
} }
int SignalSeqAssignment::emit(ostream&out, Entity*ent, Architecture*arc) void ReturnStmt::write_to_stream(ostream&fd)
{
fd << "return ";
val_->write_to_stream(fd);
fd << ";" << endl;
}
int SignalSeqAssignment::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
errors += lval_->emit(out, ent, arc); errors += lval_->emit(out, ent, scope);
if (waveform_.size() != 1) { if (waveform_.size() != 1) {
out << "/* Confusing waveform? */;" << endl; out << "/* Confusing waveform? */;" << endl;
@ -105,27 +162,50 @@ int SignalSeqAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
} else { } else {
Expression*tmp = waveform_.front(); Expression*tmp = waveform_.front();
out << " <= "; out << " <= ";
errors += tmp->emit(out, ent, arc); errors += tmp->emit(out, ent, scope);
out << ";" << endl; out << ";" << endl;
} }
return errors; return errors;
} }
int VariableSeqAssignment::emit(ostream&out, Entity*ent, Architecture*arc) void SignalSeqAssignment::write_to_stream(ostream&fd)
{
lval_->write_to_stream(fd);
if (waveform_.size() != 1) {
fd << "-- Confusing waveform?" << endl;
} else {
Expression*tmp = waveform_.front();
fd << " <= ";
tmp->write_to_stream(fd);
fd << ";" << endl;
}
}
int VariableSeqAssignment::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
errors += lval_->emit(out, ent, arc); errors += lval_->emit(out, ent, scope);
out << " = "; out << " = ";
errors += rval_->emit(out, ent, arc); errors += rval_->emit(out, ent, scope);
out << ";" << endl; out << ";" << endl;
return errors; return errors;
} }
int ProcedureCall::emit(ostream&out, Entity*, Architecture*) void VariableSeqAssignment::write_to_stream(ostream&fd)
{
lval_->write_to_stream(fd);
fd << " := ";
rval_->write_to_stream(fd);
fd << ";" << endl;
}
int ProcedureCall::emit(ostream&out, Entity*, ScopeBase*)
{ {
out << " // " << get_fileline() << ": internal error: " out << " // " << get_fileline() << ": internal error: "
<< "I don't know how to emit this sequential statement! " << "I don't know how to emit this sequential statement! "
@ -133,29 +213,38 @@ int ProcedureCall::emit(ostream&out, Entity*, Architecture*)
return 1; return 1;
} }
int LoopStatement::emit_substatements(ostream&out, Entity*ent, Architecture*arc) int LoopStatement::emit_substatements(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
for (list<SequentialStmt*>::iterator cur = stmts_.begin() for (list<SequentialStmt*>::iterator cur = stmts_.begin()
; cur != stmts_.end() ; ++cur) { ; cur != stmts_.end() ; ++cur) {
SequentialStmt*tmp = *cur; SequentialStmt*tmp = *cur;
errors += tmp->emit(out, ent, arc); errors += tmp->emit(out, ent, scope);
} }
return errors; return errors;
} }
int CaseSeqStmt::emit(ostream&out, Entity*ent, Architecture*arc) void LoopStatement::write_to_stream_substatements(ostream&fd)
{
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
; cur != stmts_.end() ; ++cur) {
SequentialStmt*tmp = *cur;
tmp->write_to_stream(fd);
}
}
int CaseSeqStmt::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
out << "case ("; out << "case (";
errors += cond_->emit(out, ent, arc); errors += cond_->emit(out, ent, scope);
out << ")" << endl; out << ")" << endl;
for (list<CaseStmtAlternative*>::iterator cur = alt_.begin() for (list<CaseStmtAlternative*>::iterator cur = alt_.begin()
; cur != alt_.end() ; ++cur) { ; cur != alt_.end() ; ++cur) {
CaseStmtAlternative*curp = *cur; CaseStmtAlternative*curp = *cur;
errors += curp ->emit(out, ent, arc); errors += curp ->emit(out, ent, scope);
} }
out << "endcase" << endl; out << "endcase" << endl;
@ -163,16 +252,38 @@ int CaseSeqStmt::emit(ostream&out, Entity*ent, Architecture*arc)
return errors; return errors;
} }
int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, Architecture*arc) void CaseSeqStmt::write_to_stream(ostream&fd)
{
fd << "case ";
cond_->write_to_stream(fd);
fd << " is" << endl;
for (list<CaseStmtAlternative*>::iterator cur = alt_.begin()
; cur != alt_.end() ; ++cur) {
CaseStmtAlternative*curp = *cur;
curp ->write_to_stream(fd);
}
fd << "end case;" << endl;
}
int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
bool first = true;
if (exp_) { if (exp_) {
errors += exp_->emit(out, ent, arc); for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end(); ++it) {
out << ":" << endl; if(first)
first = false;
else
out << ",";
errors += (*it)->emit(out, ent, scope);
}
} else { } else {
out << "default:" << endl; out << "default";
} }
out << ":" << endl;
SequentialStmt*curp; SequentialStmt*curp;
@ -182,14 +293,14 @@ int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, Architecture
break; break;
case 1: case 1:
curp = stmts_.front(); curp = stmts_.front();
errors += curp->emit(out, ent, arc); errors += curp->emit(out, ent, scope);
break; break;
default: default:
out << "begin" << endl; out << "begin" << endl;
for (list<SequentialStmt*>::iterator cur = stmts_.begin() for (list<SequentialStmt*>::iterator cur = stmts_.begin()
; cur != stmts_.end() ; ++cur) { ; cur != stmts_.end() ; ++cur) {
curp = *cur; curp = *cur;
errors += curp->emit(out, ent, arc); errors += curp->emit(out, ent, scope);
} }
out << "end" << endl; out << "end" << endl;
break; break;
@ -198,92 +309,145 @@ int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, Architecture
return errors; return errors;
} }
int ForLoopStatement::emit(ostream&out, Entity*ent, Architecture*arc) void CaseSeqStmt::CaseStmtAlternative::write_to_stream(ostream&fd)
{ {
int errors = 0; fd << "when ";
ivl_assert(*this, range_); if (exp_) {
bool first = true;
for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end(); ++it) {
if(first)
first = false;
else
fd << "|";
int64_t start_val; (*it)->write_to_stream(fd);
bool start_rc = range_->msb()->evaluate(ent, arc, start_val); }
} else {
int64_t finish_val; fd << "others" << endl;
bool finish_rc = range_->lsb()->evaluate(ent, arc, finish_val);
ivl_assert(*this, start_rc);
ivl_assert(*this, finish_rc);
bool dir = range_->is_downto();
if (!dir) {
int64_t tmp = start_val;
start_val = finish_val;
finish_val = tmp;
} }
fd << "=>" << endl;
if (dir && (start_val < finish_val)) { for (list<SequentialStmt*>::iterator cur = stmts_.begin()
if(range_->is_auto_dir()) { ; cur != stmts_.end() ; ++cur) {
dir = false; (*cur)->write_to_stream(fd);
} else {
out << "begin /* Degenerate loop at " << get_fileline()
<< ": " << start_val
<< " downto " << finish_val << " */ end" << endl;
return errors;
}
} }
else if (!dir && start_val > finish_val) {
if(range_->is_auto_dir()) {
dir = true;
} else {
out << "begin /* Degenerate loop at " << get_fileline()
<< ": " << start_val
<< " to " << finish_val << " */ end" << endl;
return errors;
}
}
perm_string scope_name = loop_name();
if (scope_name.nil()) {
char buf[80];
snprintf(buf, sizeof buf, "__%p", this);
scope_name = lex_strings.make(buf);
}
out << "begin : " << scope_name << endl;
out << "longint \\" << it_ << " ;" << endl;
out << "for (\\" << it_ << " = " << start_val << " ; ";
if (dir)
out << "\\" << it_ << " >= " << finish_val;
else
out << "\\" << it_ << " <= " << finish_val;
out << "; \\" << it_ << " = \\" << it_;
if (dir)
out << " - 1";
else
out << " + 1";
out << ") begin" << endl;
errors += emit_substatements(out, ent, arc);
out << "end" << endl;
out << "end /* " << scope_name << " */" << endl;
return errors;
} }
int WhileLoopStatement::emit(ostream&out, Entity*, Architecture*) int ForLoopStatement::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
out << " // " << get_fileline() << ": internal error: " int errors = 0;
<< "I don't know how to emit this sequential statement! " ivl_assert(*this, range_);
<< "type=" << typeid(*this).name() << endl;
return 1; int64_t start_val;
bool start_rc = range_->msb()->evaluate(ent, scope, start_val);
int64_t finish_val;
bool finish_rc = range_->lsb()->evaluate(ent, scope, finish_val);
perm_string scope_name = loop_name();
if (scope_name.nil()) {
char buf[80];
snprintf(buf, sizeof buf, "__%p", this);
scope_name = lex_strings.make(buf);
}
out << "begin : " << scope_name << endl;
out << "longint \\" << it_ << " ;" << endl;
if(!start_rc || !finish_rc) {
// Could not evaluate one of the loop boundaries, it has to be
// determined during the run-time
errors += emit_runtime_(out, ent, scope);
} else {
bool dir = range_->is_downto();
if (!dir) {
int64_t tmp = start_val;
start_val = finish_val;
finish_val = tmp;
}
if (dir && (start_val < finish_val)) {
if(range_->is_auto_dir()) {
dir = false;
} else {
out << "begin /* Degenerate loop at " << get_fileline()
<< ": " << start_val
<< " downto " << finish_val << " */ end" << endl
<< "end" << endl;
return errors;
}
}
else if (!dir && start_val > finish_val) {
if(range_->is_auto_dir()) {
dir = true;
} else {
out << "begin /* Degenerate loop at " << get_fileline()
<< ": " << start_val
<< " to " << finish_val << " */ end" << endl
<< "end" << endl;
return errors;
}
}
out << "for (\\" << it_ << " = " << start_val << " ; ";
if (dir)
out << "\\" << it_ << " >= " << finish_val;
else
out << "\\" << it_ << " <= " << finish_val;
out << "; \\" << it_ << " = \\" << it_;
if (dir)
out << " - 1)";
else
out << " + 1)";
}
out << " begin" << endl;
errors += emit_substatements(out, ent, scope);
out << "end" << endl;
out << "end /* " << scope_name << " */" << endl;
return errors;
} }
int BasicLoopStatement::emit(ostream&out, Entity*, Architecture*) void ForLoopStatement::write_to_stream(ostream&fd)
{ {
out << " // " << get_fileline() << ": internal error: " fd << "for " << it_ << " in ";
<< "I don't know how to emit this sequential statement! " range_->expr_left()->write_to_stream(fd);
<< "type=" << typeid(*this).name() << endl; fd << " to ";
return 1; range_->expr_right()->write_to_stream(fd);
fd << " loop" << endl;
write_to_stream_substatements(fd);
fd << "end loop;" << endl;
}
int ForLoopStatement::emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope)
{
int errors = 0;
out << "for (\\" << it_ << " = ";
errors += range_->expr_left()->emit(out, ent, scope);
// Twisted way of determining the loop direction at runtime
out << " ;\n(";
errors += range_->expr_left()->emit(out, ent, scope);
out << " < ";
errors += range_->expr_right()->emit(out, ent, scope);
out << " ? \\" << it_ << " <= ";
errors += range_->expr_right()->emit(out, ent, scope);
out << " : \\" << it_ << " >= ";
errors += range_->expr_right()->emit(out, ent, scope);
out << ");\n\\" << it_ << " = \\" << it_ << " + (";
errors += range_->expr_left()->emit(out, ent, scope);
out << " < ";
errors += range_->expr_right()->emit(out, ent, scope);
out << " ? 1 : -1))";
return errors;
} }

View File

@ -1,6 +1,8 @@
/* /*
* Copyright (c) 2013-2014 Stephen Williams (steve@icarus.com) * Copyright (c) 2013-2014 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
* Copyright CERN 2015
* @author Maciej Suminski (maciej.suminski@cern.ch)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -23,6 +25,8 @@
# include "vtype.h" # include "vtype.h"
# include "sequential.h" # include "sequential.h"
# include "ivl_assert.h" # include "ivl_assert.h"
# include "compiler.h"
# include <cassert>
using namespace std; using namespace std;
@ -46,7 +50,21 @@ void Subprogram::set_program_body(list<SequentialStmt*>*stmt)
{ {
ivl_assert(*this, statements_==0); ivl_assert(*this, statements_==0);
statements_ = stmt; statements_ = stmt;
fix_return_type(); }
bool Subprogram::unbounded() const {
if(return_type_->is_unbounded())
return true;
if(ports_) {
for(std::list<InterfacePort*>::const_iterator it = ports_->begin();
it != ports_->end(); ++it) {
if((*it)->type->is_unbounded())
return true;
}
}
return false;
} }
bool Subprogram::compare_specification(Subprogram*that) const bool Subprogram::compare_specification(Subprogram*that) const
@ -105,30 +123,104 @@ const VType*Subprogram::peek_param_type(int idx) const
return (*p)->type; return (*p)->type;
} }
void Subprogram::fix_return_type(void) Subprogram*Subprogram::make_instance(std::vector<Expression*> arguments, ScopeBase*scope) {
{ assert(arguments.size() == ports_->size());
if(!statements_)
return;
const ReturnStmt*ret = NULL; std::list<InterfacePort*>*ports = new std::list<InterfacePort*>;
const VType*t = NULL; int i = 0;
for (std::list<SequentialStmt*>::const_iterator s = statements_->begin() // Change the argument types to match the ones that were used during
; s != statements_->end(); ++s) { // the function call
if((ret = dynamic_cast<const ReturnStmt*>(*s))) { for(std::list<InterfacePort*>::iterator it = ports_->begin();
it != ports_->end(); ++it) {
InterfacePort*p = new InterfacePort(**it);
p->type = arguments[i++]->peek_type()->clone();
assert(p->type);
ports->push_back(p);
}
char buf[80];
snprintf(buf, sizeof(buf), "__%s_%p", name_.str(), ports);
perm_string new_name = lex_strings.make(buf);
Subprogram*instance = new Subprogram(new_name, ports, return_type_);
// Copy variables
for(std::map<perm_string,Variable*>::iterator it = new_variables_.begin();
it != new_variables_.end(); ++it) {
Variable*v = new Variable(it->first, it->second->peek_type()->clone());
instance->new_variables_[it->first] = v;
}
instance->set_parent(scope);
instance->set_program_body(statements_);
instance->fix_return_type();
scope->bind_subprogram(new_name, instance);
return instance;
}
struct check_return_type : public SeqStmtVisitor {
check_return_type(const Subprogram*subp) : subp_(subp), ret_type_(NULL) {}
void operator() (SequentialStmt*s)
{
ReturnStmt*ret;
if((ret = dynamic_cast<ReturnStmt*>(s))) {
const Expression*expr = ret->peek_expr(); const Expression*expr = ret->peek_expr();
const VType*t = NULL;
if(const ExpName*n = dynamic_cast<const ExpName*>(expr)) { if(const ExpName*n = dynamic_cast<const ExpName*>(expr)) {
if(Variable*v = find_variable(n->peek_name())) if(Variable*v = subp_->find_variable(n->peek_name()))
t = v->peek_type(); t = v->peek_type();
} else { } else {
t = expr->peek_type(); t = expr->peek_type();
} }
if(t) if(!t) { // cannot determine the type at least in one case
return_type_ = t; ret_type_ = NULL;
return;
}
if(!ret_type_) { // this is first processed return statement
ret_type_ = t;
} else if(!t->type_match(ret_type_)) {
// the function can return different types,
// we cannot have fixed width
ret_type_ = NULL;
return;
}
} }
} }
const VType*get_type() const { return ret_type_; }
private:
const Subprogram*subp_;
const VType*ret_type_;
};
void Subprogram::fix_return_type()
{
if(!statements_)
return;
check_return_type r(this);
for (std::list<SequentialStmt*>::iterator s = statements_->begin()
; s != statements_->end(); ++s) {
(*s)->visit(r);
}
VType*return_type = const_cast<VType*>(r.get_type());
if(return_type && !return_type->is_unbounded()) {
// Let's check if the variable length can be evaluated without any scope.
// If not, then it is depends on information about e.g. function params
if(return_type->is_variable_length(NULL)) {
if(VTypeArray*arr = dynamic_cast<VTypeArray*>(return_type))
arr->evaluate_ranges(this);
}
return_type_ = return_type;
}
} }
void Subprogram::write_to_stream(ostream&fd) const void Subprogram::write_to_stream(ostream&fd) const
@ -149,3 +241,39 @@ void Subprogram::write_to_stream(ostream&fd) const
return_type_->write_to_stream(fd); return_type_->write_to_stream(fd);
fd << ";" << endl; fd << ";" << endl;
} }
void Subprogram::write_to_stream_body(ostream&fd) const
{
fd << "function " << name_ << "(";
if (ports_ && ! ports_->empty()) {
list<InterfacePort*>::const_iterator cur = ports_->begin();
InterfacePort*curp = *cur;
fd << curp->name << " : ";
curp->type->write_to_stream(fd);
for (++cur ; cur != ports_->end() ; ++cur) {
curp = *cur;
fd << "; " << curp->name << " : ";
curp->type->write_to_stream(fd);
}
}
fd << ") return ";
return_type_->write_to_stream(fd);
fd << " is" << endl;
for (map<perm_string,Variable*>::const_iterator cur = new_variables_.begin()
; cur != new_variables_.end() ; ++cur) {
cur->second->write_to_stream(fd);
}
fd << "begin" << endl;
if (statements_) {
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
; cur != statements_->end() ; ++cur) {
(*cur)->write_to_stream(fd);
}
} else {
fd << "--empty body" << endl;
}
fd << "end function;" << endl;
}

View File

@ -3,6 +3,8 @@
/* /*
* Copyright (c) 2013-2014 Stephen Williams (steve@icarus.com) * Copyright (c) 2013-2014 Stephen Williams (steve@icarus.com)
* Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com)
* Copyright CERN 2015
* @author Maciej Suminski (maciej.suminski@cern.ch)
* *
* This source code is free software; you can redistribute it * This source code is free software; you can redistribute it
* and/or modify it in source code form under the terms of the GNU * and/or modify it in source code form under the terms of the GNU
@ -43,6 +45,7 @@ class Subprogram : public LineInfo, public ScopeBase {
inline const perm_string&name() const { return name_; } inline const perm_string&name() const { return name_; }
void set_program_body(std::list<SequentialStmt*>*statements); void set_program_body(std::list<SequentialStmt*>*statements);
inline bool empty_program_body() const { return !statements_ || statements_->empty(); }
// Return true if the specification (name, types, ports) // Return true if the specification (name, types, ports)
// matches this subprogram and that subprogram. // matches this subprogram and that subprogram.
@ -50,19 +53,31 @@ class Subprogram : public LineInfo, public ScopeBase {
const InterfacePort*find_param(perm_string nam) const; const InterfacePort*find_param(perm_string nam) const;
const VType*peek_param_type(int idx) const; const VType*peek_param_type(int idx) const;
const VType*peek_return_type() const { return return_type_; }
int emit(ostream&out, Entity*ent, Architecture*arc); int emit(ostream&out, Entity*ent, ScopeBase*scope);
// Emit a definition as it would show up in a package. // Emit a definition as it would show up in a package.
int emit_package(std::ostream&fd) const; int emit_package(std::ostream&fd) const;
void write_to_stream(std::ostream&fd) const; void write_to_stream(std::ostream&fd) const;
void write_to_stream_body(std::ostream&fd) const;
void dump(std::ostream&fd) const; void dump(std::ostream&fd) const;
// Creates a new instance of the function that takes arguments of
// a different type. It is used to allow VHDL functions that work with
// unbounded std_logic_vectors, so there can be a separate instance
// for limited length logic vector.
Subprogram*make_instance(std::vector<Expression*> arguments, ScopeBase*scope);
// Checks if either return type or parameters are unbounded vectors.
bool unbounded() const;
private: private:
// Determines appropriate return type. Un case of std_logic_vector // Tries to set the return type to a fixed type. VHDL functions that
// VHDL requires skipping its size in contrary to Verilog // return std_logic_vectors do not specify its length, as SystemVerilog
void fix_return_type(void); // demands.
void fix_return_type();
perm_string name_; perm_string name_;
const ScopeBase*parent_; const ScopeBase*parent_;

View File

@ -70,7 +70,7 @@ int Subprogram::emit_package(ostream&fd) const
if (statements_) { if (statements_) {
for (list<SequentialStmt*>::const_iterator cur = statements_->begin() for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
; cur != statements_->end() ; ++cur) { ; cur != statements_->end() ; ++cur) {
errors += (*cur)->emit(fd, NULL, NULL); errors += (*cur)->emit(fd, NULL, const_cast<Subprogram*>(this));
} }
} else { } else {
fd << " begin /* empty body */ end" << endl; fd << " begin /* empty body */ end" << endl;

View File

@ -34,10 +34,10 @@ SigVarBase::~SigVarBase()
{ {
} }
void SigVarBase::elaborate_init_expr(Entity*ent, Architecture*arc) void SigVarBase::elaborate_init_expr(Entity*ent, ScopeBase*scope)
{ {
if(init_expr_) { if(init_expr_) {
init_expr_->elaborate_expr(ent, arc, peek_type()); init_expr_->elaborate_expr(ent, scope, peek_type());
} }
} }
@ -46,7 +46,7 @@ void SigVarBase::type_elaborate_(VType::decl_t&decl)
decl.type = type_; decl.type = type_;
} }
int Signal::emit(ostream&out, Entity*ent, Architecture*arc) int Signal::emit(ostream&out, Entity*ent, ScopeBase*scope)
{ {
int errors = 0; int errors = 0;
@ -54,18 +54,18 @@ int Signal::emit(ostream&out, Entity*ent, Architecture*arc)
type_elaborate_(decl); type_elaborate_(decl);
if (peek_refcnt_sequ_() > 0 || !peek_type()->can_be_packed()) if (peek_refcnt_sequ_() > 0 || !peek_type()->can_be_packed())
decl.reg_flag = true; decl.reg_flag = true;
errors += decl.emit(out, peek_name_()); errors += decl.emit(out, peek_name());
Expression*init_expr = peek_init_expr(); Expression*init_expr = peek_init_expr();
if (init_expr) { if (init_expr) {
out << " = "; out << " = ";
init_expr->emit(out, ent, arc); init_expr->emit(out, ent, scope);
} }
out << ";" << endl; out << ";" << endl;
return errors; return errors;
} }
int Variable::emit(ostream&out, Entity*, Architecture*) int Variable::emit(ostream&out, Entity*, ScopeBase*)
{ {
int errors = 0; int errors = 0;
@ -73,7 +73,14 @@ int Variable::emit(ostream&out, Entity*, Architecture*)
type_elaborate_(decl); type_elaborate_(decl);
if (peek_refcnt_sequ_() > 0 || !peek_type()->can_be_packed()) if (peek_refcnt_sequ_() > 0 || !peek_type()->can_be_packed())
decl.reg_flag = true; decl.reg_flag = true;
errors += decl.emit(out, peek_name_()); errors += decl.emit(out, peek_name());
out << ";" << endl; out << ";" << endl;
return errors; return errors;
} }
void Variable::write_to_stream(std::ostream&fd)
{
fd << "variable " << peek_name() << " : ";
peek_type()->write_to_stream(fd);
fd << ";" << endl;
}

View File

@ -24,6 +24,7 @@
# include "vtype.h" # include "vtype.h"
class Architecture; class Architecture;
class ScopeBase;
class Entity; class Entity;
class Expression; class Expression;
@ -42,10 +43,11 @@ class SigVarBase : public LineInfo {
void dump(ostream&out, int indent = 0) const; void dump(ostream&out, int indent = 0) const;
// Elaborates initializer expressions if needed. // Elaborates initializer expressions if needed.
void elaborate_init_expr(Entity*ent, Architecture*arc); void elaborate_init_expr(Entity*ent, ScopeBase*scope);
perm_string peek_name() const { return name_; }
protected: protected:
perm_string peek_name_() const { return name_; }
unsigned peek_refcnt_sequ_() const { return refcnt_sequ_; } unsigned peek_refcnt_sequ_() const { return refcnt_sequ_; }
void type_elaborate_(VType::decl_t&decl); void type_elaborate_(VType::decl_t&decl);
@ -69,7 +71,7 @@ class Signal : public SigVarBase {
public: public:
Signal(perm_string name, const VType*type, Expression*init_expr); Signal(perm_string name, const VType*type, Expression*init_expr);
int emit(ostream&out, Entity*ent, Architecture*arc); int emit(ostream&out, Entity*ent, ScopeBase*scope);
}; };
class Variable : public SigVarBase { class Variable : public SigVarBase {
@ -77,7 +79,8 @@ class Variable : public SigVarBase {
public: public:
Variable(perm_string name, const VType*type); Variable(perm_string name, const VType*type);
int emit(ostream&out, Entity*ent, Architecture*arc); int emit(ostream&out, Entity*ent, ScopeBase*scope);
void write_to_stream(std::ostream&fd);
}; };
inline void SigVarBase::count_ref_sequ() inline void SigVarBase::count_ref_sequ()

View File

@ -19,13 +19,13 @@
# include "vtype.h" # include "vtype.h"
# include "parse_types.h" # include "parse_types.h"
# include "compiler.h"
# include <map> # include <map>
# include <typeinfo> # include <typeinfo>
# include <cassert> # include <cassert>
using namespace std; using namespace std;
VType::~VType() VType::~VType()
{ {
} }
@ -35,6 +35,13 @@ void VType::show(ostream&out) const
write_to_stream(out); write_to_stream(out);
} }
perm_string VType::get_generic_typename() const
{
char buf[16] = {0,};
snprintf(buf, 16, "type_%p", this);
return lex_strings.make(buf);
}
VTypePrimitive::VTypePrimitive(VTypePrimitive::type_t tt, bool packed) VTypePrimitive::VTypePrimitive(VTypePrimitive::type_t tt, bool packed)
: type_(tt), packed_(packed) : type_(tt), packed_(packed)
{ {
@ -68,8 +75,13 @@ void VTypePrimitive::show(ostream&out) const
} }
} }
VTypeArray::range_t*VTypeArray::range_t::clone() const
{
return new VTypeArray::range_t(safe_clone(msb_), safe_clone(lsb_), direction_);
}
VTypeArray::VTypeArray(const VType*element, const vector<VTypeArray::range_t>&r, bool sv) VTypeArray::VTypeArray(const VType*element, const vector<VTypeArray::range_t>&r, bool sv)
: etype_(element), ranges_(r), signed_flag_(sv) : etype_(element), ranges_(r), signed_flag_(sv), parent_(NULL)
{ {
} }
@ -81,7 +93,7 @@ VTypeArray::VTypeArray(const VType*element, const vector<VTypeArray::range_t>&r,
* this is a memory leak. Something to fix. * this is a memory leak. Something to fix.
*/ */
VTypeArray::VTypeArray(const VType*element, std::list<prange_t*>*r, bool sv) VTypeArray::VTypeArray(const VType*element, std::list<prange_t*>*r, bool sv)
: etype_(element), ranges_(r->size()), signed_flag_(sv) : etype_(element), ranges_(r->size()), signed_flag_(sv), parent_(NULL)
{ {
for (size_t idx = 0 ; idx < ranges_.size() ; idx += 1) { for (size_t idx = 0 ; idx < ranges_.size() ; idx += 1) {
prange_t*curp = r->front(); prange_t*curp = r->front();
@ -98,6 +110,18 @@ VTypeArray::~VTypeArray()
{ {
} }
VType*VTypeArray::clone() const {
std::vector<range_t> new_ranges;
new_ranges.reserve(ranges_.size());
for(std::vector<range_t>::const_iterator it = ranges_.begin();
it != ranges_.end(); ++it) {
new_ranges.push_back(*(it->clone()));
}
VTypeArray*a = new VTypeArray(etype_->clone(), new_ranges, signed_flag_);
a->set_parent_type(parent_);
return a;
}
const VType* VTypeArray::basic_type(bool typedef_allowed) const const VType* VTypeArray::basic_type(bool typedef_allowed) const
{ {
const VType*t = etype_; const VType*t = etype_;
@ -148,6 +172,49 @@ void VTypeArray::show(ostream&out) const
out << "<nil>"; out << "<nil>";
} }
bool VTypeArray::is_unbounded() const {
for(std::vector<range_t>::const_iterator it = ranges_.begin();
it != ranges_.end(); ++it)
{
if(it->is_box())
return true;
}
return etype_->is_unbounded();
}
bool VTypeArray::is_variable_length(ScopeBase*scope) const {
int64_t dummy;
if(is_unbounded())
return true;
for(std::vector<range_t>::const_iterator it = ranges_.begin();
it != ranges_.end(); ++it)
{
if(!it->lsb()->evaluate(scope, dummy))
return true;
if(!it->msb()->evaluate(scope, dummy))
return true;
}
return etype_->is_variable_length(scope);
}
void VTypeArray::evaluate_ranges(ScopeBase*scope) {
for(std::vector<range_t>::iterator it = ranges_.begin(); it != ranges_.end(); ++it ) {
int64_t lsb_val = -1, msb_val = -1;
bool dir = it->is_downto();
if(it->msb()->evaluate(scope, msb_val) && it->lsb()->evaluate(scope, lsb_val)) {
assert(lsb_val >= 0);
assert(msb_val >= 0);
*it = range_t(new ExpInteger(msb_val), new ExpInteger(lsb_val), dir);
}
}
}
VTypeRange::VTypeRange(const VType*base, int64_t max_val, int64_t min_val) VTypeRange::VTypeRange(const VType*base, int64_t max_val, int64_t min_val)
: base_(base) : base_(base)
{ {

View File

@ -30,10 +30,12 @@
# include "StringHeap.h" # include "StringHeap.h"
class Architecture; class Architecture;
class ScopeBase;
class Entity; class Entity;
class Expression; class Expression;
class prange_t; class prange_t;
class VTypeDef; class VTypeDef;
class ScopeBase;
typedef enum typedef_topo_e { NONE=0, PENDING, MARKED } typedef_topo_t; typedef enum typedef_topo_e { NONE=0, PENDING, MARKED } typedef_topo_t;
typedef std::map<const VTypeDef*, typedef_topo_t> typedef_context_t; typedef std::map<const VTypeDef*, typedef_topo_t> typedef_context_t;
@ -49,9 +51,11 @@ class VType {
VType() { } VType() { }
virtual ~VType() =0; virtual ~VType() =0;
virtual VType*clone() const =0;
// This is rarely used, but some types may have expressions // This is rarely used, but some types may have expressions
// that need to be elaborated. // that need to be elaborated.
virtual int elaborate(Entity*end, Architecture*arc) const; virtual int elaborate(Entity*end, ScopeBase*scope) const;
// This virtual method returns true if that is equivalent to // This virtual method returns true if that is equivalent to
// this type. This method is used for example to compare // this type. This method is used for example to compare
@ -85,6 +89,17 @@ class VType {
// Determines if a type can be used in Verilog packed array. // Determines if a type can be used in Verilog packed array.
virtual bool can_be_packed() const { return false; } virtual bool can_be_packed() const { return false; }
// Returns true if the type has an undefined dimension.
virtual bool is_unbounded() const { return false; }
// Checks if the variable length is dependent on other expressions, that
// cannot be evaluated (e.g. 'length, 'left, 'right).
virtual bool is_variable_length(ScopeBase*) const { return false; }
// Returns a perm_string that can be used in automatically created
// typedefs (i.e. not ones defined by the user).
perm_string get_generic_typename() const;
private: private:
friend struct decl_t; friend struct decl_t;
// This virtual method is called to emit the declaration. This // This virtual method is called to emit the declaration. This
@ -123,6 +138,8 @@ extern void preload_global_types(void);
* This type is a placeholder for ERROR types. * This type is a placeholder for ERROR types.
*/ */
class VTypeERROR : public VType { class VTypeERROR : public VType {
VType*clone() const { return NULL; }
public: public:
int emit_def(std::ostream&out, perm_string name) const; int emit_def(std::ostream&out, perm_string name) const;
}; };
@ -140,6 +157,8 @@ class VTypePrimitive : public VType {
VTypePrimitive(type_t tt, bool packed = false); VTypePrimitive(type_t tt, bool packed = false);
~VTypePrimitive(); ~VTypePrimitive();
VType*clone() const { return new VTypePrimitive(*this); }
void write_to_stream(std::ostream&fd) const; void write_to_stream(std::ostream&fd) const;
void show(std::ostream&) const; void show(std::ostream&) const;
@ -176,6 +195,8 @@ class VTypeArray : public VType {
range_t(Expression*m = NULL, Expression*l = NULL, bool dir = true) : range_t(Expression*m = NULL, Expression*l = NULL, bool dir = true) :
msb_(m), lsb_(l), direction_(dir) { } msb_(m), lsb_(l), direction_(dir) { }
range_t*clone() const;
inline bool is_box() const { return msb_==0 && lsb_==0; } inline bool is_box() const { return msb_==0 && lsb_==0; }
inline bool is_downto() const { return direction_; } inline bool is_downto() const { return direction_; }
@ -193,7 +214,9 @@ class VTypeArray : public VType {
VTypeArray(const VType*etype, std::list<prange_t*>*r, bool signed_vector =false); VTypeArray(const VType*etype, std::list<prange_t*>*r, bool signed_vector =false);
~VTypeArray(); ~VTypeArray();
int elaborate(Entity*ent, Architecture*arc) const; VType*clone() const;
int elaborate(Entity*ent, ScopeBase*scope) const;
void write_to_stream(std::ostream&fd) const; void write_to_stream(std::ostream&fd) const;
void write_type_to_stream(std::ostream&fd) const; void write_type_to_stream(std::ostream&fd) const;
void show(std::ostream&) const; void show(std::ostream&) const;
@ -205,7 +228,7 @@ class VTypeArray : public VType {
inline bool signed_vector() const { return signed_flag_; } inline bool signed_vector() const { return signed_flag_; }
// returns the type of element held in the array // returns the type of element held in the array
inline const VType* element_type() const { return etype_; } inline const VType* element_type() const { return parent_ ? parent_->element_type() : etype_; }
// returns the basic type of element held in the array // returns the basic type of element held in the array
// (unfolds typedefs and multidimensional arrays) // (unfolds typedefs and multidimensional arrays)
@ -215,16 +238,29 @@ class VTypeArray : public VType {
int emit_def(std::ostream&out, perm_string name) const; int emit_def(std::ostream&out, perm_string name) const;
int emit_typedef(std::ostream&out, typedef_context_t&ctx) const; int emit_typedef(std::ostream&out, typedef_context_t&ctx) const;
int emit_dimensions(std::ostream&out) const;
bool can_be_packed() const { return etype_->can_be_packed(); } bool can_be_packed() const { return etype_->can_be_packed(); }
private: bool is_unbounded() const;
void write_range_to_stream_(std::ostream&fd) const;
const VType*etype_;
bool is_variable_length(ScopeBase*scope) const;
// To handle subtypes
inline void set_parent_type(const VTypeArray*parent) { parent_ = parent; }
// Wherever it is possible, replaces range lsb & msb expressions with
// constant integers.
void evaluate_ranges(ScopeBase*scope);
private:
int emit_with_dims_(std::ostream&out, bool packed, perm_string name) const;
void write_range_to_stream_(std::ostream&fd) const;
const VType*etype_;
std::vector<range_t> ranges_; std::vector<range_t> ranges_;
bool signed_flag_; bool signed_flag_;
const VTypeArray*parent_;
}; };
class VTypeRange : public VType { class VTypeRange : public VType {
@ -233,6 +269,8 @@ class VTypeRange : public VType {
VTypeRange(const VType*base, int64_t max_val, int64_t min_val); VTypeRange(const VType*base, int64_t max_val, int64_t min_val);
~VTypeRange(); ~VTypeRange();
VType*clone() const { return new VTypeRange(base_->clone(), max_, min_); }
// Get the type that is limited by the range. // Get the type that is limited by the range.
inline const VType* base_type() const { return base_; } inline const VType* base_type() const { return base_; }
@ -251,6 +289,8 @@ class VTypeEnum : public VType {
VTypeEnum(const std::list<perm_string>*names); VTypeEnum(const std::list<perm_string>*names);
~VTypeEnum(); ~VTypeEnum();
VType*clone() const { return new VTypeEnum(*this); }
void write_to_stream(std::ostream&fd) const; void write_to_stream(std::ostream&fd) const;
void show(std::ostream&) const; void show(std::ostream&) const;
int emit_def(std::ostream&out, perm_string name) const; int emit_def(std::ostream&out, perm_string name) const;
@ -284,6 +324,8 @@ class VTypeRecord : public VType {
explicit VTypeRecord(std::list<element_t*>*elements); explicit VTypeRecord(std::list<element_t*>*elements);
~VTypeRecord(); ~VTypeRecord();
VType*clone() const { return new VTypeRecord(*this); }
void write_to_stream(std::ostream&fd) const; void write_to_stream(std::ostream&fd) const;
void show(std::ostream&) const; void show(std::ostream&) const;
int emit_def(std::ostream&out, perm_string name) const; int emit_def(std::ostream&out, perm_string name) const;
@ -302,6 +344,8 @@ class VTypeDef : public VType {
explicit VTypeDef(perm_string name, const VType*is); explicit VTypeDef(perm_string name, const VType*is);
~VTypeDef(); ~VTypeDef();
VType*clone() const { return new VTypeDef(*this); }
inline perm_string peek_name() const { return name_; } inline perm_string peek_name() const { return name_; }
// If the type is not given a definition in the constructor, // If the type is not given a definition in the constructor,
@ -319,6 +363,8 @@ class VTypeDef : public VType {
int emit_def(std::ostream&out, perm_string name) const; int emit_def(std::ostream&out, perm_string name) const;
bool can_be_packed() const { return type_->can_be_packed(); } bool can_be_packed() const { return type_->can_be_packed(); }
bool is_unbounded() const { return type_->is_unbounded(); }
private: private:
int emit_decl(std::ostream&out, perm_string name, bool reg_flag) const; int emit_decl(std::ostream&out, perm_string name, bool reg_flag) const;

View File

@ -21,24 +21,24 @@
# include "vtype.h" # include "vtype.h"
# include "expression.h" # include "expression.h"
int VType::elaborate(Entity*, Architecture*) const int VType::elaborate(Entity*, ScopeBase*) const
{ {
return 0; return 0;
} }
int VTypeArray::elaborate(Entity*ent, Architecture*arc) const int VTypeArray::elaborate(Entity*ent, ScopeBase*scope) const
{ {
int errors = 0; int errors = 0;
etype_->elaborate(ent, arc); etype_->elaborate(ent, scope);
for (vector<range_t>::const_iterator cur = ranges_.begin() for (vector<range_t>::const_iterator cur = ranges_.begin()
; cur != ranges_.end() ; ++ cur) { ; cur != ranges_.end() ; ++ cur) {
Expression*tmp = cur->msb(); Expression*tmp = cur->msb();
if (tmp) errors += tmp->elaborate_expr(ent, arc, 0); if (tmp) errors += tmp->elaborate_expr(ent, scope, 0);
tmp = cur->lsb(); tmp = cur->lsb();
if (tmp) errors += tmp->elaborate_expr(ent, arc, 0); if (tmp) errors += tmp->elaborate_expr(ent, scope, 0);
} }
return errors; return errors;

View File

@ -59,9 +59,7 @@ int VTypeERROR::emit_def(ostream&out, perm_string) const
int VTypeArray::emit_def(ostream&out, perm_string name) const int VTypeArray::emit_def(ostream&out, perm_string name) const
{ {
int errors = 0; int errors = 0;
const VType*raw_base = basic_type(); const VType*raw_base = basic_type();
const VTypePrimitive*base = dynamic_cast<const VTypePrimitive*> (raw_base); const VTypePrimitive*base = dynamic_cast<const VTypePrimitive*> (raw_base);
if (base) { if (base) {
@ -74,13 +72,7 @@ int VTypeArray::emit_def(ostream&out, perm_string name) const
raw_base->emit_def(out, empty_perm_string); raw_base->emit_def(out, empty_perm_string);
} }
if(raw_base->can_be_packed()) { errors += emit_with_dims_(out, raw_base->can_be_packed(), name);
errors += emit_dimensions(out);
emit_name(out, name);
} else {
emit_name(out, name);
errors += emit_dimensions(out);
}
return errors; return errors;
} }
@ -90,7 +82,7 @@ int VTypeArray::emit_typedef(std::ostream&out, typedef_context_t&ctx) const
return etype_->emit_typedef(out, ctx); return etype_->emit_typedef(out, ctx);
} }
int VTypeArray::emit_dimensions(std::ostream&out) const int VTypeArray::emit_with_dims_(std::ostream&out, bool packed, perm_string name) const
{ {
int errors = 0; int errors = 0;
@ -102,18 +94,35 @@ int VTypeArray::emit_dimensions(std::ostream&out) const
} }
dims.push_back(cur); dims.push_back(cur);
bool name_emitted = false;
while (! dims.empty()) { while (! dims.empty()) {
cur = dims.front(); cur = dims.front();
dims.pop_front(); dims.pop_front();
out << "["; if(!packed) {
if (cur->dimension(0).msb() && cur->dimension(0).lsb()) { emit_name(out, name);
// bounded array, unbounded arrays have msb() & lsb() nullified name_emitted = true;
errors += cur->dimension(0).msb()->emit(out, 0, 0);
out << ":";
errors += cur->dimension(0).lsb()->emit(out, 0, 0);
} }
out << "]";
for(unsigned i = 0; i < cur->dimensions(); ++i) {
if(cur->dimension(i).is_box() && !name_emitted) {
emit_name(out, name);
name_emitted = true;
}
out << "[";
if (!cur->dimension(i).is_box()) { // if not unbounded {
errors += cur->dimension(i).msb()->emit(out, 0, 0);
out << ":";
errors += cur->dimension(i).lsb()->emit(out, 0, 0);
}
out << "]";
}
}
if(!name_emitted) {
emit_name(out, name);
} }
return errors; return errors;
@ -200,10 +209,11 @@ int VTypeRecord::emit_def(ostream&out, perm_string name) const
* type. (We are defining a variable here, not the type itself.) The * type. (We are defining a variable here, not the type itself.) The
* emit_typedef() method was presumably called to define type already. * emit_typedef() method was presumably called to define type already.
*/ */
int VTypeDef::emit_def(ostream&out, perm_string) const int VTypeDef::emit_def(ostream&out, perm_string name) const
{ {
int errors = 0; int errors = 0;
emit_name(out, name_); emit_name(out, name_);
emit_name(out, name);
return errors; return errors;
} }

View File

@ -143,6 +143,7 @@ static PLI_INT32 to_from_vec_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
case vpiReg: case vpiReg:
case vpiBitVar: case vpiBitVar:
case vpiIntegerVar: case vpiIntegerVar:
case vpiConstant:
break; break;
default: default:
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),