Merge pull request #52 from orsonmmz/unbounded_function
Unbounded vectors in VHDL functions.
This commit is contained in:
commit
d47afb588b
3
PExpr.h
3
PExpr.h
|
|
@ -999,6 +999,9 @@ class PECastType : public PExpr {
|
|||
|
||||
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,
|
||||
unsigned expr_wid, unsigned flags) const;
|
||||
|
||||
|
|
|
|||
35
elab_expr.cc
35
elab_expr.cc
|
|
@ -2536,11 +2536,44 @@ unsigned PECastType::test_width(Design*des, NetScope*scope, width_mode_t&wid)
|
|||
expr_width_ = t->packed_width();
|
||||
}
|
||||
|
||||
signed_flag_= t->get_signed();
|
||||
signed_flag_ = t->get_signed();
|
||||
min_width_ = 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,
|
||||
unsigned, unsigned) const
|
||||
{
|
||||
|
|
|
|||
33
pform.cc
33
pform.cc
|
|
@ -2661,7 +2661,6 @@ vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
|||
}
|
||||
|
||||
delete range;
|
||||
delete names;
|
||||
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));
|
||||
}
|
||||
delete names;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -2699,35 +2697,54 @@ vector<pform_tf_port_t>*pform_make_task_ports(const struct vlltype&loc,
|
|||
data_type_t*vtype,
|
||||
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)) {
|
||||
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,
|
||||
range_tmp, names);
|
||||
}
|
||||
|
||||
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,
|
||||
copy_range(vec_type->pdims.get()),
|
||||
names, vec_type->integer_flag);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -129,12 +129,15 @@ static int eval_darray_new(ivl_expr_t ex)
|
|||
unsigned wid;
|
||||
switch (ivl_type_base(element_type)) {
|
||||
case IVL_VT_BOOL:
|
||||
case IVL_VT_LOGIC:
|
||||
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) {
|
||||
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, " %%pop/vec4 1;\n");
|
||||
}
|
||||
break;
|
||||
case IVL_VT_REAL:
|
||||
|
|
|
|||
|
|
@ -444,7 +444,7 @@ static int show_stmt_assign_vector(ivl_statement_t net)
|
|||
fprintf(vvp_out, " %%cvt/vr %u;\n", wid);
|
||||
|
||||
} 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);
|
||||
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),
|
||||
|
|
@ -452,6 +452,28 @@ static int show_stmt_assign_vector(ivl_statement_t net)
|
|||
if (slices) free(slices);
|
||||
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 {
|
||||
unsigned wid = ivl_stmt_lwidth(net);
|
||||
draw_eval_vec4(rval);
|
||||
|
|
|
|||
|
|
@ -368,9 +368,11 @@ int SignalAssignment::elaborate(Entity*ent, Architecture*arc)
|
|||
return errors;
|
||||
}
|
||||
|
||||
for (list<Expression*>::const_iterator cur = rval_.begin()
|
||||
for (list<Expression*>::iterator cur = rval_.begin()
|
||||
; cur != rval_.end() ; ++cur) {
|
||||
(*cur)->elaborate_expr(ent, arc, lval_type);
|
||||
|
||||
// Handle functions that return unbounded arrays
|
||||
}
|
||||
|
||||
return errors;
|
||||
|
|
|
|||
|
|
@ -103,7 +103,9 @@ int Architecture::emit(ostream&out, Entity*entity)
|
|||
|
||||
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin()
|
||||
; 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()
|
||||
|
|
|
|||
|
|
@ -20,6 +20,7 @@
|
|||
*/
|
||||
|
||||
# include "expression.h"
|
||||
# include "subprogram.h"
|
||||
# include "parse_types.h"
|
||||
# include "scope.h"
|
||||
# include <iostream>
|
||||
|
|
@ -63,6 +64,11 @@ ExpAttribute::~ExpAttribute()
|
|||
delete base_;
|
||||
}
|
||||
|
||||
Expression*ExpAttribute::clone() const
|
||||
{
|
||||
return new ExpAttribute(static_cast<ExpName*>(base_->clone()), name_);
|
||||
}
|
||||
|
||||
ExpBinary::ExpBinary(Expression*op1, Expression*op2)
|
||||
: operand1_(op1), operand2_(op2)
|
||||
{
|
||||
|
|
@ -112,6 +118,23 @@ ExpAggregate::~ExpAggregate()
|
|||
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)
|
||||
: 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()
|
||||
{
|
||||
}
|
||||
|
|
@ -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()
|
||||
{
|
||||
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)
|
||||
: cond_(cond)
|
||||
{
|
||||
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()
|
||||
{
|
||||
delete cond_;
|
||||
|
|
@ -283,6 +361,27 @@ ExpFunc::~ExpFunc()
|
|||
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)
|
||||
: value_(val)
|
||||
{
|
||||
|
|
@ -423,3 +522,22 @@ ExpUNot::ExpUNot(Expression*op1)
|
|||
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_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,13 +31,11 @@
|
|||
|
||||
class prange_t;
|
||||
class Entity;
|
||||
class Architecture;
|
||||
class ScopeBase;
|
||||
class Subprogram;
|
||||
class VType;
|
||||
class VTypeArray;
|
||||
class VTypePrimitive;
|
||||
|
||||
class ExpName;
|
||||
|
||||
/*
|
||||
|
|
@ -51,18 +49,21 @@ class Expression : public LineInfo {
|
|||
Expression();
|
||||
virtual ~Expression() =0;
|
||||
|
||||
// Returns a deep copy of the expression.
|
||||
virtual Expression*clone() const =0;
|
||||
|
||||
// This virtual method handles the special case of elaborating
|
||||
// an expression that is the l-value of a sequential variable
|
||||
// assignment. This generates an error for most cases, but
|
||||
// expressions that are valid l-values return 0 and set any
|
||||
// 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);
|
||||
|
||||
// This virtual method probes the expression to get the most
|
||||
// constrained type for the expression. For a given instance,
|
||||
// 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
|
||||
// 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,
|
||||
// this is mostly about helping aggregate expressions within
|
||||
// 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
|
||||
// the type of the lvalue expression, if known, and can be
|
||||
// used to calculate the type for the expression being
|
||||
// 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
|
||||
// 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
|
||||
// of this expression to the designated stream. This is used
|
||||
// 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
|
||||
// output the generated code for the expression. The derived
|
||||
// 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
|
||||
// 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
|
||||
// cannot be done.
|
||||
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
|
||||
|
|
@ -134,6 +135,13 @@ class Expression : public LineInfo {
|
|||
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)
|
||||
{
|
||||
tgt->set_line(*src);
|
||||
|
|
@ -150,13 +158,15 @@ class ExpUnary : public Expression {
|
|||
ExpUnary(Expression*op1);
|
||||
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:
|
||||
inline void write_to_stream_operand1(std::ostream&fd)
|
||||
inline void write_to_stream_operand1(std::ostream&fd) const
|
||||
{ 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;
|
||||
|
||||
private:
|
||||
|
|
@ -173,23 +183,23 @@ class ExpBinary : public Expression {
|
|||
ExpBinary(Expression*op1, Expression*op2);
|
||||
virtual ~ExpBinary() =0;
|
||||
|
||||
const Expression* peek_operand1(void) const { return operand1_; }
|
||||
const Expression* peek_operand2(void) const { return operand2_; }
|
||||
inline const Expression* peek_operand1(void) const { return operand1_; }
|
||||
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:
|
||||
|
||||
int elaborate_exprs(Entity*, Architecture*, const VType*);
|
||||
int emit_operand1(ostream&out, Entity*ent, Architecture*arc);
|
||||
int emit_operand2(ostream&out, Entity*ent, Architecture*arc);
|
||||
int elaborate_exprs(Entity*, ScopeBase*, const VType*);
|
||||
int emit_operand1(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
int emit_operand2(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
|
||||
bool eval_operand1(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); }
|
||||
inline void write_to_stream_operand2(std::ostream&out)
|
||||
inline void write_to_stream_operand2(std::ostream&out) const
|
||||
{ operand2_->write_to_stream(out); }
|
||||
|
||||
void dump_operands(ostream&out, int indent = 0) const;
|
||||
|
|
@ -219,6 +229,9 @@ class ExpAggregate : public Expression {
|
|||
explicit choice_t(perm_string name);
|
||||
// discreate_range choice
|
||||
explicit choice_t(prange_t*ran);
|
||||
|
||||
choice_t(const choice_t&other);
|
||||
|
||||
~choice_t();
|
||||
|
||||
// true if this represents an "others" choice
|
||||
|
|
@ -235,11 +248,17 @@ class ExpAggregate : public Expression {
|
|||
std::auto_ptr<Expression>expr_;
|
||||
std::auto_ptr<prange_t> range_;
|
||||
private: // not implemented
|
||||
choice_t(const choice_t&);
|
||||
choice_t& operator= (const choice_t&);
|
||||
};
|
||||
|
||||
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;
|
||||
Expression*expr;
|
||||
bool alias_flag;
|
||||
|
|
@ -251,6 +270,7 @@ class ExpAggregate : public Expression {
|
|||
class element_t {
|
||||
public:
|
||||
explicit element_t(std::list<choice_t*>*fields, Expression*val);
|
||||
element_t(const element_t&other);
|
||||
~element_t();
|
||||
|
||||
size_t count_choices() const { return fields_.size(); }
|
||||
|
|
@ -265,7 +285,6 @@ class ExpAggregate : public Expression {
|
|||
std::vector<choice_t*>fields_;
|
||||
Expression*val_;
|
||||
private: // not implemented
|
||||
element_t(const element_t&);
|
||||
element_t& operator = (const element_t&);
|
||||
};
|
||||
|
||||
|
|
@ -273,19 +292,20 @@ class ExpAggregate : public Expression {
|
|||
ExpAggregate(std::list<element_t*>*el);
|
||||
~ExpAggregate();
|
||||
|
||||
Expression*clone() const;
|
||||
|
||||
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
|
||||
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);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
int elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype);
|
||||
int elaborate_expr_record_(Entity*ent, Architecture*arc, const VTypeRecord*ltype);
|
||||
int emit_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*ltype);
|
||||
int emit_record_(ostream&out, Entity*ent, Architecture*arc, const VTypeRecord*ltype);
|
||||
int elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype);
|
||||
int elaborate_expr_record_(Entity*ent, ScopeBase*scope, const VTypeRecord*ltype);
|
||||
int emit_array_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeArray*ltype);
|
||||
int emit_record_(ostream&out, Entity*ent, ScopeBase*scope, const VTypeRecord*ltype);
|
||||
|
||||
private:
|
||||
// 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();
|
||||
|
||||
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);
|
||||
Expression*clone() const {
|
||||
return new ExpArithmetic(fun_, peek_operand1()->clone(), peek_operand2()->clone());
|
||||
}
|
||||
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
virtual bool evaluate(ScopeBase*scope, int64_t&val) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
|
|
@ -324,16 +348,18 @@ class ExpAttribute : public Expression {
|
|||
ExpAttribute(ExpName*base, perm_string name);
|
||||
~ExpAttribute();
|
||||
|
||||
Expression*clone() const;
|
||||
|
||||
inline perm_string peek_attribute() const { return name_; }
|
||||
inline const ExpName* peek_base() const { return base_; }
|
||||
|
||||
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
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);
|
||||
// Some attributes can be evaluated at compile time
|
||||
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;
|
||||
|
||||
private:
|
||||
|
|
@ -345,12 +371,15 @@ class ExpBitstring : public Expression {
|
|||
|
||||
public:
|
||||
explicit ExpBitstring(const char*);
|
||||
ExpBitstring(const ExpBitstring&other) : Expression() { value_ = other.value_; }
|
||||
~ExpBitstring();
|
||||
|
||||
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
|
||||
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);
|
||||
Expression*clone() const { return new ExpBitstring(*this); }
|
||||
|
||||
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);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
|
|
@ -362,19 +391,22 @@ class ExpCharacter : public Expression {
|
|||
|
||||
public:
|
||||
ExpCharacter(char val);
|
||||
ExpCharacter(const ExpCharacter&other) : Expression() { value_ = other.value_; }
|
||||
~ExpCharacter();
|
||||
|
||||
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
|
||||
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);
|
||||
Expression*clone() const { return new ExpCharacter(*this); }
|
||||
|
||||
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);
|
||||
bool is_primary(void) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
char value() const { return value_; }
|
||||
|
||||
private:
|
||||
int emit_primitive_bit_(ostream&out, Entity*ent, Architecture*arc,
|
||||
int emit_primitive_bit_(ostream&out, Entity*ent, ScopeBase*scope,
|
||||
const VTypePrimitive*etype);
|
||||
|
||||
private:
|
||||
|
|
@ -387,17 +419,21 @@ class ExpConcat : public Expression {
|
|||
ExpConcat(Expression*op1, Expression*op2);
|
||||
~ExpConcat();
|
||||
|
||||
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
|
||||
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);
|
||||
Expression*clone() const {
|
||||
return new ExpConcat(operand1_->clone(), operand2_->clone());
|
||||
}
|
||||
|
||||
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;
|
||||
bool is_primary(void) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
int elaborate_expr_array_(Entity*ent, Architecture*arc, const VTypeArray*ltype);
|
||||
int elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype);
|
||||
|
||||
private:
|
||||
Expression*operand1_;
|
||||
|
|
@ -415,11 +451,12 @@ class ExpConditional : public Expression {
|
|||
class else_t : public LineInfo {
|
||||
public:
|
||||
else_t(Expression*cond, std::list<Expression*>*tru);
|
||||
else_t(const else_t&other);
|
||||
~else_t();
|
||||
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*lt);
|
||||
int emit_when_else(ostream&out, Entity*ent, Architecture*arc);
|
||||
int emit_else(ostream&out, Entity*ent, Architecture*arc);
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*lt);
|
||||
int emit_when_else(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
int emit_else(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
private:
|
||||
|
|
@ -432,10 +469,12 @@ class ExpConditional : public Expression {
|
|||
std::list<else_t*>*fal);
|
||||
~ExpConditional();
|
||||
|
||||
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||
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);
|
||||
Expression*clone() const;
|
||||
|
||||
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;
|
||||
|
||||
private:
|
||||
|
|
@ -457,10 +496,12 @@ class ExpEdge : public ExpUnary {
|
|||
explicit ExpEdge(ExpEdge::fun_t ty, Expression*op);
|
||||
~ExpEdge();
|
||||
|
||||
Expression*clone() const { return new ExpEdge(fun_, peek_operand()->clone()); }
|
||||
|
||||
inline fun_t edge_fun() const { return fun_; }
|
||||
|
||||
void write_to_stream(std::ostream&fd);
|
||||
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;
|
||||
|
||||
private:
|
||||
|
|
@ -474,14 +515,17 @@ class ExpFunc : public Expression {
|
|||
ExpFunc(perm_string nn, std::list<Expression*>*args);
|
||||
~ExpFunc();
|
||||
|
||||
Expression*clone() const;
|
||||
|
||||
inline perm_string func_name() const { return name_; }
|
||||
inline size_t func_args() const { return argv_.size(); }
|
||||
inline const Expression*func_arg(size_t idx) const { return argv_[idx]; }
|
||||
const VType*func_ret_type() const;
|
||||
|
||||
public: // Base methods
|
||||
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);
|
||||
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;
|
||||
|
||||
private:
|
||||
|
|
@ -494,14 +538,17 @@ class ExpInteger : public Expression {
|
|||
|
||||
public:
|
||||
ExpInteger(int64_t val);
|
||||
ExpInteger(const ExpInteger&other) : Expression(), value_(other.value_) {}
|
||||
~ExpInteger();
|
||||
|
||||
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||
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);
|
||||
Expression*clone() const { return new ExpInteger(*this); }
|
||||
|
||||
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);
|
||||
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;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
virtual ostream& dump_inline(ostream&out) const;
|
||||
|
|
@ -514,12 +561,15 @@ class ExpReal : public Expression {
|
|||
|
||||
public:
|
||||
ExpReal(double val);
|
||||
ExpReal(const ExpReal&other) : Expression(), value_(other.value_) {}
|
||||
~ExpReal();
|
||||
|
||||
const VType*probe_type(Entity*ent, Architecture*arc) const;
|
||||
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);
|
||||
Expression*clone() const { return new ExpReal(*this); }
|
||||
|
||||
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);
|
||||
int emit_package(std::ostream&out);
|
||||
bool is_primary(void) 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();
|
||||
|
||||
Expression*clone() const {
|
||||
return new ExpLogical(fun_, peek_operand1()->clone(), peek_operand2()->clone());
|
||||
}
|
||||
|
||||
inline fun_t logic_fun() const { return fun_; }
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
private:
|
||||
|
|
@ -565,31 +619,35 @@ class ExpName : public Expression {
|
|||
~ExpName();
|
||||
|
||||
public: // Base methods
|
||||
int elaborate_lval(Entity*ent, Architecture*arc, bool);
|
||||
int elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*);
|
||||
const VType* probe_type(Entity*ent, Architecture*arc) const;
|
||||
const VType* fit_type(Entity*ent, Architecture*arc, const VTypeArray*host) const;
|
||||
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);
|
||||
Expression*clone() const {
|
||||
return new ExpName(static_cast<ExpName*>(safe_clone(prefix_.get())),
|
||||
name_, safe_clone(index_), safe_clone(lsb_));
|
||||
}
|
||||
int elaborate_lval(Entity*ent, ScopeBase*scope, bool);
|
||||
int elaborate_rval(Entity*ent, ScopeBase*scope, const InterfacePort*);
|
||||
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 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;
|
||||
void dump(ostream&out, int indent = 0) 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);
|
||||
|
||||
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);
|
||||
const VType* probe_prefix_type_(Entity*ent, Architecture*arc) const;
|
||||
const VType* probe_prefixed_type_(Entity*ent, Architecture*arc) const;
|
||||
int elaborate_lval_(Entity*ent, ScopeBase*scope, bool, ExpName*suffix);
|
||||
const VType* probe_prefix_type_(Entity*ent, ScopeBase*scope) 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:
|
||||
std::auto_ptr<ExpName> prefix_;
|
||||
|
|
@ -604,8 +662,8 @@ class ExpNameALL : public ExpName {
|
|||
ExpNameALL() : ExpName(perm_string()) { }
|
||||
|
||||
public:
|
||||
int elaborate_lval(Entity*ent, Architecture*arc, bool);
|
||||
const VType* probe_type(Entity*ent, Architecture*arc) const;
|
||||
int elaborate_lval(Entity*ent, ScopeBase*scope, bool);
|
||||
const VType* probe_type(Entity*ent, ScopeBase*scope) 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();
|
||||
|
||||
const VType* probe_type(Entity*ent, Architecture*arc) const;
|
||||
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);
|
||||
Expression*clone() const {
|
||||
return new ExpRelation(fun_, peek_operand1()->clone(), peek_operand2()->clone());
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
private:
|
||||
|
|
@ -634,18 +696,21 @@ class ExpString : public Expression {
|
|||
|
||||
public:
|
||||
explicit ExpString(const char*);
|
||||
ExpString(const ExpString&other) : Expression(), value_(other.value_) {}
|
||||
~ExpString();
|
||||
|
||||
const VType*fit_type(Entity*ent, Architecture*arc, const VTypeArray*atype) const;
|
||||
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);
|
||||
Expression*clone() const { return new ExpString(*this); }
|
||||
|
||||
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);
|
||||
bool is_primary(void) const;
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
const std::vector<char>& get_value() const { return value_; }
|
||||
|
||||
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:
|
||||
std::vector<char> value_;
|
||||
|
|
@ -657,8 +722,10 @@ class ExpUAbs : public ExpUnary {
|
|||
ExpUAbs(Expression*op1);
|
||||
~ExpUAbs();
|
||||
|
||||
void write_to_stream(std::ostream&fd);
|
||||
int emit(ostream&out, Entity*ent, Architecture*arc);
|
||||
Expression*clone() const { return new ExpUAbs(peek_operand()->clone()); }
|
||||
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
};
|
||||
|
||||
|
|
@ -668,10 +735,56 @@ class ExpUNot : public ExpUnary {
|
|||
ExpUNot(Expression*op1);
|
||||
~ExpUNot();
|
||||
|
||||
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);
|
||||
Expression*clone() const { return new ExpUNot(peek_operand()->clone()); }
|
||||
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
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 */
|
||||
|
|
|
|||
|
|
@ -68,3 +68,17 @@ void ExpConcat::dump(ostream&out, int indent) const
|
|||
operand1_->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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -33,20 +33,20 @@
|
|||
|
||||
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;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const VType* Expression::probe_type(Entity*, Architecture*) const
|
||||
const VType* Expression::probe_type(Entity*, ScopeBase*) const
|
||||
{
|
||||
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) {
|
||||
cerr << get_fileline() << ": internal error: "
|
||||
<< "fit_type for " << typeid(*this).name()
|
||||
|
|
@ -56,7 +56,7 @@ const VType* Expression::fit_type(Entity*ent, Architecture*arc, const VTypeArray
|
|||
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
|
||||
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;
|
||||
bool flag;
|
||||
|
||||
flag = index_->evaluate(arc, use_msb);
|
||||
flag = index_->evaluate(scope, use_msb);
|
||||
ivl_assert(*this, flag);
|
||||
flag = lsb_->evaluate(arc, use_lsb);
|
||||
flag = lsb_->evaluate(scope, use_lsb);
|
||||
ivl_assert(*this, flag);
|
||||
|
||||
Expression*exp_msb = new ExpInteger(use_msb);
|
||||
|
|
@ -91,7 +91,7 @@ const VType*ExpName::elaborate_adjust_type_with_range_(Entity*, Architecture*arc
|
|||
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;
|
||||
|
||||
|
|
@ -134,13 +134,13 @@ int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName
|
|||
<< ent->get_name() << "." << endl;
|
||||
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.
|
||||
if (is_sequ) sig->count_ref_sequ();
|
||||
|
||||
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.
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
suffix->set_type(suffix_type);
|
||||
|
|
@ -209,12 +209,12 @@ int ExpName::elaborate_lval_(Entity*ent, Architecture*arc, bool is_sequ, ExpName
|
|||
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;
|
||||
|
||||
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;
|
||||
|
|
@ -238,13 +238,13 @@ int ExpName::elaborate_lval(Entity*ent, Architecture*arc, bool is_sequ)
|
|||
<< ent->get_name() << "." << endl;
|
||||
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.
|
||||
if (is_sequ) sig->count_ref_sequ();
|
||||
|
||||
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.
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
|
||||
|
|
@ -295,7 +295,7 @@ int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lv
|
|||
default:
|
||||
break;
|
||||
}
|
||||
} else if (arc->find_signal(name_)) {
|
||||
} else if (scope->find_signal(name_)) {
|
||||
/* OK */
|
||||
|
||||
} else if (ent->find_generic(name_)) {
|
||||
|
|
@ -310,21 +310,21 @@ int ExpName::elaborate_rval(Entity*ent, Architecture*arc, const InterfacePort*lv
|
|||
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;
|
||||
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*t2 = operand2_->probe_type(ent, arc);
|
||||
const VType*t1 = operand1_->probe_type(ent, scope);
|
||||
const VType*t2 = operand2_->probe_type(ent, scope);
|
||||
|
||||
if (t1 == 0)
|
||||
return t2;
|
||||
|
|
@ -351,12 +351,12 @@ const VType*ExpBinary::resolve_operand_types_(const VType*, const VType*) const
|
|||
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;
|
||||
|
||||
errors += operand1_->elaborate_expr(ent, arc, ltype);
|
||||
errors += operand2_->elaborate_expr(ent, arc, ltype);
|
||||
errors += operand1_->elaborate_expr(ent, scope, ltype);
|
||||
errors += operand2_->elaborate_expr(ent, scope, ltype);
|
||||
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
|
||||
* 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);
|
||||
size_t choice_count = elements_[0]->count_choices();
|
||||
|
|
@ -401,7 +401,7 @@ const VType*ExpAggregate::fit_type(Entity*, Architecture*, const VTypeArray*host
|
|||
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) {
|
||||
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)) {
|
||||
return elaborate_expr_array_(ent, arc, larray);
|
||||
return elaborate_expr_array_(ent, scope, larray);
|
||||
}
|
||||
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;
|
||||
|
|
@ -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
|
||||
* 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();
|
||||
int errors = 0;
|
||||
|
|
@ -476,7 +476,7 @@ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTyp
|
|||
if (aggregate_[idx].alias_flag)
|
||||
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.
|
||||
|
|
@ -485,7 +485,7 @@ int ExpAggregate::elaborate_expr_array_(Entity*ent, Architecture*arc, const VTyp
|
|||
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;
|
||||
|
||||
|
|
@ -513,10 +513,12 @@ int ExpAggregate::elaborate_expr_record_(Entity*ent, Architecture*arc, const VTy
|
|||
ivl_assert(*this, field);
|
||||
|
||||
perm_string field_name = field->peek_name();
|
||||
idx = -1;
|
||||
const VTypeRecord::element_t*el = ltype->element_by_name(field_name, &idx);
|
||||
ivl_assert(*this, idx >= 0);
|
||||
|
||||
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.
|
||||
|
|
@ -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;
|
||||
|
||||
if (ltype == 0) {
|
||||
ltype = probe_type(ent, arc);
|
||||
ltype = probe_type(ent, scope);
|
||||
}
|
||||
|
||||
ivl_assert(*this, ltype != 0);
|
||||
errors += elaborate_exprs(ent, arc, ltype);
|
||||
errors += elaborate_exprs(ent, scope, ltype);
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
|
@ -563,9 +565,9 @@ const VType* ExpArithmetic::resolve_operand_types_(const VType*t1, const VType*t
|
|||
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") {
|
||||
return &primitive_INTEGER;
|
||||
|
|
@ -574,42 +576,46 @@ const VType* ExpAttribute::probe_type(Entity*ent, Architecture*arc) const
|
|||
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;
|
||||
const VType*sub_type = base_->probe_type(ent, arc);
|
||||
errors += base_->elaborate_expr(ent, arc, sub_type);
|
||||
const VType*sub_type = base_->probe_type(ent, scope);
|
||||
errors += base_->elaborate_expr(ent, scope, sub_type);
|
||||
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
|
||||
// array 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;
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
// array 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);
|
||||
set_type(ltype);
|
||||
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_};
|
||||
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
|
||||
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])) {
|
||||
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.
|
||||
*/
|
||||
const VType*ExpConcat::probe_type(Entity*, Architecture*) const
|
||||
const VType*ExpConcat::probe_type(Entity*, ScopeBase*) const
|
||||
{
|
||||
ivl_assert(*this, 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;
|
||||
|
||||
if (ltype == 0) {
|
||||
ltype = probe_type(ent, arc);
|
||||
ltype = probe_type(ent, scope);
|
||||
}
|
||||
|
||||
ivl_assert(*this, ltype != 0);
|
||||
|
||||
if (const VTypeArray*atype = dynamic_cast<const VTypeArray*>(ltype)) {
|
||||
errors += elaborate_expr_array_(ent, arc, atype);
|
||||
errors += elaborate_expr_array_(ent, scope, atype);
|
||||
} else {
|
||||
errors += operand1_->elaborate_expr(ent, arc, ltype);
|
||||
errors += operand2_->elaborate_expr(ent, arc, ltype);
|
||||
errors += operand1_->elaborate_expr(ent, scope, ltype);
|
||||
errors += operand2_->elaborate_expr(ent, scope, ltype);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
// For now, only support single-dimension arrays here.
|
||||
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);
|
||||
|
||||
const VType*type2 = operand2_->fit_type(ent, arc, atype);
|
||||
const VType*type2 = operand2_->fit_type(ent, scope, atype);
|
||||
ivl_assert(*this, type2);
|
||||
|
||||
errors += operand1_->elaborate_expr(ent, arc, type1);
|
||||
errors += operand2_->elaborate_expr(ent, arc, type2);
|
||||
errors += operand1_->elaborate_expr(ent, scope, type1);
|
||||
errors += operand2_->elaborate_expr(ent, scope, type2);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
const VType* ExpConditional::probe_type(Entity*, Architecture*) const
|
||||
const VType* ExpConditional::probe_type(Entity*, ScopeBase*) const
|
||||
{
|
||||
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;
|
||||
|
||||
if (ltype == 0)
|
||||
ltype = probe_type(ent, arc);
|
||||
ltype = probe_type(ent, scope);
|
||||
|
||||
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
|
||||
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()
|
||||
; 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()
|
||||
; cur != else_clause_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate_expr(ent, arc, ltype);
|
||||
errors += (*cur)->elaborate_expr(ent, scope, ltype);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
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()
|
||||
; cur != true_clause_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate_expr(ent, arc, ltype);
|
||||
errors += (*cur)->elaborate_expr(ent, scope, ltype);
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
ivl_assert(*this, arc);
|
||||
Subprogram*prog = arc->find_subprogram(name_);
|
||||
ivl_assert(*this, scope);
|
||||
Subprogram*prog = scope->find_subprogram(name_);
|
||||
|
||||
if(!prog)
|
||||
prog = library_find_subprogram(name_);
|
||||
|
|
@ -751,27 +757,36 @@ int ExpFunc::elaborate_expr(Entity*ent, Architecture*arc, const VType*)
|
|||
ivl_assert(*this, def_==0);
|
||||
def_ = prog;
|
||||
|
||||
// Elaborate arguments
|
||||
for (size_t idx = 0 ; idx < argv_.size() ; idx += 1) {
|
||||
const VType*tmp = argv_[idx]->probe_type(ent, arc);
|
||||
if(!tmp && prog)
|
||||
tmp = prog->peek_param_type(idx);
|
||||
errors += argv_[idx]->elaborate_expr(ent, arc, tmp);
|
||||
const VType*tmp = argv_[idx]->probe_type(ent, scope);
|
||||
const VType*param_type = prog ? prog->peek_param_type(idx) : NULL;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
const VType* ExpInteger::probe_type(Entity*, Architecture*) const
|
||||
const VType* ExpInteger::probe_type(Entity*, ScopeBase*) const
|
||||
{
|
||||
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;
|
||||
|
||||
if (ltype == 0) {
|
||||
ltype = probe_type(ent, arc);
|
||||
ltype = probe_type(ent, scope);
|
||||
}
|
||||
|
||||
ivl_assert(*this, ltype != 0);
|
||||
|
|
@ -779,17 +794,17 @@ int ExpInteger::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
|||
return errors;
|
||||
}
|
||||
|
||||
const VType* ExpReal::probe_type(Entity*, Architecture*) const
|
||||
const VType* ExpReal::probe_type(Entity*, ScopeBase*) const
|
||||
{
|
||||
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;
|
||||
|
||||
if (ltype == 0) {
|
||||
ltype = probe_type(ent, arc);
|
||||
ltype = probe_type(ent, scope);
|
||||
}
|
||||
|
||||
ivl_assert(*this, ltype != 0);
|
||||
|
|
@ -797,27 +812,27 @@ int ExpReal::elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype)
|
|||
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;
|
||||
|
||||
if (ltype == 0) {
|
||||
ltype = probe_type(ent, arc);
|
||||
ltype = probe_type(ent, scope);
|
||||
}
|
||||
|
||||
ivl_assert(*this, ltype != 0);
|
||||
errors += elaborate_exprs(ent, arc, ltype);
|
||||
errors += elaborate_exprs(ent, scope, ltype);
|
||||
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()) {
|
||||
cerr << get_fileline() << ": sorry: I do not know how to support nested prefix parts." << endl;
|
||||
return 0;
|
||||
}
|
||||
|
||||
const VType*type = probe_type(ent, arc);
|
||||
const VType*type = probe_type(ent, scope);
|
||||
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
|
||||
* 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.
|
||||
const VType*prefix_type = prefix_->probe_prefix_type_(ent, arc);
|
||||
const VType*prefix_type = prefix_->probe_prefix_type_(ent, scope);
|
||||
if (prefix_type == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -857,34 +872,40 @@ const VType* ExpName::probe_prefixed_type_(Entity*ent, Architecture*arc) const
|
|||
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())
|
||||
return probe_prefixed_type_(ent, arc);
|
||||
return probe_prefixed_type_(ent, scope);
|
||||
|
||||
if (const InterfacePort*cur = ent->find_port(name_)) {
|
||||
ivl_assert(*this, cur->type);
|
||||
return cur->type;
|
||||
if(ent) {
|
||||
if (const InterfacePort*cur = ent->find_port(name_)) {
|
||||
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_)) {
|
||||
ivl_assert(*this, cur->type);
|
||||
return cur->type;
|
||||
}
|
||||
if(scope) {
|
||||
if (Signal*sig = scope->find_signal(name_))
|
||||
return sig->peek_type();
|
||||
|
||||
if (Signal*sig = arc->find_signal(name_))
|
||||
return sig->peek_type();
|
||||
if (Variable*var = scope->find_variable(name_))
|
||||
return var->peek_type();
|
||||
|
||||
if (Variable*var = arc->find_variable(name_))
|
||||
return var->peek_type();
|
||||
const VType*ctype = 0;
|
||||
Expression*cval = 0;
|
||||
if (scope->find_constant(name_, ctype, cval))
|
||||
return ctype;
|
||||
|
||||
const VType*ctype = 0;
|
||||
Expression*cval = 0;
|
||||
if (arc->find_constant(name_, ctype, cval))
|
||||
return ctype;
|
||||
|
||||
if (const VType*gtype = arc->probe_genvar_type(name_)) {
|
||||
return gtype;
|
||||
const VType*gtype = 0;
|
||||
Architecture*arc = dynamic_cast<Architecture*>(scope);
|
||||
if (arc && (gtype = arc->probe_genvar_type(name_))) {
|
||||
return gtype;
|
||||
}
|
||||
}
|
||||
|
||||
cerr << get_fileline() << ": error: Signal/variable " << name_
|
||||
|
|
@ -892,12 +913,12 @@ const VType* ExpName::probe_type(Entity*ent, Architecture*arc) const
|
|||
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) {
|
||||
ivl_assert(*this, ltype != 0);
|
||||
|
|
@ -907,22 +928,22 @@ int ExpName::elaborate_expr(Entity*, Architecture*, const VType*ltype)
|
|||
return 0;
|
||||
}
|
||||
|
||||
const VType* ExpNameALL::probe_type(Entity*, Architecture*) const
|
||||
const VType* ExpNameALL::probe_type(Entity*, ScopeBase*) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const VType* ExpRelation::probe_type(Entity*, Architecture*) const
|
||||
const VType* ExpRelation::probe_type(Entity*, ScopeBase*) const
|
||||
{
|
||||
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;
|
||||
|
||||
if (ltype == 0) {
|
||||
ltype = probe_type(ent, arc);
|
||||
ltype = probe_type(ent, scope);
|
||||
}
|
||||
|
||||
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
|
||||
// type for the ExpRelation itself. So get the operand type
|
||||
// separately.
|
||||
const VType*otype = ExpBinary::probe_type(ent, arc);
|
||||
errors += elaborate_exprs(ent, arc, otype);
|
||||
const VType*otype = ExpBinary::probe_type(ent, scope);
|
||||
errors += elaborate_exprs(ent, scope, otype);
|
||||
|
||||
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,
|
||||
* 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());
|
||||
|
||||
|
|
@ -957,14 +978,14 @@ const VType*ExpString::fit_type(Entity*, Architecture*, const VTypeArray*atype)
|
|||
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);
|
||||
set_type(ltype);
|
||||
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);
|
||||
set_type(ltype);
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
int Expression::emit(ostream&out, Entity*, Architecture*)
|
||||
int Expression::emit(ostream&out, Entity*, ScopeBase*)
|
||||
{
|
||||
out << " /* " << get_fileline() << ": internal error: "
|
||||
<< "I don't know how to emit this expression! "
|
||||
|
|
@ -54,34 +54,34 @@ bool Expression::is_primary(void) const
|
|||
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;
|
||||
bool oper_primary = operand1_->is_primary();
|
||||
if (! oper_primary) out << "(";
|
||||
errors += operand1_->emit(out, ent, arc);
|
||||
errors += operand1_->emit(out, ent, scope);
|
||||
if (! oper_primary) out << ")";
|
||||
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;
|
||||
bool oper_primary = operand2_->is_primary();
|
||||
if (! oper_primary) out << "(";
|
||||
errors += operand2_->emit(out, ent, arc);
|
||||
errors += operand2_->emit(out, ent, scope);
|
||||
if (! oper_primary) out << ")";
|
||||
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;
|
||||
errors += operand1_->emit(out, ent, arc);
|
||||
errors += operand1_->emit(out, ent, scope);
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpAggregate::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpAggregate::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
if (peek_type() == 0) {
|
||||
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))
|
||||
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))
|
||||
return emit_record_(out, ent, arc, arecord);
|
||||
return emit_record_(out, ent, scope, arecord);
|
||||
|
||||
out << "/* " << get_fileline() << ": internal error: "
|
||||
<< "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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
|
@ -119,14 +119,14 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
|
|||
int64_t use_msb;
|
||||
int64_t use_lsb;
|
||||
bool rc_msb, rc_lsb;
|
||||
rc_msb = rang.msb()->evaluate(ent, arc, use_msb);
|
||||
rc_lsb = rang.lsb()->evaluate(ent, arc, use_lsb);
|
||||
rc_msb = rang.msb()->evaluate(ent, scope, use_msb);
|
||||
rc_lsb = rang.lsb()->evaluate(ent, scope, use_lsb);
|
||||
|
||||
if (rc_msb && rc_lsb) {
|
||||
int asize = (use_msb >= use_lsb) ? (use_msb - use_lsb) + 1 :
|
||||
(use_lsb - use_msb) + 1;
|
||||
out << "{" << asize << "{";
|
||||
errors += aggregate_[0].expr->emit(out, ent, arc);
|
||||
errors += aggregate_[0].expr->emit(out, ent, scope);
|
||||
out << "}}";
|
||||
} else {
|
||||
out << "{(";
|
||||
|
|
@ -134,7 +134,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
|
|||
out << use_msb;
|
||||
} else {
|
||||
out << "(";
|
||||
errors += rang.msb()->emit(out, ent, arc);
|
||||
errors += rang.msb()->emit(out, ent, scope);
|
||||
out << ")";
|
||||
}
|
||||
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;
|
||||
} else {
|
||||
out << "-(";
|
||||
errors += rang.lsb()->emit(out, ent, arc);
|
||||
errors += rang.lsb()->emit(out, ent, scope);
|
||||
out << ")";
|
||||
}
|
||||
out << "+1){";
|
||||
errors += aggregate_[0].expr->emit(out, ent, arc);
|
||||
errors += aggregate_[0].expr->emit(out, ent, scope);
|
||||
out << "}}";
|
||||
}
|
||||
return errors;
|
||||
|
|
@ -158,9 +158,9 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
|
|||
// Fully calculate the range numbers.
|
||||
int64_t use_msb, use_lsb;
|
||||
bool rc;
|
||||
rc = rang.msb()->evaluate(ent, arc, use_msb);
|
||||
rc = rang.msb()->evaluate(ent, scope, use_msb);
|
||||
ivl_assert(*this, rc);
|
||||
rc = rang.lsb()->evaluate(ent, arc, use_lsb);
|
||||
rc = rang.lsb()->evaluate(ent, scope, use_lsb);
|
||||
ivl_assert(*this, rc);
|
||||
if(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()) {
|
||||
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: "
|
||||
<< "Unable to evaluate aggregate choice expression." << endl;
|
||||
errors += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! range->lsb()->evaluate(ent, arc, end_val)) {
|
||||
if (! range->lsb()->evaluate(ent, scope, end_val)) {
|
||||
cerr << range->msb()->get_fileline() << ": error: "
|
||||
<< "Unable to evaluate aggregate choice expression." << endl;
|
||||
errors += 1;
|
||||
|
|
@ -235,7 +235,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
|
|||
// elements so disable further positional
|
||||
// processing.
|
||||
positional_section = false;
|
||||
if (! tmp->evaluate(ent, arc, tmp_val)) {
|
||||
if (! tmp->evaluate(ent, scope, tmp_val)) {
|
||||
cerr << tmp->get_fileline() << ": error: "
|
||||
<< "Unable to evaluate aggregate choice expression." << endl;
|
||||
errors += 1;
|
||||
|
|
@ -266,7 +266,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
|
|||
<< "Missing element " << idx << "." << endl;
|
||||
errors += 1;
|
||||
} else {
|
||||
errors += cur->expr->emit(out, ent, arc);
|
||||
errors += cur->expr->emit(out, ent, scope);
|
||||
}
|
||||
}
|
||||
out << "}";
|
||||
|
|
@ -274,7 +274,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V
|
|||
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;
|
||||
|
||||
|
|
@ -292,9 +292,9 @@ int ExpAggregate::emit_record_(ostream&out, Entity*ent, Architecture*arc, const
|
|||
if(idx != 0)
|
||||
out << ",";
|
||||
|
||||
//errors += name->emit(out, ent, arc);
|
||||
//errors += name->emit(out, ent, scope);
|
||||
//out << ": ";
|
||||
errors += val->emit(out, ent, arc);
|
||||
errors += val->emit(out, ent, scope);
|
||||
}
|
||||
|
||||
out << "}";
|
||||
|
|
@ -302,13 +302,13 @@ int ExpAggregate::emit_record_(ostream&out, Entity*ent, Architecture*arc, const
|
|||
return errors;
|
||||
}
|
||||
|
||||
int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpAttribute::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (name_ == "event") {
|
||||
out << "$ivlh_attribute_event(";
|
||||
errors += base_->emit(out, ent, arc);
|
||||
errors += base_->emit(out, ent, scope);
|
||||
out << ")";
|
||||
return errors;
|
||||
}
|
||||
|
|
@ -319,27 +319,27 @@ int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
expression doesn't even need to be evaluated.) */
|
||||
if (name_=="length") {
|
||||
out << "$bits(";
|
||||
errors += base_->emit(out, ent, arc);
|
||||
errors += base_->emit(out, ent, scope);
|
||||
out << ")";
|
||||
return errors;
|
||||
} else if (name_=="left" || name_=="right") {
|
||||
out << "$" << name_ << "(";
|
||||
errors += base_->emit(out, ent, arc);
|
||||
errors += base_->emit(out, ent, scope);
|
||||
out << ")";
|
||||
return errors;
|
||||
}
|
||||
|
||||
out << "$ivl_attribute(";
|
||||
errors += base_->emit(out, ent, arc);
|
||||
errors += base_->emit(out, ent, scope);
|
||||
out << ", \"" << name_ << "\")";
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpArithmetic::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += emit_operand1(out, ent, arc);
|
||||
errors += emit_operand1(out, ent, scope);
|
||||
|
||||
switch (fun_) {
|
||||
case PLUS:
|
||||
|
|
@ -369,12 +369,12 @@ int ExpArithmetic::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
break;
|
||||
}
|
||||
|
||||
errors += emit_operand2(out, ent, arc);
|
||||
errors += emit_operand2(out, ent, scope);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpBitstring::emit(ostream&out, Entity*, Architecture*)
|
||||
int ExpBitstring::emit(ostream&out, Entity*, ScopeBase*)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
|
|
@ -385,7 +385,7 @@ int ExpBitstring::emit(ostream&out, Entity*, Architecture*)
|
|||
return errors;
|
||||
}
|
||||
|
||||
int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, Architecture*,
|
||||
int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, ScopeBase*,
|
||||
const VTypePrimitive*etype)
|
||||
{
|
||||
switch (etype->type()) {
|
||||
|
|
@ -407,17 +407,17 @@ int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, Architecture*,
|
|||
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();
|
||||
|
||||
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 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;
|
||||
}
|
||||
|
||||
int ExpConcat::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpConcat::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
out << "{";
|
||||
errors += operand1_->emit(out, ent, arc);
|
||||
errors += operand1_->emit(out, ent, scope);
|
||||
out << ", ";
|
||||
errors += operand2_->emit(out, ent, arc);
|
||||
errors += operand2_->emit(out, ent, scope);
|
||||
out << "}";
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpConditional::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
out << "(";
|
||||
errors += cond_->emit(out, ent, arc);
|
||||
errors += cond_->emit(out, ent, scope);
|
||||
out << ")? (";
|
||||
|
||||
if (true_clause_.size() > 1) {
|
||||
|
|
@ -463,7 +463,7 @@ int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
}
|
||||
|
||||
Expression*tmp = true_clause_.front();
|
||||
errors += tmp->emit(out, ent, arc);
|
||||
errors += tmp->emit(out, ent, scope);
|
||||
|
||||
out << ") : (";
|
||||
|
||||
|
|
@ -475,11 +475,11 @@ int ExpConditional::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
|
||||
for (list<else_t*>::iterator cur = else_clause_.begin()
|
||||
; 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 << ")";
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
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;
|
||||
assert(cond_ != 0);
|
||||
|
||||
out << "(";
|
||||
errors += cond_->emit(out, ent, arc);
|
||||
errors += cond_->emit(out, ent, scope);
|
||||
out << ")? (";
|
||||
|
||||
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();
|
||||
errors += tmp->emit(out, ent, arc);
|
||||
errors += tmp->emit(out, ent, scope);
|
||||
|
||||
out << ") : (";
|
||||
|
||||
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;
|
||||
// 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();
|
||||
errors += tmp->emit(out, ent, arc);
|
||||
errors += tmp->emit(out, ent, scope);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpEdge::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpEdge::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
switch (fun_) {
|
||||
|
|
@ -544,11 +544,11 @@ int ExpEdge::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
case ANYEDGE:
|
||||
break;
|
||||
}
|
||||
errors += emit_operand1(out, ent, arc);
|
||||
errors += emit_operand1(out, ent, scope);
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
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
|
||||
// as the $unsigned function.
|
||||
out << "$unsigned(";
|
||||
errors += argv_[0]->emit(out, ent, arc);
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "integer" && argv_.size() == 1) {
|
||||
// Simply skip the function name, SystemVerilog takes care of
|
||||
// rounding real numbers
|
||||
errors += argv_[0]->emit(out, ent, arc);
|
||||
out << "$signed(";
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "std_logic_vector" && argv_.size() == 1) {
|
||||
// Special case: The std_logic_vector function casts its
|
||||
// argument to std_logic_vector. Internally, we don't
|
||||
// have to do anything for that to work.
|
||||
out << "(";
|
||||
errors += argv_[0]->emit(out, ent, arc);
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "to_unsigned" && argv_.size() == 2) {
|
||||
|
||||
out << "$ivlh_to_unsigned(";
|
||||
errors += argv_[0]->emit(out, ent, arc);
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ", ";
|
||||
errors += argv_[1]->emit(out, ent, arc);
|
||||
errors += argv_[1]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "conv_std_logic_vector" && argv_.size() == 2) {
|
||||
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);
|
||||
out << use_size << "'(";
|
||||
errors += argv_[0]->emit(out, ent, arc);
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "rising_edge" && argv_.size()==1) {
|
||||
out << "$ivlh_rising_edge(";
|
||||
errors += argv_[0]->emit(out, ent, arc);
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else if (name_ == "falling_edge" && argv_.size()==1) {
|
||||
out << "$ivlh_falling_edge(";
|
||||
errors += argv_[0]->emit(out, ent, arc);
|
||||
errors += argv_[0]->emit(out, ent, scope);
|
||||
out << ")";
|
||||
|
||||
} else {
|
||||
|
|
@ -615,7 +615,7 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
out << "\\" << name_ << " (";
|
||||
for (size_t idx = 0; idx < argv_.size() ; idx += 1) {
|
||||
if (idx > 0) out << ", ";
|
||||
errors += argv_[idx]->emit(out, ent, arc);
|
||||
errors += argv_[idx]->emit(out, ent, scope);
|
||||
}
|
||||
out << ")";
|
||||
}
|
||||
|
|
@ -623,7 +623,7 @@ int ExpFunc::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
return errors;
|
||||
}
|
||||
|
||||
int ExpInteger::emit(ostream&out, Entity*, Architecture*)
|
||||
int ExpInteger::emit(ostream&out, Entity*, ScopeBase*)
|
||||
{
|
||||
out << value_;
|
||||
return 0;
|
||||
|
|
@ -635,12 +635,7 @@ int ExpInteger::emit_package(ostream&out)
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool ExpInteger::is_primary(void) const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int ExpReal::emit(ostream&out, Entity*, Architecture*)
|
||||
int ExpReal::emit(ostream&out, Entity*, ScopeBase*)
|
||||
{
|
||||
out << value_;
|
||||
return 0;
|
||||
|
|
@ -657,11 +652,11 @@ bool ExpReal::is_primary(void) const
|
|||
return true;
|
||||
}
|
||||
|
||||
int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpLogical::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += emit_operand1(out, ent, arc);
|
||||
errors += emit_operand1(out, ent, scope);
|
||||
|
||||
switch (fun_) {
|
||||
case AND:
|
||||
|
|
@ -684,22 +679,22 @@ int ExpLogical::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
break;
|
||||
}
|
||||
|
||||
errors += emit_operand2(out, ent, arc);
|
||||
errors += emit_operand2(out, ent, scope);
|
||||
|
||||
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;
|
||||
if (prefix_.get()) {
|
||||
errors += prefix_->emit_as_prefix_(out, ent, arc);
|
||||
errors += prefix_->emit_as_prefix_(out, ent, scope);
|
||||
}
|
||||
|
||||
out << "\\" << name_ << " ";
|
||||
if (index_) {
|
||||
out << "[";
|
||||
errors += index_->emit(out, ent, arc);
|
||||
errors += index_->emit(out, ent, scope);
|
||||
out << "]";
|
||||
ivl_assert(*this, lsb_ == 0);
|
||||
}
|
||||
|
|
@ -707,27 +702,28 @@ int ExpName::emit_as_prefix_(ostream&out, Entity*ent, Architecture*arc)
|
|||
return errors;
|
||||
}
|
||||
|
||||
int ExpName::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpName::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if (prefix_.get()) {
|
||||
errors += prefix_->emit_as_prefix_(out, ent, arc);
|
||||
errors += prefix_->emit_as_prefix_(out, ent, scope);
|
||||
}
|
||||
|
||||
const GenerateStatement*gs = 0;
|
||||
Architecture*arc = dynamic_cast<Architecture*>(scope);
|
||||
if (arc && (gs = arc->probe_genvar_emit(name_)))
|
||||
out << "\\" << gs->get_name() << ":" << name_ << " ";
|
||||
out << "\\" << gs->get_name() << ":" << name_ << " ";
|
||||
else
|
||||
out << "\\" << name_ << " ";
|
||||
|
||||
if (index_) {
|
||||
out << "[";
|
||||
errors += index_->emit(out, ent, arc);
|
||||
errors += index_->emit(out, ent, scope);
|
||||
|
||||
if (lsb_) {
|
||||
out << ":";
|
||||
errors += lsb_->emit(out, ent, arc);
|
||||
errors += lsb_->emit(out, ent, scope);
|
||||
}
|
||||
out << "]";
|
||||
}
|
||||
|
|
@ -740,10 +736,10 @@ bool ExpName::is_primary(void) const
|
|||
return true;
|
||||
}
|
||||
|
||||
int ExpRelation::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpRelation::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
errors += emit_operand1(out, ent, arc);
|
||||
errors += emit_operand1(out, ent, scope);
|
||||
|
||||
switch (fun_) {
|
||||
case EQ:
|
||||
|
|
@ -766,7 +762,7 @@ int ExpRelation::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
break;
|
||||
}
|
||||
|
||||
errors += emit_operand2(out, ent, arc);
|
||||
errors += emit_operand2(out, ent, scope);
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
|
@ -775,13 +771,13 @@ bool ExpString::is_primary(void) const
|
|||
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();
|
||||
assert(type != 0);
|
||||
|
||||
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 << "\"";
|
||||
|
|
@ -792,7 +788,7 @@ int ExpString::emit(ostream& out, Entity*ent, Architecture*arc)
|
|||
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;
|
||||
assert(arr->dimensions() == 1);
|
||||
|
|
@ -843,20 +839,39 @@ int ExpString::emit_as_array_(ostream& out, Entity*, Architecture*, const VTypeA
|
|||
return errors;
|
||||
}
|
||||
|
||||
int ExpUAbs::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpUAbs::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
out << "abs(";
|
||||
errors += emit_operand1(out, ent, arc);
|
||||
errors += emit_operand1(out, ent, scope);
|
||||
out << ")";
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ExpUNot::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int ExpUNot::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
out << "~(";
|
||||
errors += emit_operand1(out, ent, arc);
|
||||
errors += emit_operand1(out, ent, scope);
|
||||
out << ")";
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
/*
|
||||
* 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
|
||||
* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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
|
||||
needs is the type of the base expression. (The base
|
||||
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();
|
||||
//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);
|
||||
if (arr == 0) {
|
||||
|
|
@ -97,25 +112,43 @@ bool ExpAttribute::evaluate(ScopeBase*, int64_t&val) const
|
|||
return false;
|
||||
}
|
||||
|
||||
int64_t size = 1;
|
||||
for (size_t idx = 0 ; idx < arr->dimensions() ; idx += 1) {
|
||||
const VTypeArray::range_t&dim = arr->dimension(idx);
|
||||
ivl_assert(*this, ! dim.is_box());
|
||||
size *= 1 + labs(dim.msb() - dim.lsb());
|
||||
}
|
||||
val = size;
|
||||
if(name_ == "length") {
|
||||
int64_t size = 1;
|
||||
for (size_t idx = 0 ; idx < arr->dimensions() ; idx += 1) {
|
||||
const VTypeArray::range_t&dim = arr->dimension(idx);
|
||||
int64_t msb_val, lsb_val;
|
||||
|
||||
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 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") {
|
||||
const VType*base_type = base_->peek_type();
|
||||
if (base_type == 0)
|
||||
base_type = base_->probe_type(ent,arc);
|
||||
base_type = base_->probe_type(ent, scope);
|
||||
|
||||
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);
|
||||
if(name_ == "left")
|
||||
arr->dimension(0).msb()->evaluate(ent, arc, val);
|
||||
else
|
||||
arr->dimension(0).lsb()->evaluate(ent, arc, val);
|
||||
arr->dimension(0).msb()->evaluate(ent, scope, val);
|
||||
else // "right"
|
||||
arr->dimension(0).lsb()->evaluate(ent, scope, val);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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()) {
|
||||
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.
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
|
||||
using namespace std;
|
||||
|
||||
void ExpAggregate::write_to_stream(ostream&fd)
|
||||
void ExpAggregate::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << "(";
|
||||
for (vector<element_t*>::const_iterator cur = elements_.begin()
|
||||
|
|
@ -73,7 +73,7 @@ void ExpAggregate::choice_t::write_to_stream(ostream&fd)
|
|||
fd << "/* ERROR */";
|
||||
}
|
||||
|
||||
void ExpArithmetic::write_to_stream(ostream&out)
|
||||
void ExpArithmetic::write_to_stream(ostream&out) const
|
||||
{
|
||||
out << "(";
|
||||
write_to_stream_operand1(out);
|
||||
|
|
@ -111,23 +111,23 @@ void ExpArithmetic::write_to_stream(ostream&out)
|
|||
out << ")";
|
||||
}
|
||||
|
||||
void ExpAttribute::write_to_stream(ostream&fd)
|
||||
void ExpAttribute::write_to_stream(ostream&fd) const
|
||||
{
|
||||
base_->write_to_stream(fd);
|
||||
fd << "'" << name_;
|
||||
}
|
||||
|
||||
void ExpBitstring::write_to_stream(ostream&fd)
|
||||
void ExpBitstring::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << "\"";
|
||||
for(vector<char>::const_iterator it = value_.begin();
|
||||
it != value_.end(); ++it) {
|
||||
fd << "B\"";
|
||||
for(vector<char>::const_reverse_iterator it = value_.rbegin();
|
||||
it != value_.rend(); ++it) {
|
||||
fd << *it;
|
||||
}
|
||||
fd << "\"";
|
||||
}
|
||||
|
||||
void ExpCharacter::write_to_stream(ostream&fd)
|
||||
void ExpCharacter::write_to_stream(ostream&fd) const
|
||||
{
|
||||
char buf[4];
|
||||
buf[0] = '\'';
|
||||
|
|
@ -137,7 +137,7 @@ void ExpCharacter::write_to_stream(ostream&fd)
|
|||
fd << buf;
|
||||
}
|
||||
|
||||
void ExpConcat::write_to_stream(ostream&fd)
|
||||
void ExpConcat::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << "(";
|
||||
operand1_->write_to_stream(fd);
|
||||
|
|
@ -146,21 +146,21 @@ void ExpConcat::write_to_stream(ostream&fd)
|
|||
fd << ")";
|
||||
}
|
||||
|
||||
void ExpConditional::write_to_stream(ostream&)
|
||||
void ExpConditional::write_to_stream(ostream&) const
|
||||
{
|
||||
ivl_assert(*this, !"Not supported");
|
||||
}
|
||||
|
||||
void ExpEdge::write_to_stream(ostream&)
|
||||
void ExpEdge::write_to_stream(ostream&) const
|
||||
{
|
||||
ivl_assert(*this, !"Not supported");
|
||||
}
|
||||
|
||||
void ExpFunc::write_to_stream(ostream&fd)
|
||||
void ExpFunc::write_to_stream(ostream&fd) const
|
||||
{
|
||||
const char*comma = "";
|
||||
fd << name_ << "(";
|
||||
for (vector<Expression*>::iterator cur = argv_.begin()
|
||||
for (vector<Expression*>::const_iterator cur = argv_.begin()
|
||||
; cur != argv_.end() ; ++cur) {
|
||||
fd << comma;
|
||||
(*cur)->write_to_stream(fd);
|
||||
|
|
@ -169,22 +169,22 @@ void ExpFunc::write_to_stream(ostream&fd)
|
|||
fd << ")";
|
||||
}
|
||||
|
||||
void ExpInteger::write_to_stream(ostream&fd)
|
||||
void ExpInteger::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << value_;
|
||||
}
|
||||
|
||||
void ExpReal::write_to_stream(ostream&fd)
|
||||
void ExpReal::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << value_;
|
||||
}
|
||||
|
||||
void ExpLogical::write_to_stream(ostream&)
|
||||
void ExpLogical::write_to_stream(ostream&) const
|
||||
{
|
||||
ivl_assert(*this, !"Not supported");
|
||||
}
|
||||
|
||||
void ExpName::write_to_stream(ostream&fd)
|
||||
void ExpName::write_to_stream(ostream&fd) const
|
||||
{
|
||||
if (prefix_.get()) {
|
||||
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 << "\"";
|
||||
for(vector<char>::const_iterator it = value_.begin();
|
||||
|
|
@ -218,15 +246,21 @@ void ExpString::write_to_stream(ostream&fd)
|
|||
fd << "\"";
|
||||
}
|
||||
|
||||
void ExpUAbs::write_to_stream(ostream&fd)
|
||||
void ExpUAbs::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << "abs ";
|
||||
write_to_stream_operand1(fd);
|
||||
}
|
||||
|
||||
void ExpUNot::write_to_stream(ostream&fd)
|
||||
void ExpUNot::write_to_stream(ostream&fd) const
|
||||
{
|
||||
fd << "not ";
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -430,13 +430,10 @@ void library_set_work_path(const char*path)
|
|||
library_work_path = path;
|
||||
}
|
||||
|
||||
list<const Package*> work_packages;
|
||||
static void store_package_in_work(const Package*pack)
|
||||
{
|
||||
string path = make_work_package_path(pack->name());
|
||||
|
||||
ofstream file (path.c_str(), ios_base::out);
|
||||
|
||||
pack->write_to_stream(file);
|
||||
work_packages.push_back(pack);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -130,4 +130,11 @@ void Package::write_to_stream(ostream&fd) const
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,8 @@ int Package::emit_package(ostream&fd) const
|
|||
for (map<perm_string,const VType*>::const_iterator cur = cur_types_.begin()
|
||||
; cur != cur_types_.end() ; ++ cur) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -68,7 +69,9 @@ int Package::emit_package(ostream&fd) const
|
|||
|
||||
for (map<perm_string,Subprogram*>::const_iterator cur = cur_subprograms_.begin()
|
||||
; 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;
|
||||
|
|
|
|||
|
|
@ -573,20 +573,40 @@ case_statement_alternative_list
|
|||
* statement alternative and pass that up instead.
|
||||
*/
|
||||
case_statement_alternative
|
||||
: K_when choice ARROW sequence_of_statements
|
||||
: K_when choices ARROW sequence_of_statements
|
||||
{ CaseSeqStmt::CaseStmtAlternative* tmp;
|
||||
if ($2->others()) {
|
||||
tmp = new CaseSeqStmt::CaseStmtAlternative(0, $4);
|
||||
} else if (Expression*ex = $2->simple_expression()) {
|
||||
tmp = new CaseSeqStmt::CaseStmtAlternative(ex, $4);
|
||||
} else {
|
||||
errormsg(@2, "I don't know what to make of the case choice\n");
|
||||
tmp = 0;
|
||||
}
|
||||
if (tmp) FILE_NAME(tmp, @1);
|
||||
delete $2;
|
||||
delete $4;
|
||||
$$ = tmp;
|
||||
std::list<ExpAggregate::choice_t*>*choices = $2;
|
||||
std::list<Expression*>*exp_list = new std::list<Expression*>;
|
||||
bool others = false;
|
||||
|
||||
for(std::list<ExpAggregate::choice_t*>::iterator it = choices->begin();
|
||||
it != choices->end(); ++it) {
|
||||
if((*it)->others() || others)
|
||||
// If there is one "others", then it also covers all other alternatives
|
||||
// Continue the loop to delete every choice_t, but do not
|
||||
// bother to add the expressions to the exp_list (we are going to
|
||||
// delete them very soon)
|
||||
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 | ;
|
||||
%%
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -105,6 +105,7 @@ static const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_n
|
|||
|
||||
VTypeArray*subtype = new VTypeArray(element, range,
|
||||
base_array->signed_vector());
|
||||
subtype->set_parent_type(base_array);
|
||||
return subtype;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -72,6 +72,9 @@ class prange_t {
|
|||
public:
|
||||
prange_t(Expression* left, Expression* right, bool dir)
|
||||
: 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_; }
|
||||
void dump(ostream&out, int indent) const;
|
||||
|
||||
|
|
@ -91,7 +94,6 @@ class prange_t {
|
|||
bool auto_dir_;
|
||||
|
||||
private: //not implemented
|
||||
prange_t(const prange_t&);
|
||||
prange_t operator=(const prange_t&);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@
|
|||
# include "scope.h"
|
||||
# include "package.h"
|
||||
# include "subprogram.h"
|
||||
# include "entity.h"
|
||||
# include <algorithm>
|
||||
# include <iostream>
|
||||
# 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
|
||||
{
|
||||
map<perm_string,Subprogram*>::const_iterator cur;
|
||||
|
|
|
|||
|
|
@ -56,11 +56,19 @@ class ScopeBase {
|
|||
bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp);
|
||||
Signal* find_signal(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;
|
||||
// Moves all signals, variables and components from another scope to
|
||||
// this one. After the transfer new_* maps are emptied in the another scope.
|
||||
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:
|
||||
void cleanup();
|
||||
|
||||
|
|
|
|||
|
|
@ -19,6 +19,15 @@
|
|||
|
||||
# include "sequential.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()
|
||||
{
|
||||
|
|
@ -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)
|
||||
: 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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
: name_(name), param_list_(0)
|
||||
{
|
||||
|
|
@ -163,6 +197,12 @@ ReturnStmt::~ReturnStmt()
|
|||
delete val_;
|
||||
}
|
||||
|
||||
void ReturnStmt::cast_to(const VType*type)
|
||||
{
|
||||
assert(val_);
|
||||
val_ = new ExpCast(val_, type);
|
||||
}
|
||||
|
||||
LoopStatement::LoopStatement(perm_string name, list<SequentialStmt*>* stmts)
|
||||
: 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)
|
||||
: LoopStatement(scope_name, stmts), it_(it), range_(range)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -23,10 +23,17 @@
|
|||
# include "LineInfo.h"
|
||||
# include "parse_types.h"
|
||||
# include <list>
|
||||
# include <functional>
|
||||
|
||||
class Architecture;
|
||||
class ScopeBase;
|
||||
class Entity;
|
||||
class Expression;
|
||||
class SequentialStmt;
|
||||
|
||||
struct SeqStmtVisitor {
|
||||
virtual ~SeqStmtVisitor() {};
|
||||
virtual void operator() (SequentialStmt*s) = 0;
|
||||
};
|
||||
|
||||
class SequentialStmt : public LineInfo {
|
||||
|
||||
|
|
@ -35,9 +42,13 @@ class SequentialStmt : public LineInfo {
|
|||
virtual ~SequentialStmt() =0;
|
||||
|
||||
public:
|
||||
virtual int elaborate(Entity*ent, Architecture*arc);
|
||||
virtual int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
virtual int elaborate(Entity*ent, ScopeBase*scope);
|
||||
virtual int emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
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_; }
|
||||
|
||||
void dump(ostream&out, int indent) const;
|
||||
void visit(SeqStmtVisitor& func);
|
||||
|
||||
protected:
|
||||
int elaborate_substatements(Entity*ent, Architecture*arc);
|
||||
int emit_substatements(std::ostream&out, Entity*ent, Architecture*arc);
|
||||
int elaborate_substatements(Entity*ent, ScopeBase*scope);
|
||||
int emit_substatements(std::ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void write_to_stream_substatements(ostream&fd);
|
||||
|
||||
private:
|
||||
perm_string name_;
|
||||
|
|
@ -70,11 +83,15 @@ class IfSequential : public SequentialStmt {
|
|||
Elsif(Expression*cond, std::list<SequentialStmt*>*tr);
|
||||
~Elsif();
|
||||
|
||||
int elaborate(Entity*entity, Architecture*arc);
|
||||
int condition_emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int statement_emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*entity, ScopeBase*scope);
|
||||
int condition_emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
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 visit(SeqStmtVisitor& func);
|
||||
|
||||
private:
|
||||
Expression*cond_;
|
||||
|
|
@ -91,9 +108,11 @@ class IfSequential : public SequentialStmt {
|
|||
~IfSequential();
|
||||
|
||||
public:
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
int emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
void dump(ostream&out, int indent) const;
|
||||
void visit(SeqStmtVisitor& func);
|
||||
|
||||
const Expression*peek_condition() const { return cond_; }
|
||||
|
||||
|
|
@ -117,10 +136,12 @@ class ReturnStmt : public SequentialStmt {
|
|||
~ReturnStmt();
|
||||
|
||||
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;
|
||||
|
||||
const Expression*peek_expr() const { return val_; };
|
||||
void cast_to(const VType*type);
|
||||
|
||||
private:
|
||||
Expression*val_;
|
||||
|
|
@ -132,8 +153,9 @@ class SignalSeqAssignment : public SequentialStmt {
|
|||
~SignalSeqAssignment();
|
||||
|
||||
public:
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
int emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
void dump(ostream&out, int indent) const;
|
||||
|
||||
private:
|
||||
|
|
@ -145,15 +167,17 @@ class CaseSeqStmt : public SequentialStmt {
|
|||
public:
|
||||
class CaseStmtAlternative : public LineInfo {
|
||||
public:
|
||||
CaseStmtAlternative(Expression* exp, std::list<SequentialStmt*>* stmts);
|
||||
CaseStmtAlternative(std::list<Expression*>*exp, std::list<SequentialStmt*>*stmts);
|
||||
~CaseStmtAlternative();
|
||||
void dump(std::ostream& out, int indent) const;
|
||||
int elaborate_expr(Entity*ent, Architecture*arc, const VType*ltype);
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
int emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
void visit(SeqStmtVisitor& func);
|
||||
|
||||
private:
|
||||
Expression* exp_;
|
||||
std::list<Expression*>*exp_;
|
||||
std::list<SequentialStmt*> stmts_;
|
||||
private: // not implemented
|
||||
CaseStmtAlternative(const CaseStmtAlternative&);
|
||||
|
|
@ -166,8 +190,10 @@ class CaseSeqStmt : public SequentialStmt {
|
|||
|
||||
public:
|
||||
void dump(ostream&out, int indent) const;
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
int emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
void visit(SeqStmtVisitor& func);
|
||||
|
||||
private:
|
||||
Expression* cond_;
|
||||
|
|
@ -180,8 +206,8 @@ class ProcedureCall : public SequentialStmt {
|
|||
ProcedureCall(perm_string name, std::list<named_expr_t*>* param_list);
|
||||
~ProcedureCall();
|
||||
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
int emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent) const;
|
||||
|
||||
private:
|
||||
|
|
@ -195,8 +221,9 @@ class VariableSeqAssignment : public SequentialStmt {
|
|||
~VariableSeqAssignment();
|
||||
|
||||
public:
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
int emit(ostream&out, Entity*entity, ScopeBase*scope);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
void dump(ostream&out, int indent) const;
|
||||
|
||||
private:
|
||||
|
|
@ -210,8 +237,7 @@ class WhileLoopStatement : public LoopStatement {
|
|||
ExpLogical*, list<SequentialStmt*>*);
|
||||
~WhileLoopStatement();
|
||||
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent) const;
|
||||
|
||||
private:
|
||||
|
|
@ -224,11 +250,16 @@ class ForLoopStatement : public LoopStatement {
|
|||
perm_string index, prange_t*, list<SequentialStmt*>*);
|
||||
~ForLoopStatement();
|
||||
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void write_to_stream(std::ostream&fd);
|
||||
void dump(ostream&out, int indent) const;
|
||||
|
||||
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_;
|
||||
prange_t* range_;
|
||||
};
|
||||
|
|
@ -238,8 +269,7 @@ class BasicLoopStatement : public LoopStatement {
|
|||
BasicLoopStatement(perm_string lname, list<SequentialStmt*>*);
|
||||
~BasicLoopStatement();
|
||||
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
int emit(ostream&out, Entity*entity, Architecture*arc);
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent) const;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -105,7 +105,9 @@ void CaseSeqStmt::CaseStmtAlternative::dump(ostream& out, int indent) const
|
|||
|
||||
out << setw(indent) << "" << "when ";
|
||||
if (exp_)
|
||||
exp_->dump(out, 0);
|
||||
for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end(); ++it) {
|
||||
(*it)->dump(out, 0);
|
||||
}
|
||||
else
|
||||
out << "others" << endl;
|
||||
|
||||
|
|
|
|||
|
|
@ -20,35 +20,35 @@
|
|||
# include "sequential.h"
|
||||
# include "expression.h"
|
||||
|
||||
int SequentialStmt::elaborate(Entity*, Architecture*)
|
||||
int SequentialStmt::elaborate(Entity*, ScopeBase*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int LoopStatement::elaborate_substatements(Entity*ent, Architecture*arc)
|
||||
int LoopStatement::elaborate_substatements(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
|
||||
; cur != stmts_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate(ent, arc);
|
||||
errors += (*cur)->elaborate(ent, scope);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int CaseSeqStmt::elaborate(Entity*ent, Architecture*arc)
|
||||
int CaseSeqStmt::elaborate(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
const VType*ctype = cond_->probe_type(ent, arc);
|
||||
errors += cond_->elaborate_expr(ent, arc, ctype);
|
||||
const VType*ctype = cond_->probe_type(ent, scope);
|
||||
errors += cond_->elaborate_expr(ent, scope, ctype);
|
||||
|
||||
for (list<CaseStmtAlternative*>::iterator cur = alt_.begin()
|
||||
; cur != alt_.end() ; ++cur) {
|
||||
CaseStmtAlternative*curp = *cur;
|
||||
errors += curp->elaborate_expr(ent, arc, ctype);
|
||||
errors += curp->elaborate(ent, arc);
|
||||
errors += curp->elaborate_expr(ent, scope, ctype);
|
||||
errors += curp->elaborate(ent, scope);
|
||||
}
|
||||
|
||||
return errors;
|
||||
|
|
@ -59,79 +59,82 @@ int CaseSeqStmt::elaborate(Entity*ent, Architecture*arc)
|
|||
* ltype is the probed type for the main case condition. The
|
||||
* 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;
|
||||
if (exp_)
|
||||
errors += exp_->elaborate_expr(ent, arc, ltype);
|
||||
if (exp_) {
|
||||
for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end();
|
||||
++it) {
|
||||
errors += (*it)->elaborate_expr(ent, scope, ltype);
|
||||
}
|
||||
}
|
||||
return errors;
|
||||
}
|
||||
|
||||
int CaseSeqStmt::CaseStmtAlternative::elaborate(Entity*ent, Architecture*arc)
|
||||
int CaseSeqStmt::CaseStmtAlternative::elaborate(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
|
||||
; cur != stmts_.end() ; ++cur) {
|
||||
SequentialStmt*curp = *cur;
|
||||
errors += curp->elaborate(ent, arc);
|
||||
errors += curp->elaborate(ent, scope);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
||||
int ForLoopStatement::elaborate(Entity*ent, Architecture*arc)
|
||||
int ForLoopStatement::elaborate(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
errors += elaborate_substatements(ent, arc);
|
||||
errors += elaborate_substatements(ent, scope);
|
||||
return errors;
|
||||
}
|
||||
|
||||
int IfSequential::elaborate(Entity*ent, Architecture*arc)
|
||||
int IfSequential::elaborate(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += cond_->elaborate_expr(ent, arc, 0);
|
||||
errors += cond_->elaborate_expr(ent, scope, 0);
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = if_.begin()
|
||||
; cur != if_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate(ent, arc);
|
||||
errors += (*cur)->elaborate(ent, scope);
|
||||
}
|
||||
|
||||
for (list<IfSequential::Elsif*>::iterator cur = elsif_.begin()
|
||||
; cur != elsif_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate(ent, arc);
|
||||
errors += (*cur)->elaborate(ent, scope);
|
||||
}
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = else_.begin()
|
||||
; cur != else_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate(ent, arc);
|
||||
errors += (*cur)->elaborate(ent, scope);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int IfSequential::Elsif::elaborate(Entity*ent, Architecture*arc)
|
||||
int IfSequential::Elsif::elaborate(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
errors += cond_->elaborate_expr(ent, arc, 0);
|
||||
errors += cond_->elaborate_expr(ent, scope, 0);
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = if_.begin()
|
||||
; cur != if_.end() ; ++cur) {
|
||||
errors += (*cur)->elaborate(ent, arc);
|
||||
errors += (*cur)->elaborate(ent, scope);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int SignalSeqAssignment::elaborate(Entity*ent, Architecture*arc)
|
||||
int SignalSeqAssignment::elaborate(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
// 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
|
||||
// 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()
|
||||
; cur != waveform_.end() ; ++cur) {
|
||||
|
||||
errors += (*cur)->elaborate_expr(ent, arc, lval_type);
|
||||
errors += (*cur)->elaborate_expr(ent, scope, lval_type);
|
||||
}
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int ProcedureCall::elaborate(Entity*, Architecture*)
|
||||
int ProcedureCall::elaborate(Entity*, ScopeBase*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VariableSeqAssignment::elaborate(Entity*ent, Architecture*arc)
|
||||
int VariableSeqAssignment::elaborate(Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
// 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
|
||||
// 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.
|
||||
errors += rval_->elaborate_expr(ent, arc, lval_type);
|
||||
errors += rval_->elaborate_expr(ent, scope, lval_type);
|
||||
|
||||
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)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BasicLoopStatement::elaborate(Entity*, Architecture*)
|
||||
int BasicLoopStatement::elaborate(Entity*, ScopeBase*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/*
|
||||
* Copyright (c) 2011-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
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -27,7 +29,7 @@
|
|||
# include <typeinfo>
|
||||
# include <ivl_assert.h>
|
||||
|
||||
int SequentialStmt::emit(ostream&out, Entity*, Architecture*)
|
||||
int SequentialStmt::emit(ostream&out, Entity*, ScopeBase*)
|
||||
{
|
||||
out << " // " << get_fileline() << ": internal error: "
|
||||
<< "I don't know how to emit this sequential statement! "
|
||||
|
|
@ -35,23 +37,30 @@ int SequentialStmt::emit(ostream&out, Entity*, Architecture*)
|
|||
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;
|
||||
out << "if (";
|
||||
errors += cond_->emit(out, ent, arc);
|
||||
errors += cond_->emit(out, ent, scope);
|
||||
out << ") begin" << endl;
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = if_.begin()
|
||||
; cur != if_.end() ; ++cur)
|
||||
errors += (*cur)->emit(out, ent, arc);
|
||||
errors += (*cur)->emit(out, ent, scope);
|
||||
|
||||
for (list<IfSequential::Elsif*>::iterator cur = elsif_.begin()
|
||||
; cur != elsif_.end() ; ++cur) {
|
||||
out << "end else if (";
|
||||
errors += (*cur)->condition_emit(out, ent, arc);
|
||||
errors += (*cur)->condition_emit(out, ent, scope);
|
||||
out << ") begin" << endl;
|
||||
errors += (*cur)->statement_emit(out, ent, arc);
|
||||
errors += (*cur)->statement_emit(out, ent, scope);
|
||||
}
|
||||
|
||||
if (! else_.empty()) {
|
||||
|
|
@ -59,7 +68,7 @@ int IfSequential::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
|
||||
for (list<SequentialStmt*>::iterator cur = else_.begin()
|
||||
; 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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
for (list<SequentialStmt*>::iterator cur = if_.begin()
|
||||
; cur != if_.end() ; ++cur)
|
||||
errors += (*cur)->emit(out, ent, arc);
|
||||
errors += (*cur)->emit(out, ent, scope);
|
||||
|
||||
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;
|
||||
out << "return ";
|
||||
errors += val_->emit(out, ent, arc);
|
||||
errors += val_->emit(out, ent, scope);
|
||||
out << ";" << endl;
|
||||
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;
|
||||
|
||||
errors += lval_->emit(out, ent, arc);
|
||||
errors += lval_->emit(out, ent, scope);
|
||||
|
||||
if (waveform_.size() != 1) {
|
||||
out << "/* Confusing waveform? */;" << endl;
|
||||
|
|
@ -105,27 +162,50 @@ int SignalSeqAssignment::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
} else {
|
||||
Expression*tmp = waveform_.front();
|
||||
out << " <= ";
|
||||
errors += tmp->emit(out, ent, arc);
|
||||
errors += tmp->emit(out, ent, scope);
|
||||
out << ";" << endl;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
errors += lval_->emit(out, ent, arc);
|
||||
errors += lval_->emit(out, ent, scope);
|
||||
|
||||
out << " = ";
|
||||
errors += rval_->emit(out, ent, arc);
|
||||
errors += rval_->emit(out, ent, scope);
|
||||
out << ";" << endl;
|
||||
|
||||
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: "
|
||||
<< "I don't know how to emit this sequential statement! "
|
||||
|
|
@ -133,29 +213,38 @@ int ProcedureCall::emit(ostream&out, Entity*, Architecture*)
|
|||
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;
|
||||
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
|
||||
; cur != stmts_.end() ; ++cur) {
|
||||
SequentialStmt*tmp = *cur;
|
||||
errors += tmp->emit(out, ent, arc);
|
||||
errors += tmp->emit(out, ent, scope);
|
||||
}
|
||||
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;
|
||||
|
||||
out << "case (";
|
||||
errors += cond_->emit(out, ent, arc);
|
||||
errors += cond_->emit(out, ent, scope);
|
||||
out << ")" << endl;
|
||||
|
||||
for (list<CaseStmtAlternative*>::iterator cur = alt_.begin()
|
||||
; cur != alt_.end() ; ++cur) {
|
||||
CaseStmtAlternative*curp = *cur;
|
||||
errors += curp ->emit(out, ent, arc);
|
||||
errors += curp ->emit(out, ent, scope);
|
||||
}
|
||||
|
||||
out << "endcase" << endl;
|
||||
|
|
@ -163,16 +252,38 @@ int CaseSeqStmt::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
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;
|
||||
|
||||
bool first = true;
|
||||
if (exp_) {
|
||||
errors += exp_->emit(out, ent, arc);
|
||||
out << ":" << endl;
|
||||
for (list<Expression*>::iterator it = exp_->begin(); it != exp_->end(); ++it) {
|
||||
if(first)
|
||||
first = false;
|
||||
else
|
||||
out << ",";
|
||||
errors += (*it)->emit(out, ent, scope);
|
||||
}
|
||||
} else {
|
||||
out << "default:" << endl;
|
||||
out << "default";
|
||||
}
|
||||
out << ":" << endl;
|
||||
|
||||
SequentialStmt*curp;
|
||||
|
||||
|
|
@ -182,14 +293,14 @@ int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, Architecture
|
|||
break;
|
||||
case 1:
|
||||
curp = stmts_.front();
|
||||
errors += curp->emit(out, ent, arc);
|
||||
errors += curp->emit(out, ent, scope);
|
||||
break;
|
||||
default:
|
||||
out << "begin" << endl;
|
||||
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
|
||||
; cur != stmts_.end() ; ++cur) {
|
||||
curp = *cur;
|
||||
errors += curp->emit(out, ent, arc);
|
||||
errors += curp->emit(out, ent, scope);
|
||||
}
|
||||
out << "end" << endl;
|
||||
break;
|
||||
|
|
@ -198,92 +309,145 @@ int CaseSeqStmt::CaseStmtAlternative::emit(ostream&out, Entity*ent, Architecture
|
|||
return errors;
|
||||
}
|
||||
|
||||
int ForLoopStatement::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
void CaseSeqStmt::CaseStmtAlternative::write_to_stream(ostream&fd)
|
||||
{
|
||||
int errors = 0;
|
||||
ivl_assert(*this, range_);
|
||||
fd << "when ";
|
||||
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;
|
||||
bool start_rc = range_->msb()->evaluate(ent, arc, start_val);
|
||||
|
||||
int64_t finish_val;
|
||||
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;
|
||||
(*it)->write_to_stream(fd);
|
||||
}
|
||||
} else {
|
||||
fd << "others" << endl;
|
||||
}
|
||||
fd << "=>" << endl;
|
||||
|
||||
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;
|
||||
return errors;
|
||||
}
|
||||
for (list<SequentialStmt*>::iterator cur = stmts_.begin()
|
||||
; cur != stmts_.end() ; ++cur) {
|
||||
(*cur)->write_to_stream(fd);
|
||||
}
|
||||
|
||||
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: "
|
||||
<< "I don't know how to emit this sequential statement! "
|
||||
<< "type=" << typeid(*this).name() << endl;
|
||||
return 1;
|
||||
int errors = 0;
|
||||
ivl_assert(*this, range_);
|
||||
|
||||
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: "
|
||||
<< "I don't know how to emit this sequential statement! "
|
||||
<< "type=" << typeid(*this).name() << endl;
|
||||
return 1;
|
||||
fd << "for " << it_ << " in ";
|
||||
range_->expr_left()->write_to_stream(fd);
|
||||
fd << " to ";
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2014 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
|
||||
* and/or modify it in source code form under the terms of the GNU
|
||||
|
|
@ -23,6 +25,8 @@
|
|||
# include "vtype.h"
|
||||
# include "sequential.h"
|
||||
# include "ivl_assert.h"
|
||||
# include "compiler.h"
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
|
@ -46,7 +50,21 @@ void Subprogram::set_program_body(list<SequentialStmt*>*stmt)
|
|||
{
|
||||
ivl_assert(*this, statements_==0);
|
||||
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
|
||||
|
|
@ -105,30 +123,104 @@ const VType*Subprogram::peek_param_type(int idx) const
|
|||
return (*p)->type;
|
||||
}
|
||||
|
||||
void Subprogram::fix_return_type(void)
|
||||
{
|
||||
if(!statements_)
|
||||
return;
|
||||
Subprogram*Subprogram::make_instance(std::vector<Expression*> arguments, ScopeBase*scope) {
|
||||
assert(arguments.size() == ports_->size());
|
||||
|
||||
const ReturnStmt*ret = NULL;
|
||||
const VType*t = NULL;
|
||||
std::list<InterfacePort*>*ports = new std::list<InterfacePort*>;
|
||||
int i = 0;
|
||||
|
||||
for (std::list<SequentialStmt*>::const_iterator s = statements_->begin()
|
||||
; s != statements_->end(); ++s) {
|
||||
if((ret = dynamic_cast<const ReturnStmt*>(*s))) {
|
||||
// Change the argument types to match the ones that were used during
|
||||
// the function call
|
||||
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 VType*t = NULL;
|
||||
|
||||
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();
|
||||
} else {
|
||||
t = expr->peek_type();
|
||||
}
|
||||
|
||||
if(t)
|
||||
return_type_ = t;
|
||||
if(!t) { // cannot determine the type at least in one case
|
||||
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
|
||||
|
|
@ -149,3 +241,39 @@ void Subprogram::write_to_stream(ostream&fd) const
|
|||
return_type_->write_to_stream(fd);
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
/*
|
||||
* Copyright (c) 2013-2014 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
|
||||
* 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_; }
|
||||
|
||||
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)
|
||||
// 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 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.
|
||||
int emit_package(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;
|
||||
|
||||
// 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:
|
||||
// Determines appropriate return type. Un case of std_logic_vector
|
||||
// VHDL requires skipping its size in contrary to Verilog
|
||||
void fix_return_type(void);
|
||||
// Tries to set the return type to a fixed type. VHDL functions that
|
||||
// return std_logic_vectors do not specify its length, as SystemVerilog
|
||||
// demands.
|
||||
void fix_return_type();
|
||||
|
||||
perm_string name_;
|
||||
const ScopeBase*parent_;
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ int Subprogram::emit_package(ostream&fd) const
|
|||
if (statements_) {
|
||||
for (list<SequentialStmt*>::const_iterator cur = statements_->begin()
|
||||
; cur != statements_->end() ; ++cur) {
|
||||
errors += (*cur)->emit(fd, NULL, NULL);
|
||||
errors += (*cur)->emit(fd, NULL, const_cast<Subprogram*>(this));
|
||||
}
|
||||
} else {
|
||||
fd << " begin /* empty body */ end" << endl;
|
||||
|
|
|
|||
|
|
@ -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_) {
|
||||
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_;
|
||||
}
|
||||
|
||||
int Signal::emit(ostream&out, Entity*ent, Architecture*arc)
|
||||
int Signal::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
|
|
@ -54,18 +54,18 @@ int Signal::emit(ostream&out, Entity*ent, Architecture*arc)
|
|||
type_elaborate_(decl);
|
||||
if (peek_refcnt_sequ_() > 0 || !peek_type()->can_be_packed())
|
||||
decl.reg_flag = true;
|
||||
errors += decl.emit(out, peek_name_());
|
||||
errors += decl.emit(out, peek_name());
|
||||
|
||||
Expression*init_expr = peek_init_expr();
|
||||
if (init_expr) {
|
||||
out << " = ";
|
||||
init_expr->emit(out, ent, arc);
|
||||
init_expr->emit(out, ent, scope);
|
||||
}
|
||||
out << ";" << endl;
|
||||
return errors;
|
||||
}
|
||||
|
||||
int Variable::emit(ostream&out, Entity*, Architecture*)
|
||||
int Variable::emit(ostream&out, Entity*, ScopeBase*)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
|
|
@ -73,7 +73,14 @@ int Variable::emit(ostream&out, Entity*, Architecture*)
|
|||
type_elaborate_(decl);
|
||||
if (peek_refcnt_sequ_() > 0 || !peek_type()->can_be_packed())
|
||||
decl.reg_flag = true;
|
||||
errors += decl.emit(out, peek_name_());
|
||||
errors += decl.emit(out, peek_name());
|
||||
out << ";" << endl;
|
||||
return errors;
|
||||
}
|
||||
|
||||
void Variable::write_to_stream(std::ostream&fd)
|
||||
{
|
||||
fd << "variable " << peek_name() << " : ";
|
||||
peek_type()->write_to_stream(fd);
|
||||
fd << ";" << endl;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@
|
|||
# include "vtype.h"
|
||||
|
||||
class Architecture;
|
||||
class ScopeBase;
|
||||
class Entity;
|
||||
class Expression;
|
||||
|
||||
|
|
@ -42,10 +43,11 @@ class SigVarBase : public LineInfo {
|
|||
void dump(ostream&out, int indent = 0) const;
|
||||
|
||||
// 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:
|
||||
perm_string peek_name_() const { return name_; }
|
||||
unsigned peek_refcnt_sequ_() const { return refcnt_sequ_; }
|
||||
|
||||
void type_elaborate_(VType::decl_t&decl);
|
||||
|
|
@ -69,7 +71,7 @@ class Signal : public SigVarBase {
|
|||
public:
|
||||
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 {
|
||||
|
|
@ -77,7 +79,8 @@ class Variable : public SigVarBase {
|
|||
public:
|
||||
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()
|
||||
|
|
|
|||
|
|
@ -19,13 +19,13 @@
|
|||
|
||||
# include "vtype.h"
|
||||
# include "parse_types.h"
|
||||
# include "compiler.h"
|
||||
# include <map>
|
||||
# include <typeinfo>
|
||||
# include <cassert>
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
VType::~VType()
|
||||
{
|
||||
}
|
||||
|
|
@ -35,6 +35,13 @@ void VType::show(ostream&out) const
|
|||
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)
|
||||
: 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)
|
||||
: 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.
|
||||
*/
|
||||
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) {
|
||||
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*t = etype_;
|
||||
|
|
@ -148,6 +172,49 @@ void VTypeArray::show(ostream&out) const
|
|||
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)
|
||||
: base_(base)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -30,10 +30,12 @@
|
|||
# include "StringHeap.h"
|
||||
|
||||
class Architecture;
|
||||
class ScopeBase;
|
||||
class Entity;
|
||||
class Expression;
|
||||
class prange_t;
|
||||
class VTypeDef;
|
||||
class ScopeBase;
|
||||
|
||||
typedef enum typedef_topo_e { NONE=0, PENDING, MARKED } typedef_topo_t;
|
||||
typedef std::map<const VTypeDef*, typedef_topo_t> typedef_context_t;
|
||||
|
|
@ -49,9 +51,11 @@ class VType {
|
|||
VType() { }
|
||||
virtual ~VType() =0;
|
||||
|
||||
virtual VType*clone() const =0;
|
||||
|
||||
// This is rarely used, but some types may have expressions
|
||||
// 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 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.
|
||||
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:
|
||||
friend struct decl_t;
|
||||
// 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.
|
||||
*/
|
||||
class VTypeERROR : public VType {
|
||||
VType*clone() const { return NULL; }
|
||||
|
||||
public:
|
||||
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();
|
||||
|
||||
VType*clone() const { return new VTypePrimitive(*this); }
|
||||
|
||||
void write_to_stream(std::ostream&fd) 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) :
|
||||
msb_(m), lsb_(l), direction_(dir) { }
|
||||
|
||||
range_t*clone() const;
|
||||
|
||||
inline bool is_box() const { return msb_==0 && lsb_==0; }
|
||||
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();
|
||||
|
||||
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_type_to_stream(std::ostream&fd) const;
|
||||
void show(std::ostream&) const;
|
||||
|
|
@ -205,7 +228,7 @@ class VTypeArray : public VType {
|
|||
inline bool signed_vector() const { return signed_flag_; }
|
||||
|
||||
// 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
|
||||
// (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_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(); }
|
||||
|
||||
private:
|
||||
void write_range_to_stream_(std::ostream&fd) const;
|
||||
const VType*etype_;
|
||||
bool is_unbounded() const;
|
||||
|
||||
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_;
|
||||
bool signed_flag_;
|
||||
const VTypeArray*parent_;
|
||||
};
|
||||
|
||||
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();
|
||||
|
||||
VType*clone() const { return new VTypeRange(base_->clone(), max_, min_); }
|
||||
|
||||
// Get the type that is limited by the range.
|
||||
inline const VType* base_type() const { return base_; }
|
||||
|
||||
|
|
@ -251,6 +289,8 @@ class VTypeEnum : public VType {
|
|||
VTypeEnum(const std::list<perm_string>*names);
|
||||
~VTypeEnum();
|
||||
|
||||
VType*clone() const { return new VTypeEnum(*this); }
|
||||
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
void show(std::ostream&) 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);
|
||||
~VTypeRecord();
|
||||
|
||||
VType*clone() const { return new VTypeRecord(*this); }
|
||||
|
||||
void write_to_stream(std::ostream&fd) const;
|
||||
void show(std::ostream&) 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);
|
||||
~VTypeDef();
|
||||
|
||||
VType*clone() const { return new VTypeDef(*this); }
|
||||
|
||||
inline perm_string peek_name() const { return name_; }
|
||||
|
||||
// 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;
|
||||
|
||||
bool can_be_packed() const { return type_->can_be_packed(); }
|
||||
|
||||
bool is_unbounded() const { return type_->is_unbounded(); }
|
||||
private:
|
||||
int emit_decl(std::ostream&out, perm_string name, bool reg_flag) const;
|
||||
|
||||
|
|
|
|||
|
|
@ -21,24 +21,24 @@
|
|||
# include "vtype.h"
|
||||
# include "expression.h"
|
||||
|
||||
int VType::elaborate(Entity*, Architecture*) const
|
||||
int VType::elaborate(Entity*, ScopeBase*) const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VTypeArray::elaborate(Entity*ent, Architecture*arc) const
|
||||
int VTypeArray::elaborate(Entity*ent, ScopeBase*scope) const
|
||||
{
|
||||
int errors = 0;
|
||||
etype_->elaborate(ent, arc);
|
||||
etype_->elaborate(ent, scope);
|
||||
|
||||
for (vector<range_t>::const_iterator cur = ranges_.begin()
|
||||
; cur != ranges_.end() ; ++ cur) {
|
||||
|
||||
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();
|
||||
if (tmp) errors += tmp->elaborate_expr(ent, arc, 0);
|
||||
if (tmp) errors += tmp->elaborate_expr(ent, scope, 0);
|
||||
}
|
||||
|
||||
return errors;
|
||||
|
|
|
|||
|
|
@ -59,9 +59,7 @@ int VTypeERROR::emit_def(ostream&out, perm_string) const
|
|||
int VTypeArray::emit_def(ostream&out, perm_string name) const
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
const VType*raw_base = basic_type();
|
||||
|
||||
const VTypePrimitive*base = dynamic_cast<const VTypePrimitive*> (raw_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);
|
||||
}
|
||||
|
||||
if(raw_base->can_be_packed()) {
|
||||
errors += emit_dimensions(out);
|
||||
emit_name(out, name);
|
||||
} else {
|
||||
emit_name(out, name);
|
||||
errors += emit_dimensions(out);
|
||||
}
|
||||
errors += emit_with_dims_(out, raw_base->can_be_packed(), name);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
|
@ -90,7 +82,7 @@ int VTypeArray::emit_typedef(std::ostream&out, typedef_context_t&ctx) const
|
|||
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;
|
||||
|
||||
|
|
@ -102,18 +94,35 @@ int VTypeArray::emit_dimensions(std::ostream&out) const
|
|||
}
|
||||
dims.push_back(cur);
|
||||
|
||||
bool name_emitted = false;
|
||||
|
||||
while (! dims.empty()) {
|
||||
cur = dims.front();
|
||||
dims.pop_front();
|
||||
|
||||
out << "[";
|
||||
if (cur->dimension(0).msb() && cur->dimension(0).lsb()) {
|
||||
// bounded array, unbounded arrays have msb() & lsb() nullified
|
||||
errors += cur->dimension(0).msb()->emit(out, 0, 0);
|
||||
out << ":";
|
||||
errors += cur->dimension(0).lsb()->emit(out, 0, 0);
|
||||
if(!packed) {
|
||||
emit_name(out, name);
|
||||
name_emitted = true;
|
||||
}
|
||||
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;
|
||||
|
|
@ -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
|
||||
* 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;
|
||||
emit_name(out, name_);
|
||||
emit_name(out, name);
|
||||
return errors;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -143,6 +143,7 @@ static PLI_INT32 to_from_vec_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name)
|
|||
case vpiReg:
|
||||
case vpiBitVar:
|
||||
case vpiIntegerVar:
|
||||
case vpiConstant:
|
||||
break;
|
||||
default:
|
||||
vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh),
|
||||
|
|
|
|||
Loading…
Reference in New Issue