vhdlpp: Refactored prange_t (class ExpRange).
This commit is contained in:
parent
2c010d34bb
commit
e0b2a5b337
|
|
@ -137,7 +137,7 @@ GenerateStatement::~GenerateStatement()
|
|||
}
|
||||
|
||||
ForGenerate::ForGenerate(perm_string gname, perm_string genvar,
|
||||
prange_t*rang, std::list<Architecture::Statement*>&s)
|
||||
ExpRange*rang, std::list<Architecture::Statement*>&s)
|
||||
: GenerateStatement(gname, s), genvar_(genvar),
|
||||
lsb_(rang->lsb()), msb_(rang->msb())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class GenerateStatement;
|
|||
class SequentialStmt;
|
||||
class Signal;
|
||||
class named_expr_t;
|
||||
class prange_t;
|
||||
class ExpRange;
|
||||
|
||||
/*
|
||||
* The Architecture class carries the contents (name, statements,
|
||||
|
|
@ -142,7 +142,7 @@ class ForGenerate : public GenerateStatement {
|
|||
|
||||
public:
|
||||
ForGenerate(perm_string gname, perm_string genvar,
|
||||
prange_t*rang, std::list<Architecture::Statement*>&s);
|
||||
ExpRange*rang, std::list<Architecture::Statement*>&s);
|
||||
~ForGenerate();
|
||||
|
||||
int elaborate(Entity*ent, Architecture*arc);
|
||||
|
|
|
|||
|
|
@ -442,13 +442,6 @@ void named_expr_t::dump(ostream&out, int indent) const
|
|||
expr_->dump(out, indent);
|
||||
}
|
||||
|
||||
void prange_t::dump(ostream&out, int indent) const
|
||||
{
|
||||
left_->dump(out, indent);
|
||||
out << setw(indent) << "" << (direction_ ? "downto" : "to");
|
||||
right_->dump(out, indent);
|
||||
}
|
||||
|
||||
ostream& Expression::dump_inline(ostream&out) const
|
||||
{
|
||||
out << typeid(*this).name();
|
||||
|
|
|
|||
|
|
@ -77,6 +77,9 @@ void ExpAttribute::visit(ExprVisitor& func)
|
|||
func(this);
|
||||
}
|
||||
|
||||
const perm_string ExpAttribute::LEFT = perm_string::literal("left");
|
||||
const perm_string ExpAttribute::RIGHT = perm_string::literal("right");
|
||||
|
||||
ExpBinary::ExpBinary(Expression*op1, Expression*op2)
|
||||
: operand1_(op1), operand2_(op2)
|
||||
{
|
||||
|
|
@ -192,7 +195,7 @@ ExpAggregate::choice_t::choice_t()
|
|||
{
|
||||
}
|
||||
|
||||
ExpAggregate::choice_t::choice_t(prange_t*rang)
|
||||
ExpAggregate::choice_t::choice_t(ExpRange*rang)
|
||||
: range_(rang)
|
||||
{
|
||||
}
|
||||
|
|
@ -203,7 +206,7 @@ ExpAggregate::choice_t::choice_t(const choice_t&other)
|
|||
expr_.reset(e->clone());
|
||||
|
||||
if(other.range_.get())
|
||||
range_.reset(new prange_t(*other.range_.get()));
|
||||
range_.reset(static_cast<ExpRange*>(other.range_.get()->clone()));
|
||||
}
|
||||
|
||||
ExpAggregate::choice_t::~choice_t()
|
||||
|
|
@ -221,7 +224,7 @@ Expression*ExpAggregate::choice_t::simple_expression(bool detach_flag)
|
|||
return res;
|
||||
}
|
||||
|
||||
prange_t*ExpAggregate::choice_t::range_expressions(void)
|
||||
ExpRange*ExpAggregate::choice_t::range_expressions(void)
|
||||
{
|
||||
return range_.get();
|
||||
}
|
||||
|
|
@ -535,6 +538,7 @@ ExpName::ExpName(perm_string nn, list<Expression*>*indices)
|
|||
ExpName::ExpName(perm_string nn, Expression*msb, Expression*lsb)
|
||||
: name_(nn), index_(msb), lsb_(lsb)
|
||||
{
|
||||
ivl_assert(*this, !msb || msb != lsb);
|
||||
}
|
||||
|
||||
ExpName::ExpName(ExpName*prefix, perm_string nn)
|
||||
|
|
@ -545,6 +549,7 @@ ExpName::ExpName(ExpName*prefix, perm_string nn)
|
|||
ExpName::ExpName(ExpName*prefix, perm_string nn, Expression*msb, Expression*lsb)
|
||||
: prefix_(prefix), name_(nn), index_(msb), lsb_(lsb)
|
||||
{
|
||||
ivl_assert(*this, !msb || msb != lsb);
|
||||
}
|
||||
|
||||
ExpName::~ExpName()
|
||||
|
|
@ -712,3 +717,70 @@ double ExpTime::to_fs() const
|
|||
|
||||
return val;
|
||||
}
|
||||
|
||||
ExpRange::ExpRange(Expression*left, Expression*right, range_dir_t direction)
|
||||
: left_(left), right_(right), direction_(direction), range_expr_(false)
|
||||
{
|
||||
}
|
||||
|
||||
ExpRange::ExpRange(ExpName*base, bool reverse_range)
|
||||
: direction_(AUTO), range_expr_(true), range_base_(base), range_reverse_(reverse_range)
|
||||
{
|
||||
}
|
||||
|
||||
ExpRange::~ExpRange()
|
||||
{
|
||||
delete left_;
|
||||
delete right_;
|
||||
delete range_base_;
|
||||
}
|
||||
|
||||
Expression*ExpRange::clone() const
|
||||
{
|
||||
if(range_expr_)
|
||||
return new ExpRange(static_cast<ExpName*>(range_base_->clone()), range_reverse_);
|
||||
else
|
||||
return new ExpRange(left_->clone(), right_->clone(), direction_);
|
||||
}
|
||||
|
||||
Expression* ExpRange::msb()
|
||||
{
|
||||
ivl_assert(*this, direction() != AUTO);
|
||||
|
||||
switch(direction()) {
|
||||
case DOWNTO: return left_;
|
||||
case TO: return right_;
|
||||
default: return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Expression* ExpRange::lsb()
|
||||
{
|
||||
ivl_assert(*this, direction() != AUTO);
|
||||
|
||||
switch(direction()) {
|
||||
case DOWNTO: return right_;
|
||||
case TO: return left_;
|
||||
default: return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Expression*ExpRange::left()
|
||||
{
|
||||
if(range_expr_ && !left_)
|
||||
left_ = new ExpAttribute(range_base_, ExpAttribute::LEFT);
|
||||
|
||||
return left_;
|
||||
}
|
||||
|
||||
Expression*ExpRange::right()
|
||||
{
|
||||
if(range_expr_ && !right_)
|
||||
right_ = new ExpAttribute(range_base_, ExpAttribute::RIGHT);
|
||||
|
||||
return right_;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,8 +29,7 @@
|
|||
# include <memory>
|
||||
# include <vector>
|
||||
|
||||
class prange_t;
|
||||
class Entity;
|
||||
class ExpRange;
|
||||
class ScopeBase;
|
||||
class SubprogramHeader;
|
||||
class VType;
|
||||
|
|
@ -239,7 +238,7 @@ class ExpAggregate : public Expression {
|
|||
// Create a named choice
|
||||
explicit choice_t(perm_string name);
|
||||
// discreate_range choice
|
||||
explicit choice_t(prange_t*ran);
|
||||
explicit choice_t(ExpRange*ran);
|
||||
|
||||
choice_t(const choice_t&other);
|
||||
|
||||
|
|
@ -249,15 +248,15 @@ class ExpAggregate : public Expression {
|
|||
bool others() const;
|
||||
// Return expression if this represents a simple_expression.
|
||||
Expression*simple_expression(bool detach_flag =true);
|
||||
// Return prange_t if this represents a range_expression
|
||||
prange_t*range_expressions(void);
|
||||
// Return ExpRange if this represents a range_expression
|
||||
ExpRange*range_expressions(void);
|
||||
|
||||
void write_to_stream(std::ostream&fd);
|
||||
void dump(ostream&out, int indent) const;
|
||||
|
||||
private:
|
||||
std::auto_ptr<Expression>expr_;
|
||||
std::auto_ptr<prange_t> range_;
|
||||
std::auto_ptr<ExpRange> range_;
|
||||
private: // not implemented
|
||||
choice_t& operator= (const choice_t&);
|
||||
};
|
||||
|
|
@ -373,6 +372,10 @@ class ExpAttribute : public Expression {
|
|||
void dump(ostream&out, int indent = 0) const;
|
||||
void visit(ExprVisitor& func);
|
||||
|
||||
// Constants for the standard attributes
|
||||
static const perm_string LEFT;
|
||||
static const perm_string RIGHT;
|
||||
|
||||
private:
|
||||
ExpName*base_;
|
||||
perm_string name_;
|
||||
|
|
@ -898,6 +901,46 @@ class ExpTime : public Expression {
|
|||
timeunit_t unit_;
|
||||
};
|
||||
|
||||
class ExpRange : public Expression {
|
||||
public:
|
||||
typedef enum { DOWNTO, TO, AUTO } range_dir_t;
|
||||
|
||||
// Regular range
|
||||
ExpRange(Expression*left, Expression*right, range_dir_t direction);
|
||||
// 'range/'reverse range attribute
|
||||
ExpRange(ExpName*base, bool reverse_range);
|
||||
~ExpRange();
|
||||
|
||||
Expression*clone() const;
|
||||
|
||||
// Returns the upper boundary
|
||||
Expression*msb();
|
||||
// Returns the lower boundary
|
||||
Expression*lsb();
|
||||
|
||||
Expression*left();
|
||||
Expression*right();
|
||||
|
||||
range_dir_t direction() const { return direction_; }
|
||||
|
||||
int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype);
|
||||
void write_to_stream(std::ostream&) const;
|
||||
int emit(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
void dump(ostream&out, int indent = 0) const;
|
||||
private:
|
||||
// Regular range related fields
|
||||
Expression*left_, *right_;
|
||||
range_dir_t direction_;
|
||||
|
||||
// 'range/'reverse_range attribute related fields
|
||||
// Flag to indicate it is a 'range/'reverse_range expression
|
||||
bool range_expr_;
|
||||
// Object name to which the attribute is applied
|
||||
ExpName*range_base_;
|
||||
// Flag to distinguish between 'range & 'reverse_range
|
||||
bool range_reverse_;
|
||||
};
|
||||
|
||||
// Elaborates an expression used as an argument in a procedure/function call.
|
||||
int elaborate_argument(Expression*expr, const SubprogramHeader*subp,
|
||||
int idx, Entity*ent, ScopeBase*scope);
|
||||
|
|
|
|||
|
|
@ -117,3 +117,9 @@ void ExpTime::dump(ostream&out, int indent) const
|
|||
out << setw(indent) << "" << "Time ";
|
||||
write_to_stream(out);
|
||||
}
|
||||
|
||||
void ExpRange::dump(ostream&out, int indent) const
|
||||
{
|
||||
out << setw(indent) << "" << "Range ";
|
||||
write_to_stream(out);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -402,7 +402,7 @@ const VType*ExpAggregate::fit_type(Entity*, ScopeBase*, const VTypeArray*host) c
|
|||
elements_[0]->map_choices(&ce[0]);
|
||||
|
||||
ivl_assert(*this, ce.size() == 1);
|
||||
prange_t*prange = ce[0].choice->range_expressions();
|
||||
ExpRange*prange = ce[0].choice->range_expressions();
|
||||
ivl_assert(*this, prange);
|
||||
|
||||
Expression*use_msb = prange->msb();
|
||||
|
|
@ -657,8 +657,8 @@ const VType*ExpConcat::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*at
|
|||
new ExpArithmetic(ExpArithmetic::PLUS, sizes[0], sizes[1]),
|
||||
new ExpInteger(1));
|
||||
|
||||
std::list<prange_t*> ranges;
|
||||
ranges.push_front(new prange_t(size, new ExpInteger(0), true));
|
||||
std::list<ExpRange*> ranges;
|
||||
ranges.push_front(new ExpRange(size, new ExpInteger(0), ExpRange::DOWNTO));
|
||||
const VType*array = new VTypeArray(types[1], &ranges);
|
||||
|
||||
return array;
|
||||
|
|
@ -1057,6 +1057,19 @@ int ExpTime::elaborate_expr(Entity*, ScopeBase*, const VType*)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int ExpRange::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if(left_)
|
||||
errors += left_->elaborate_expr(ent, scope, &primitive_INTEGER);
|
||||
|
||||
if(right_)
|
||||
errors += right_->elaborate_expr(ent, scope, &primitive_INTEGER);
|
||||
|
||||
return errors;
|
||||
}
|
||||
|
||||
int elaborate_argument(Expression*expr, const SubprogramHeader*subp,
|
||||
int idx, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -224,7 +224,7 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, ScopeBase*scope, const VT
|
|||
// If this is a range choice, then calculate the bounds
|
||||
// of the range and scan through the values, mapping the
|
||||
// value to the aggregate_[idx] element.
|
||||
if (prange_t*range = aggregate_[idx].choice->range_expressions()) {
|
||||
if (ExpRange*range = aggregate_[idx].choice->range_expressions()) {
|
||||
int64_t begin_val, end_val;
|
||||
|
||||
if (! range->msb()->evaluate(ent, scope, begin_val)) {
|
||||
|
|
@ -1031,3 +1031,25 @@ int ExpTime::emit(ostream&out, Entity*, ScopeBase*)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ExpRange::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
||||
{
|
||||
int errors = 0;
|
||||
|
||||
if(range_expr_) {
|
||||
out << "$left(";
|
||||
errors += range_base_->emit(out, ent, scope);
|
||||
out << "):$right(";
|
||||
errors += range_base_->emit(out, ent, scope);
|
||||
out << ")";
|
||||
} else if(direction_ == AUTO) {
|
||||
ivl_assert(*this, false);
|
||||
out << "/* auto dir */";
|
||||
} else {
|
||||
errors += left_->emit(out, ent, scope);
|
||||
out << ":";
|
||||
errors += right_->emit(out, ent, scope);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -61,13 +61,9 @@ void ExpAggregate::choice_t::write_to_stream(ostream&fd)
|
|||
return;
|
||||
}
|
||||
|
||||
if (prange_t*rp = range_expressions()) {
|
||||
rp->msb()->write_to_stream(fd);
|
||||
if (rp->is_downto())
|
||||
fd << " downto ";
|
||||
else
|
||||
fd << " to ";
|
||||
rp->msb()->write_to_stream(fd);
|
||||
if (ExpRange*rp = range_expressions()) {
|
||||
rp->write_to_stream(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
fd << "/* ERROR */";
|
||||
|
|
@ -316,3 +312,19 @@ void ExpTime::write_to_stream(ostream&fd) const
|
|||
case S: fd << " s"; break;
|
||||
}
|
||||
}
|
||||
|
||||
void ExpRange::write_to_stream(ostream&fd) const
|
||||
{
|
||||
if(range_expr_) {
|
||||
range_base_->write_to_stream(fd);
|
||||
fd << (range_reverse_ ? "'reverse_range" : "'range");
|
||||
} else {
|
||||
left_->write_to_stream(fd);
|
||||
switch(direction_) {
|
||||
case DOWNTO: fd << " downto "; break;
|
||||
case TO: fd << " to "; break;
|
||||
default: ivl_assert(*this, false); break;
|
||||
}
|
||||
right_->write_to_stream(fd);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -87,10 +87,6 @@ static ActiveScope*active_scope = new ActiveScope;
|
|||
static stack<ActiveScope*> scope_stack;
|
||||
static SubprogramHeader*active_sub = NULL;
|
||||
|
||||
// perm_strings for attributes
|
||||
const static perm_string left_attr = perm_string::literal("left");
|
||||
const static perm_string right_attr = perm_string::literal("right");
|
||||
|
||||
/*
|
||||
* When a scope boundary starts, call the push_scope function to push
|
||||
* a scope context. Preload this scope context with the contents of
|
||||
|
|
@ -245,8 +241,9 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
|||
|
||||
const VType* vtype;
|
||||
|
||||
prange_t* range;
|
||||
std::list<prange_t*>*range_list;
|
||||
ExpRange*range;
|
||||
std::list<ExpRange*>*range_list;
|
||||
ExpRange::range_dir_t range_dir;
|
||||
|
||||
ExpArithmetic::fun_t arithmetic_op;
|
||||
std::list<struct adding_term>*adding_terms;
|
||||
|
|
@ -305,8 +302,6 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
|||
|
||||
/* The rules may have types. */
|
||||
|
||||
%type <flag> direction
|
||||
|
||||
%type <arithmetic_op> adding_operator
|
||||
%type <adding_terms> simple_expression_terms
|
||||
|
||||
|
|
@ -372,6 +367,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
|
|||
|
||||
%type <range> range
|
||||
%type <range_list> range_list index_constraint
|
||||
%type <range_dir> direction
|
||||
|
||||
%type <case_alt> case_statement_alternative
|
||||
%type <case_alt_list> case_statement_alternative_list
|
||||
|
|
@ -752,8 +748,9 @@ composite_type_definition
|
|||
|
||||
/* unbounded_array_definition IEEE 1076-2008 P5.3.2.1 */
|
||||
| K_array '(' index_subtype_definition_list ')' K_of subtype_indication
|
||||
{ std::list<prange_t*> r;
|
||||
r.push_back(new prange_t(NULL, NULL, true)); // NULL boundaries indicate unbounded array type
|
||||
{ std::list<ExpRange*> r;
|
||||
// NULL boundaries indicate unbounded array type
|
||||
r.push_back(new ExpRange(NULL, NULL, ExpRange::DOWNTO));
|
||||
VTypeArray*tmp = new VTypeArray($6, &r);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
@ -983,8 +980,10 @@ design_units
|
|||
| design_unit
|
||||
;
|
||||
|
||||
/* Indicate the direction as a flag, with "downto" being TRUE. */
|
||||
direction : K_to { $$ = false; } | K_downto { $$ = true; } ;
|
||||
direction
|
||||
: K_to { $$ = ExpRange::TO; }
|
||||
| K_downto { $$ = ExpRange::DOWNTO; }
|
||||
;
|
||||
|
||||
element_association
|
||||
: choices ARROW expression
|
||||
|
|
@ -1498,7 +1497,7 @@ index_constraint
|
|||
| '(' error ')'
|
||||
{ errormsg(@2, "Errors in the index constraint.\n");
|
||||
yyerrok;
|
||||
$$ = new list<prange_t*>;
|
||||
$$ = new list<ExpRange*>;
|
||||
}
|
||||
;
|
||||
|
||||
|
|
@ -2096,18 +2095,15 @@ process_sensitivity_list
|
|||
|
||||
range
|
||||
: simple_expression direction simple_expression
|
||||
{ prange_t* tmp = new prange_t($1, $3, $2);
|
||||
{ ExpRange* tmp = new ExpRange($1, $3, $2);
|
||||
$$ = tmp;
|
||||
}
|
||||
| name '\'' K_range
|
||||
{
|
||||
prange_t*tmp = NULL;
|
||||
ExpRange*tmp = NULL;
|
||||
ExpName*name = NULL;
|
||||
if((name = dynamic_cast<ExpName*>($1))) {
|
||||
ExpAttribute*left = new ExpAttribute(name, left_attr);
|
||||
ExpAttribute*right = new ExpAttribute(name, right_attr);
|
||||
tmp = new prange_t(left, right, true);
|
||||
tmp->set_auto_dir();
|
||||
tmp = new ExpRange(name, false);
|
||||
} else {
|
||||
errormsg(@1, "'range attribute can be used with named expressions only");
|
||||
}
|
||||
|
|
@ -2115,13 +2111,10 @@ range
|
|||
}
|
||||
| name '\'' K_reverse_range
|
||||
{
|
||||
prange_t*tmp = NULL;
|
||||
ExpRange*tmp = NULL;
|
||||
ExpName*name = NULL;
|
||||
if((name = dynamic_cast<ExpName*>($1))) {
|
||||
ExpAttribute*left = new ExpAttribute(name, left_attr);
|
||||
ExpAttribute*right = new ExpAttribute(name, right_attr);
|
||||
tmp = new prange_t(left, right, false);
|
||||
tmp->set_auto_dir();
|
||||
tmp = new ExpRange(name, true);
|
||||
} else {
|
||||
errormsg(@1, "'reverse_range attribute can be used with named expressions only");
|
||||
}
|
||||
|
|
@ -2131,12 +2124,12 @@ range
|
|||
|
||||
range_list
|
||||
: range
|
||||
{ list<prange_t*>*tmp = new list<prange_t*>;
|
||||
{ list<ExpRange*>*tmp = new list<ExpRange*>;
|
||||
tmp->push_back($1);
|
||||
$$ = tmp;
|
||||
}
|
||||
| range_list ',' range
|
||||
{ list<prange_t*>*tmp = $1;
|
||||
{ list<ExpRange*>*tmp = $1;
|
||||
tmp->push_back($3);
|
||||
$$ = tmp;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -113,14 +113,14 @@ static const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_n
|
|||
}
|
||||
|
||||
const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_name,
|
||||
ScopeBase*scope, list<prange_t*>*ranges)
|
||||
ScopeBase*scope, list<ExpRange*>*ranges)
|
||||
{
|
||||
if (ranges->size() == 1) {
|
||||
prange_t*tmpr = ranges->front();
|
||||
Expression*lef = tmpr->expr_left();
|
||||
Expression*rig = tmpr->expr_right();
|
||||
ExpRange*tmpr = ranges->front();
|
||||
Expression*lef = tmpr->left();
|
||||
Expression*rig = tmpr->right();
|
||||
return calculate_subtype_array(loc, base_name, scope,
|
||||
lef, tmpr->is_downto(), rig);
|
||||
lef, tmpr->direction(), rig);
|
||||
}
|
||||
|
||||
sorrymsg(loc, "Don't know how to handle multiple ranges here.\n");
|
||||
|
|
@ -130,7 +130,7 @@ const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_name,
|
|||
const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_name,
|
||||
ScopeBase*scope,
|
||||
Expression*range_left,
|
||||
bool downto,
|
||||
int direction,
|
||||
Expression*range_right)
|
||||
{
|
||||
const VType*base_type = parse_type_by_name(lex_strings.make(base_name));
|
||||
|
|
@ -148,7 +148,7 @@ const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_name,
|
|||
if(range_left->evaluate(scope, left_val) && range_right->evaluate(scope, right_val)) {
|
||||
subtype = new VTypeRangeConst(base_type, left_val, right_val);
|
||||
} else {
|
||||
subtype = new VTypeRangeExpr(base_type, range_left, range_right, downto);
|
||||
subtype = new VTypeRangeExpr(base_type, range_left, range_right, direction);
|
||||
}
|
||||
|
||||
return subtype;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ class ActiveScope;
|
|||
class Architecture;
|
||||
class Expression;
|
||||
class Package;
|
||||
class prange_t;
|
||||
class ExpRange;
|
||||
class ScopeBase;
|
||||
class VType;
|
||||
|
||||
|
|
@ -35,11 +35,11 @@ extern void bind_architecture_to_entity(const char*ename, Architecture*arch);
|
|||
|
||||
extern const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_name,
|
||||
ScopeBase*scope,
|
||||
std::list<prange_t*>*ranges);
|
||||
std::list<ExpRange*>*ranges);
|
||||
extern const VType* calculate_subtype_range(const YYLTYPE&loc, const char*base_name,
|
||||
ScopeBase*scope,
|
||||
Expression*range_left,
|
||||
bool downto,
|
||||
int direction,
|
||||
Expression*range_right);
|
||||
|
||||
/*
|
||||
|
|
|
|||
|
|
@ -68,35 +68,6 @@ class instant_list_t {
|
|||
std::list<perm_string>* labels_;
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
inline Expression*msb() { return direction_? left_ : right_; }
|
||||
inline Expression*lsb() { return direction_? right_: left_; }
|
||||
|
||||
inline bool is_downto() const { return direction_; }
|
||||
inline void set_auto_dir(bool enabled = true) { auto_dir_ = enabled; };
|
||||
inline bool is_auto_dir() const { return auto_dir_; }
|
||||
|
||||
inline Expression*expr_left() { return left_; }
|
||||
inline Expression*expr_right() { return right_; }
|
||||
|
||||
private:
|
||||
Expression *left_, *right_;
|
||||
bool direction_;
|
||||
bool auto_dir_;
|
||||
|
||||
private: //not implemented
|
||||
prange_t operator=(const prange_t&);
|
||||
};
|
||||
|
||||
struct adding_term {
|
||||
ExpArithmetic::fun_t op;
|
||||
Expression*term;
|
||||
|
|
|
|||
|
|
@ -238,7 +238,7 @@ void LoopStatement::visit(SeqStmtVisitor& func)
|
|||
func(this);
|
||||
}
|
||||
|
||||
ForLoopStatement::ForLoopStatement(perm_string scope_name, perm_string it, prange_t* range, list<SequentialStmt*>* stmts)
|
||||
ForLoopStatement::ForLoopStatement(perm_string scope_name, perm_string it, ExpRange* range, list<SequentialStmt*>* stmts)
|
||||
: LoopStatement(scope_name, stmts), it_(it), range_(range)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -250,7 +250,7 @@ class WhileLoopStatement : public LoopStatement {
|
|||
class ForLoopStatement : public LoopStatement {
|
||||
public:
|
||||
ForLoopStatement(perm_string loop_name,
|
||||
perm_string index, prange_t*, list<SequentialStmt*>*);
|
||||
perm_string index, ExpRange*, list<SequentialStmt*>*);
|
||||
~ForLoopStatement();
|
||||
|
||||
int elaborate(Entity*ent, ScopeBase*scope);
|
||||
|
|
@ -264,7 +264,7 @@ class ForLoopStatement : public LoopStatement {
|
|||
int emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope);
|
||||
|
||||
perm_string it_;
|
||||
prange_t* range_;
|
||||
ExpRange* range_;
|
||||
};
|
||||
|
||||
class BasicLoopStatement : public LoopStatement {
|
||||
|
|
|
|||
|
|
@ -383,10 +383,10 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
|||
ivl_assert(*this, range_);
|
||||
|
||||
int64_t start_val;
|
||||
bool start_rc = range_->msb()->evaluate(ent, scope, start_val);
|
||||
bool start_rc = range_->left()->evaluate(ent, scope, start_val);
|
||||
|
||||
int64_t finish_val;
|
||||
bool finish_rc = range_->lsb()->evaluate(ent, scope, finish_val);
|
||||
bool finish_rc = range_->right()->evaluate(ent, scope, finish_val);
|
||||
|
||||
perm_string scope_name = loop_name();
|
||||
if (scope_name.nil()) {
|
||||
|
|
@ -403,48 +403,31 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
|||
// determined during the run-time
|
||||
errors += emit_runtime_(out, ent, scope);
|
||||
} else {
|
||||
bool dir = range_->is_downto();
|
||||
ExpRange::range_dir_t dir = range_->direction();
|
||||
|
||||
if (!dir) {
|
||||
int64_t tmp = start_val;
|
||||
start_val = finish_val;
|
||||
finish_val = tmp;
|
||||
}
|
||||
if(dir == ExpRange::AUTO)
|
||||
dir = start_val < finish_val ? ExpRange::TO : ExpRange::DOWNTO;
|
||||
|
||||
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;
|
||||
}
|
||||
if ((dir == ExpRange::DOWNTO && start_val < finish_val) ||
|
||||
(dir == ExpRange::TO && start_val > finish_val)) {
|
||||
out << "begin /* Degenerate loop at " << get_fileline()
|
||||
<< ": " << start_val;
|
||||
out << (dir == ExpRange::DOWNTO ? " downto " : " to ");
|
||||
out << finish_val << " */ end" << endl
|
||||
<< "end" << endl;
|
||||
return errors;
|
||||
}
|
||||
|
||||
out << "for (\\" << it_ << " = " << start_val << " ; ";
|
||||
|
||||
if (dir)
|
||||
if (dir == ExpRange::DOWNTO)
|
||||
out << "\\" << it_ << " >= " << finish_val;
|
||||
else
|
||||
out << "\\" << it_ << " <= " << finish_val;
|
||||
|
||||
out << "; \\" << it_ << " = \\" << it_;
|
||||
|
||||
if (dir)
|
||||
if (dir == ExpRange::DOWNTO)
|
||||
out << " - 1)";
|
||||
else
|
||||
out << " + 1)";
|
||||
|
|
@ -463,9 +446,7 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, ScopeBase*scope)
|
|||
void ForLoopStatement::write_to_stream(ostream&fd)
|
||||
{
|
||||
fd << "for " << it_ << " in ";
|
||||
range_->expr_left()->write_to_stream(fd);
|
||||
fd << " to ";
|
||||
range_->expr_right()->write_to_stream(fd);
|
||||
range_->write_to_stream(fd);
|
||||
fd << " loop" << endl;
|
||||
write_to_stream_substatements(fd);
|
||||
fd << "end loop;" << endl;
|
||||
|
|
@ -476,21 +457,21 @@ int ForLoopStatement::emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope)
|
|||
int errors = 0;
|
||||
|
||||
out << "for (\\" << it_ << " = ";
|
||||
errors += range_->expr_left()->emit(out, ent, scope);
|
||||
errors += range_->left()->emit(out, ent, scope);
|
||||
|
||||
// Twisted way of determining the loop direction at runtime
|
||||
out << " ;\n(";
|
||||
errors += range_->expr_left()->emit(out, ent, scope);
|
||||
errors += range_->left()->emit(out, ent, scope);
|
||||
out << " < ";
|
||||
errors += range_->expr_right()->emit(out, ent, scope);
|
||||
errors += range_->right()->emit(out, ent, scope);
|
||||
out << " ? \\" << it_ << " <= ";
|
||||
errors += range_->expr_right()->emit(out, ent, scope);
|
||||
errors += range_->right()->emit(out, ent, scope);
|
||||
out << " : \\" << it_ << " >= ";
|
||||
errors += range_->expr_right()->emit(out, ent, scope);
|
||||
errors += range_->right()->emit(out, ent, scope);
|
||||
out << ");\n\\" << it_ << " = \\" << it_ << " + (";
|
||||
errors += range_->expr_left()->emit(out, ent, scope);
|
||||
errors += range_->left()->emit(out, ent, scope);
|
||||
out << " < ";
|
||||
errors += range_->expr_right()->emit(out, ent, scope);
|
||||
errors += range_->right()->emit(out, ent, scope);
|
||||
out << " ? 1 : -1))";
|
||||
|
||||
return errors;
|
||||
|
|
|
|||
|
|
@ -108,21 +108,18 @@ VTypeArray::VTypeArray(const VType*element, const vector<VTypeArray::range_t>&r,
|
|||
|
||||
/*
|
||||
* Create a VTypeArray range set from a list of parsed ranges.
|
||||
* FIXME: We are copying pointers from the prange_t object into the
|
||||
* range_t. This means that we cannot delete the prange_t object
|
||||
* FIXME: We are copying pointers from the ExpRange object into the
|
||||
* range_t. This means that we cannot delete the ExpRange object
|
||||
* unless we invent a way to remove the pointers from that object. So
|
||||
* this is a memory leak. Something to fix.
|
||||
*/
|
||||
VTypeArray::VTypeArray(const VType*element, std::list<prange_t*>*r, bool sv)
|
||||
VTypeArray::VTypeArray(const VType*element, std::list<ExpRange*>*r, bool 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();
|
||||
ExpRange*curp = r->front();
|
||||
r->pop_front();
|
||||
Expression*msb = curp->msb();
|
||||
Expression*lsb = curp->lsb();
|
||||
bool dir = curp->is_downto();
|
||||
ranges_[idx] = range_t(msb, lsb, dir);
|
||||
ranges_[idx] = range_t(curp->msb(), curp->lsb(), curp->direction());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class Architecture;
|
|||
class ScopeBase;
|
||||
class Entity;
|
||||
class Expression;
|
||||
class prange_t;
|
||||
class ExpRange;
|
||||
class VTypeDef;
|
||||
class ScopeBase;
|
||||
|
||||
|
|
@ -210,7 +210,7 @@ class VTypeArray : public VType {
|
|||
|
||||
public:
|
||||
VTypeArray(const VType*etype, const std::vector<range_t>&r, bool signed_vector = false);
|
||||
VTypeArray(const VType*etype, std::list<prange_t*>*r, bool signed_vector = false);
|
||||
VTypeArray(const VType*etype, std::list<ExpRange*>*r, bool signed_vector = false);
|
||||
VTypeArray(const VType*etype, int msb, int lsb, bool signed_vector = false);
|
||||
~VTypeArray();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue