Merge pull request #46 from orsonmmz/range

VHDL attributes: 'range, 'reverse_range, 'left & 'right
This commit is contained in:
Stephen Williams 2014-10-10 17:23:59 -07:00
commit d6685f40a1
15 changed files with 143 additions and 27 deletions

View File

@ -567,7 +567,7 @@ const VType* ExpAttribute::probe_type(Entity*ent, Architecture*arc) const
{ {
base_->probe_type(ent, arc); base_->probe_type(ent, arc);
if (name_ == "length") { if (name_ == "length" || name_ == "left" || name_ == "right") {
return &primitive_INTEGER; return &primitive_INTEGER;
} }

View File

@ -313,8 +313,8 @@ int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc)
return errors; return errors;
} }
/* Special Case: The length attribute can be calculated all /* Special Case: The length,left & right attributes can be calculated
the down to a literal integer at compile time, and all it all the down to a literal integer at compile time, and all it
needs is the type of the base expression. (The base needs is the type of the base expression. (The base
expression doesn't even need to be evaluated.) */ expression doesn't even need to be evaluated.) */
if (name_=="length") { if (name_=="length") {
@ -322,9 +322,13 @@ int ExpAttribute::emit(ostream&out, Entity*ent, Architecture*arc)
errors += base_->emit(out, ent, arc); errors += base_->emit(out, ent, arc);
out << ")"; out << ")";
return errors; return errors;
} else if (name_=="left" || name_=="right") {
out << "$" << name_ << "(";
errors += base_->emit(out, ent, arc);
out << ")";
return errors;
} }
out << "$ivl_attribute("; out << "$ivl_attribute(";
errors += base_->emit(out, ent, arc); errors += base_->emit(out, ent, arc);
out << ", \"" << name_ << "\")"; out << ", \"" << name_ << "\")";

View File

@ -110,8 +110,32 @@ bool ExpAttribute::evaluate(ScopeBase*, int64_t&val) const
return false; return false;
} }
bool ExpAttribute::evaluate(Entity*, Architecture*arc, int64_t&val) const bool ExpAttribute::evaluate(Entity*ent, Architecture*arc, int64_t&val) const
{ {
if (name_ == "left" || name_ == "right") {
const VType*base_type = base_->peek_type();
if (base_type == 0)
base_type = base_->probe_type(ent,arc);
ivl_assert(*this, base_type);
const VTypeArray*arr = dynamic_cast<const VTypeArray*>(base_type);
if (arr == 0) {
cerr << get_fileline() << ": error: "
<< "Cannot apply the 'left attribute to non-array objects"
<< endl;
return false;
}
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);
return true;
}
return evaluate(arc, val); return evaluate(arc, val);
} }

View File

@ -111,9 +111,10 @@ void ExpArithmetic::write_to_stream(ostream&out)
out << ")"; out << ")";
} }
void ExpAttribute::write_to_stream(ostream&) void ExpAttribute::write_to_stream(ostream&fd)
{ {
ivl_assert(*this, !"Not supported"); base_->write_to_stream(fd);
fd << "'" << name_;
} }
void ExpBitstring::write_to_stream(ostream&fd) void ExpBitstring::write_to_stream(ostream&fd)

View File

@ -96,6 +96,7 @@ rem, GN_KEYWORD_2008, K_rem
report, GN_KEYWORD_2008, K_report report, GN_KEYWORD_2008, K_report
restrict, GN_KEYWORD_2008, K_restrict restrict, GN_KEYWORD_2008, K_restrict
return, GN_KEYWORD_2008, K_return return, GN_KEYWORD_2008, K_return
reverse_range, GN_KEYWORD_2008, K_reverse_range
rol, GN_KEYWORD_2008, K_rol rol, GN_KEYWORD_2008, K_rol
ror, GN_KEYWORD_2008, K_ror ror, GN_KEYWORD_2008, K_ror
select, GN_KEYWORD_2008, K_select select, GN_KEYWORD_2008, K_select

View File

@ -363,7 +363,7 @@ static void import_ieee_use(ActiveScope*res, perm_string package, perm_string na
const VTypePrimitive primitive_BOOLEAN(VTypePrimitive::BOOLEAN, true); const VTypePrimitive primitive_BOOLEAN(VTypePrimitive::BOOLEAN, true);
const VTypePrimitive primitive_BIT(VTypePrimitive::BIT, true); const VTypePrimitive primitive_BIT(VTypePrimitive::BIT, true);
const VTypePrimitive primitive_INTEGER(VTypePrimitive::INTEGER, true); const VTypePrimitive primitive_INTEGER(VTypePrimitive::INTEGER);
const VTypePrimitive primitive_REAL(VTypePrimitive::REAL); const VTypePrimitive primitive_REAL(VTypePrimitive::REAL);
const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC, true); const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC, true);
const VTypePrimitive primitive_CHARACTER(VTypePrimitive::CHARACTER); const VTypePrimitive primitive_CHARACTER(VTypePrimitive::CHARACTER);

