Merge pull request #52 from orsonmmz/unbounded_function

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

View File

@ -999,6 +999,9 @@ class PECastType : public PExpr {
void dump(ostream &out) const;
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;

View File

@ -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
{

View File

@ -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;
}
/*

View File

@ -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:

View File

@ -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);

View File

@ -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;

View File

@ -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()

View File

@ -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_;
}

View File

@ -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 */

View File

@ -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);
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -49,7 +49,8 @@ int Package::emit_package(ostream&fd) const
for (map<perm_string,const VType*>::const_iterator cur = cur_types_.begin()
; 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;

View File

@ -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;
}

View File

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

View File

@ -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&);
};

View File

@ -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;

View File

@ -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();

View File

@ -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)
{

View File

@ -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;
};

View File

@ -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;

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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_;

View File

@ -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;

View File

@ -34,10 +34,10 @@ SigVarBase::~SigVarBase()
{
}
void SigVarBase::elaborate_init_expr(Entity*ent, Architecture*arc)
void SigVarBase::elaborate_init_expr(Entity*ent, ScopeBase*scope)
{
if(init_expr_) {
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;
}

View File

@ -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()

View File

@ -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)
{

View File

@ -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;

View File

@ -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;

View File

@ -59,9 +59,7 @@ int VTypeERROR::emit_def(ostream&out, perm_string) const
int VTypeArray::emit_def(ostream&out, perm_string name) const
{
int 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;
}

View File

@ -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),