View File

@ -75,6 +75,10 @@ void Package::write_to_stream(ostream&fd) const
continue; continue;
if (cur->first == "std_logic_vector") if (cur->first == "std_logic_vector")
continue; continue;
if (cur->first == "signed")
continue;
if (cur->first == "unsigned")
continue;
fd << "type " << cur->first << " is "; fd << "type " << cur->first << " is ";
cur->second->write_type_to_stream(fd); cur->second->write_type_to_stream(fd);

View File

@ -85,6 +85,10 @@ static ActiveScope*active_scope = new ActiveScope;
static stack<ActiveScope*> scope_stack; static stack<ActiveScope*> scope_stack;
static Subprogram*active_sub = NULL; static Subprogram*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 * When a scope boundary starts, call the push_scope function to push
* a scope context. Preload this scope context with the contents of * a scope context. Preload this scope context with the contents of
@ -276,7 +280,7 @@ static void touchup_interface_for_functions(std::list<InterfacePort*>*ports)
%token K_package K_parameter K_port K_postponed K_procedure K_process %token K_package K_parameter K_port K_postponed K_procedure K_process
%token K_property K_protected K_pure %token K_property K_protected K_pure
%token K_range K_record K_register K_reject K_release K_rem K_report %token K_range K_record K_register K_reject K_release K_rem K_report
%token K_restrict K_restrict_guarantee K_return K_rol K_ror %token K_restrict K_restrict_guarantee K_return K_reverse_range K_rol K_ror
%token K_select K_sequence K_severity K_signal K_shared %token K_select K_sequence K_severity K_signal K_shared
%token K_sla K_sll K_sra K_srl K_strong K_subtype %token K_sla K_sll K_sra K_srl K_strong K_subtype
%token K_then K_to K_transport K_type %token K_then K_to K_transport K_type
@ -1904,6 +1908,34 @@ range
{ prange_t* tmp = new prange_t($1, $3, $2); { prange_t* tmp = new prange_t($1, $3, $2);
$$ = tmp; $$ = tmp;
} }
| name '\'' K_range
{
prange_t*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();
} else {
errormsg(@1, "'range attribute can be used with named expressions only");
}
$$ = tmp;
}
| name '\'' K_reverse_range
{
prange_t*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();
} else {
errormsg(@1, "'reverse_range attribute can be used with named expressions only");
}
$$ = tmp;
}
; ;
range_list range_list

View File

@ -71,7 +71,7 @@ class instant_list_t {
class prange_t { class prange_t {
public: public:
prange_t(Expression* left, Expression* right, bool dir) prange_t(Expression* left, Expression* right, bool dir)
: left_(left), right_(right), direction_(dir) {} : left_(left), right_(right), direction_(dir), auto_dir_(false) {}
~prange_t() { delete left_; delete right_; } ~prange_t() { delete left_; delete right_; }
void dump(ostream&out, int indent) const; void dump(ostream&out, int indent) const;
@ -79,12 +79,16 @@ class prange_t {
inline Expression*lsb() { return direction_? right_: left_; } inline Expression*lsb() { return direction_? right_: left_; }
inline bool is_downto() const { return direction_; } 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_left() { return left_; }
inline Expression*expr_right() { return right_; } inline Expression*expr_right() { return right_; }
private: private:
Expression *left_, *right_; Expression *left_, *right_;
bool direction_; bool direction_;
bool auto_dir_;
private: //not implemented private: //not implemented
prange_t(const prange_t&); prange_t(const prange_t&);

View File

@ -212,25 +212,35 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, Architecture*arc)
ivl_assert(*this, start_rc); ivl_assert(*this, start_rc);
ivl_assert(*this, finish_rc); ivl_assert(*this, finish_rc);
if (! range_->is_downto()) { bool dir = range_->is_downto();
if (!dir) {
int64_t tmp = start_val; int64_t tmp = start_val;
start_val = finish_val; start_val = finish_val;
finish_val = tmp; finish_val = tmp;
} }
if (range_->is_downto() && (start_val < finish_val)) { if (dir && (start_val < finish_val)) {
if(range_->is_auto_dir()) {
dir = false;
} else {
out << "begin /* Degenerate loop at " << get_fileline() out << "begin /* Degenerate loop at " << get_fileline()
<< ": " << start_val << ": " << start_val
<< " downto " << finish_val << " */ end" << endl; << " downto " << finish_val << " */ end" << endl;
return errors; return errors;
} }
}
if (!range_->is_downto() && start_val > finish_val) { else if (!dir && start_val > finish_val) {
if(range_->is_auto_dir()) {
dir = true;
} else {
out << "begin /* Degenerate loop at " << get_fileline() out << "begin /* Degenerate loop at " << get_fileline()
<< ": " << start_val << ": " << start_val
<< " to " << finish_val << " */ end" << endl; << " to " << finish_val << " */ end" << endl;
return errors; return errors;
} }
}
perm_string scope_name = loop_name(); perm_string scope_name = loop_name();
if (scope_name.nil()) { if (scope_name.nil()) {
@ -242,12 +252,12 @@ int ForLoopStatement::emit(ostream&out, Entity*ent, Architecture*arc)
out << "begin : " << scope_name << endl; out << "begin : " << scope_name << endl;
out << "longint \\" << it_ << " ;" << endl; out << "longint \\" << it_ << " ;" << endl;
out << "for (\\" << it_ << " = " << start_val << " ; "; out << "for (\\" << it_ << " = " << start_val << " ; ";
if (range_->is_downto()) if (dir)
out << "\\" << it_ << " >= " << finish_val; out << "\\" << it_ << " >= " << finish_val;
else else
out << "\\" << it_ << " <= " << finish_val; out << "\\" << it_ << " <= " << finish_val;
out << "; \\" << it_ << " = \\" << it_; out << "; \\" << it_ << " = \\" << it_;
if (range_->is_downto()) if (dir)
out << " - 1"; out << " - 1";
else else
out << " + 1"; out << " + 1";

View File

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

View File

@ -195,6 +195,7 @@ class VTypeArray : public VType {
int elaborate(Entity*ent, Architecture*arc) const; int elaborate(Entity*ent, Architecture*arc) const;
void write_to_stream(std::ostream&fd) const; void write_to_stream(std::ostream&fd) const;
void write_type_to_stream(std::ostream&fd) const;
void show(std::ostream&) const; void show(std::ostream&) const;
inline size_t dimensions() const { return ranges_.size(); }; inline size_t dimensions() const { return ranges_.size(); };
@ -312,7 +313,7 @@ class VTypeDef : public VType {
inline const VType* peek_definition(void) const { return type_; } inline const VType* peek_definition(void) const { return type_; }
void write_to_stream(std::ostream&fd) const; void write_to_stream(std::ostream&fd) const;
void write_type_to_stream(ostream&fd) const; void write_type_to_stream(std::ostream&fd) const;
int emit_typedef(std::ostream&out, typedef_context_t&ctx) const; int emit_typedef(std::ostream&out, typedef_context_t&ctx) const;
int emit_def(std::ostream&out, perm_string name) const; int emit_def(std::ostream&out, perm_string name) const;

View File

@ -146,7 +146,7 @@ int VTypePrimitive::emit_primitive_type(ostream&out) const
out << "logic"; out << "logic";
break; break;
case INTEGER: case INTEGER:
out << "bool[31:0]"; out << "int";
break; break;
case REAL: case REAL:
out << "real"; out << "real";

View File

@ -90,9 +90,40 @@ void VTypeArray::write_range_to_stream_(std::ostream&fd) const
fd << ") "; fd << ") ";
} }
void VTypeArray::write_type_to_stream(ostream&fd) const
{
// Special case: std_logic_vector
if (etype_ == &primitive_STDLOGIC) {
fd << "std_logic_vector";
if (! ranges_.empty() && ! ranges_[0].is_box()) {
write_range_to_stream_(fd);
}
return;
}
fd << "array ";
if (! ranges_.empty()) {
assert(ranges_.size() < 2);
if (ranges_[0].is_box()) {
fd << "(INTEGER range <>) ";
} else {
write_range_to_stream_(fd);
}
}
fd << "of ";
if(const VTypeDef*tdef = dynamic_cast<const VTypeDef*>(etype_)) {
tdef->write_to_stream(fd);
} else {
etype_->write_to_stream(fd);
}
}
void VTypeDef::write_type_to_stream(ostream&fd) const void VTypeDef::write_type_to_stream(ostream&fd) const
{ {
type_->write_to_stream(fd); type_->write_type_to_stream(fd);
} }
void VTypeDef::write_to_stream(ostream&fd) const void VTypeDef::write_to_stream(ostream&fd) const

View File

@ -808,6 +808,10 @@ statement
symbols_net ';' symbols_net ';'
{ compile_netw($1, $3, $4, $6, $7, vpiLogicVar, true, $9.cnt, $9.vect); } { compile_netw($1, $3, $4, $6, $7, vpiLogicVar, true, $9.cnt, $9.vect); }
| T_LABEL K_NET_2S T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ','
symbols_net ';'
{ compile_netw($1, $3, $4, $6, $7, vpiIntVar, true, $9.cnt, $9.vect); }
| T_LABEL K_NET8 T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ',' | T_LABEL K_NET8 T_SYMBOL T_NUMBER ',' signed_t_number signed_t_number ','
symbols_net ';' symbols_net ';'
{ compile_netw($1, $3, $4, $6, $7, -vpiLogicVar, false, $9.cnt, $9.vect); } { compile_netw($1, $3, $4, $6, $7, -vpiLogicVar, false, $9.cnt, $9.vect); }