From 4786f80b0b6a829716247c7ba97497ee7eb66533 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 8 Aug 2014 09:52:57 +0200 Subject: [PATCH 01/19] Add the string terminator for binary bitstrings. --- vhdlpp/lexor.lex | 1 + 1 file changed, 1 insertion(+) diff --git a/vhdlpp/lexor.lex b/vhdlpp/lexor.lex index 2f3fd197b..c9dae5c51 100644 --- a/vhdlpp/lexor.lex +++ b/vhdlpp/lexor.lex @@ -409,6 +409,7 @@ static char*make_bitstring_bin(int width_prefix, bool sflag, bool, while (*src) { *rp++ = *src++; } + *rp = 0; return res; } From 9031f392ba937eb03f68cea4ecdf3c68d2101942 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 8 Aug 2014 11:20:07 +0200 Subject: [PATCH 02/19] Convert string to bitstring in SigVarBase constructor if applicable (vhdlpp). --- vhdlpp/expression.h | 1 + vhdlpp/vsignal.cc | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index d26a8c5df..185622f91 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -639,6 +639,7 @@ class ExpString : public Expression { int emit(ostream&out, Entity*ent, Architecture*arc); bool is_primary(void) const; void dump(ostream&out, int indent = 0) const; + const std::vector& get_value() const { return value_; } private: int emit_as_array_(ostream&out, Entity*ent, Architecture*arc, const VTypeArray*arr); diff --git a/vhdlpp/vsignal.cc b/vhdlpp/vsignal.cc index 29627f924..59cf3774b 100644 --- a/vhdlpp/vsignal.cc +++ b/vhdlpp/vsignal.cc @@ -27,6 +27,21 @@ using namespace std; SigVarBase::SigVarBase(perm_string nam, const VType*typ, Expression*exp) : name_(nam), type_(typ), init_expr_(exp), refcnt_sequ_(0) { + if(init_expr_) + { + // convert the initializing string to bitstring if applicable + const ExpString *string = dynamic_cast(init_expr_); + if(string) { + const std::vector& val = string->get_value(); + char buf[val.size() + 1]; + std::copy(val.begin(), val.end(), buf); + buf[val.size()] = 0; + + ExpBitstring *bitstring = new ExpBitstring(buf); + delete init_expr_; + init_expr_ = bitstring; + } + } } SigVarBase::~SigVarBase() From c92dea77fcecf5a3c3bb4035c1af2f299d5e9268 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 8 Aug 2014 17:17:47 +0200 Subject: [PATCH 03/19] vhdlpp: Basic support for unbounded array types. Once a signal/variable of unbounded array type becomes limited in its size, it is emitted as a packed array. Therefore currently it works only for bit/logic/reg/wire types. --- vhdlpp/parse.y | 4 ++-- vhdlpp/parse_misc.cc | 6 ++++++ vhdlpp/vtype_emit.cc | 12 +++++------- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index e9ac90604..0372d4925 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -684,8 +684,8 @@ composite_type_definition /* unbounded_array_definition IEEE 1076-2008 P5.3.2.1 */ | K_array '(' index_subtype_definition_list ')' K_of subtype_indication - { sorrymsg(@1, "unbounded_array_definition not supported.\n"); - std::list r; + { std::list r; + r.push_back(new prange_t(NULL, NULL, true)); // NULL boundaries indicate unbounded array type VTypeArray*tmp = new VTypeArray($6, &r); $$ = tmp; } diff --git a/vhdlpp/parse_misc.cc b/vhdlpp/parse_misc.cc index 0049388bf..3956b4a1a 100644 --- a/vhdlpp/parse_misc.cc +++ b/vhdlpp/parse_misc.cc @@ -82,6 +82,12 @@ static const VType* calculate_subtype_array(const YYLTYPE&loc, const char*base_n assert(array_left==0 || array_right!=0); + // unfold typedef, if it is the case + const VTypeDef*type_def = dynamic_cast (base_type); + if (type_def) { + base_type = type_def->peek_definition(); + } + const VTypeArray*base_array = dynamic_cast (base_type); if (base_array) { assert(array_left && array_right); diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index d5f8b32da..baea99a3d 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -88,16 +88,14 @@ int VTypeArray::emit_def(ostream&out) const while (! dims.empty()) { cur = dims.front(); dims.pop_front(); + out << "["; - if (cur->dimension(0).msb()) + 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); - else - out << "?error?"; - out << ":"; - if (cur->dimension(0).lsb()) + out << ":"; errors += cur->dimension(0).lsb()->emit(out, 0, 0); - else - out << "?error?"; + } out << "]"; } From 72ff9ac00b0da449e5bf9401493b0958807ab6c4 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 20 Aug 2014 14:18:16 +0200 Subject: [PATCH 04/19] vhdlpp: Aggregate expression are elaborated if they are used for Signal/Variable initalization. --- vhdlpp/architec_elaborate.cc | 18 ++++++++++++++++++ vhdlpp/vsignal.cc | 25 +++++++++++++++++-------- vhdlpp/vsignal.h | 3 +++ 3 files changed, 38 insertions(+), 8 deletions(-) diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index 3ffc8c6da..c255df43a 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -41,6 +41,24 @@ int Architecture::elaborate(Entity*entity) cur->second->val->elaborate_expr(entity, this, cur->second->typ); } + // Elaborate initializer expressions for signals & variables + for (map::iterator cur = old_signals_.begin() + ; cur != old_signals_.end() ; ++cur) { + cur->second->elaborate_init_expr(entity, this); + } + for (map::iterator cur = new_signals_.begin() + ; cur != new_signals_.end() ; ++cur) { + cur->second->elaborate_init_expr(entity, this); + } + for (map::iterator cur = old_variables_.begin() + ; cur != old_variables_.end() ; ++cur) { + cur->second->elaborate_init_expr(entity, this); + } + for (map::iterator cur = new_variables_.begin() + ; cur != new_variables_.end() ; ++cur) { + cur->second->elaborate_init_expr(entity, this); + } + for (list::iterator cur = statements_.begin() ; cur != statements_.end() ; ++cur) { diff --git a/vhdlpp/vsignal.cc b/vhdlpp/vsignal.cc index 59cf3774b..a53d6bf36 100644 --- a/vhdlpp/vsignal.cc +++ b/vhdlpp/vsignal.cc @@ -27,27 +27,36 @@ using namespace std; SigVarBase::SigVarBase(perm_string nam, const VType*typ, Expression*exp) : name_(nam), type_(typ), init_expr_(exp), refcnt_sequ_(0) { - if(init_expr_) - { +} + +SigVarBase::~SigVarBase() +{ +} + +void SigVarBase::elaborate_init_expr(Entity*ent, Architecture*arc) +{ + if(init_expr_) { // convert the initializing string to bitstring if applicable - const ExpString *string = dynamic_cast(init_expr_); + const ExpString*string = dynamic_cast(init_expr_); if(string) { const std::vector& val = string->get_value(); char buf[val.size() + 1]; std::copy(val.begin(), val.end(), buf); buf[val.size()] = 0; - ExpBitstring *bitstring = new ExpBitstring(buf); + ExpBitstring*bitstring = new ExpBitstring(buf); delete init_expr_; init_expr_ = bitstring; } + else { + ExpAggregate*aggr = dynamic_cast(init_expr_); + if(aggr) { + aggr->elaborate_expr(ent, arc, peek_type()); + } + } } } -SigVarBase::~SigVarBase() -{ -} - void SigVarBase::type_elaborate_(VType::decl_t&decl) { decl.type = type_; diff --git a/vhdlpp/vsignal.h b/vhdlpp/vsignal.h index 3e2be389c..9d97e3b0f 100644 --- a/vhdlpp/vsignal.h +++ b/vhdlpp/vsignal.h @@ -41,6 +41,9 @@ 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); + protected: perm_string peek_name_() const { return name_; } unsigned peek_refcnt_sequ_() const { return refcnt_sequ_; } From feccae56bf286582385a73f6a9cad63e23dbc723 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 22 Aug 2014 10:42:51 +0200 Subject: [PATCH 05/19] libmisc: Added empty_perm_string. --- libmisc/StringHeap.cc | 2 ++ libmisc/StringHeap.h | 1 + 2 files changed, 3 insertions(+) diff --git a/libmisc/StringHeap.cc b/libmisc/StringHeap.cc index 6c30bafa7..f87c4fcf8 100644 --- a/libmisc/StringHeap.cc +++ b/libmisc/StringHeap.cc @@ -210,3 +210,5 @@ ostream& operator << (ostream&out, perm_string that) out << that.str(); return out; } + +const perm_string empty_perm_string = perm_string::literal(""); diff --git a/libmisc/StringHeap.h b/libmisc/StringHeap.h index eecbec7b0..5c791e104 100644 --- a/libmisc/StringHeap.h +++ b/libmisc/StringHeap.h @@ -52,6 +52,7 @@ class perm_string { const char*text_; }; +extern const perm_string empty_perm_string; extern bool operator == (perm_string a, perm_string b); extern bool operator == (perm_string a, const char* b); extern bool operator != (perm_string a, perm_string b); From 8e9c25a23e33cf7b5e1e8cfd8aa886b2aa90d581 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 22 Aug 2014 10:45:02 +0200 Subject: [PATCH 06/19] vhdlpp: Added 'packed' property for VTypes. It detetermines if a type can be used as the base type of a packed array. --- vhdlpp/library.cc | 15 ++++++++++++--- vhdlpp/parse_misc.h | 3 +++ vhdlpp/vtype.cc | 8 ++++---- vhdlpp/vtype.h | 10 +++++++++- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index 7266fcba1..91c197267 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -343,11 +343,11 @@ static void import_ieee_use(ActiveScope*res, perm_string package, perm_string na } } -const VTypePrimitive primitive_BOOLEAN(VTypePrimitive::BOOLEAN); -const VTypePrimitive primitive_BIT(VTypePrimitive::BIT); +const VTypePrimitive primitive_BOOLEAN(VTypePrimitive::BOOLEAN, true); +const VTypePrimitive primitive_BIT(VTypePrimitive::BIT, true); const VTypePrimitive primitive_INTEGER(VTypePrimitive::INTEGER); const VTypePrimitive primitive_REAL(VTypePrimitive::REAL); -const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC); +const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC, true); const VTypePrimitive primitive_CHARACTER(VTypePrimitive::CHARACTER); const VTypeRange primitive_NATURAL(&primitive_INTEGER, INT64_MAX, 0); @@ -383,6 +383,15 @@ bool is_global_type(perm_string name) return false; } +bool can_be_packed(perm_string name) +{ + if (name == "boolean") return true; + if (name == "bit") return true; + if (name == "std_logic") return true; + if (name == "bit_vector") return true; + return true; +} + void library_set_work_path(const char*path) { assert(library_work_path == 0); diff --git a/vhdlpp/parse_misc.h b/vhdlpp/parse_misc.h index e4aa9e644..a2e6292c9 100644 --- a/vhdlpp/parse_misc.h +++ b/vhdlpp/parse_misc.h @@ -67,4 +67,7 @@ extern void generate_global_types(ActiveScope*res); extern bool is_global_type(perm_string type_name); +// Returns true if a type can be used as the base type in Verilog packed array. +extern bool can_be_packed(perm_string type_name); + #endif /* IVL_parse_misc_H */ diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index 9d35bd36b..7c0875f44 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -35,8 +35,8 @@ void VType::show(ostream&out) const write_to_stream(out); } -VTypePrimitive::VTypePrimitive(VTypePrimitive::type_t tt) -: type_(tt) +VTypePrimitive::VTypePrimitive(VTypePrimitive::type_t tt, bool packed) +: type_(tt), packed_(packed) { } @@ -60,8 +60,8 @@ void VTypePrimitive::show(ostream&out) const out << "INTEGER"; break; case REAL: - out << "REAL"; - break; + out << "REAL"; + break; case STDLOGIC: out << "std_logic"; break; diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index f9f66001e..003f8d937 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -82,6 +82,9 @@ class VType { // all the types that it emits. virtual int emit_typedef(std::ostream&out, typedef_context_t&ctx) const; + // Determines if a type can be used in Verilog packed array. + virtual bool can_be_packed() const { return false; } + private: friend class decl_t; // This virtual method is called to emit the declaration. This @@ -128,7 +131,7 @@ class VTypePrimitive : public VType { enum type_t { BOOLEAN, BIT, INTEGER, REAL, STDLOGIC, CHARACTER }; public: - VTypePrimitive(type_t); + VTypePrimitive(type_t tt, bool packed = false); ~VTypePrimitive(); void write_to_stream(std::ostream&fd) const; @@ -139,8 +142,11 @@ class VTypePrimitive : public VType { int emit_primitive_type(std::ostream&fd) const; int emit_def(std::ostream&out) const; + bool can_be_packed() const { return packed_; } + private: type_t type_; + bool packed_; }; extern const VTypePrimitive primitive_BOOLEAN; @@ -194,6 +200,8 @@ class VTypeArray : public VType { int emit_def(std::ostream&out) const; int emit_typedef(std::ostream&out, typedef_context_t&ctx) const; + bool can_be_packed() const { return etype_->can_be_packed(); } + private: const VType*etype_; From 27730395caaa15873b488e0db7b6fb3fdbc249a4 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 22 Aug 2014 10:49:55 +0200 Subject: [PATCH 07/19] vhdlpp: Type of an array is selected depending on the element type. --- vhdlpp/package_emit.cc | 4 +- vhdlpp/subprogram_emit.cc | 5 +- vhdlpp/vtype.h | 17 +++--- vhdlpp/vtype_emit.cc | 105 ++++++++++++++++++++++++-------------- 4 files changed, 79 insertions(+), 52 deletions(-) diff --git a/vhdlpp/package_emit.cc b/vhdlpp/package_emit.cc index 5792cd728..2cc3b91fb 100644 --- a/vhdlpp/package_emit.cc +++ b/vhdlpp/package_emit.cc @@ -48,8 +48,8 @@ int Package::emit_package(ostream&fd) const for (map::const_iterator cur = cur_types_.begin() ; cur != cur_types_.end() ; ++ cur) { fd << "typedef "; - errors += cur->second->emit_def(fd); - fd << " \\" << cur->first << " ;" << endl; + errors += cur->second->emit_def(fd, cur->first); + fd << " ;" << endl; } for (map::const_iterator cur = use_constants_.begin() diff --git a/vhdlpp/subprogram_emit.cc b/vhdlpp/subprogram_emit.cc index efd586bd0..402b0a4cd 100644 --- a/vhdlpp/subprogram_emit.cc +++ b/vhdlpp/subprogram_emit.cc @@ -31,7 +31,7 @@ int Subprogram::emit_package(ostream&fd) const if (return_type_) { fd << "function "; - return_type_->emit_def(fd); + return_type_->emit_def(fd, empty_perm_string); fd << " " << name_; fd << "("; } else { @@ -55,8 +55,7 @@ int Subprogram::emit_package(ostream&fd) const break; } - errors += curp->type->emit_def(fd); - fd << " \\" << curp->name << " "; + errors += curp->type->emit_def(fd, curp->name); } fd << ");" << endl; diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 003f8d937..ed264e762 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -74,7 +74,7 @@ class VType { // This virtual method emits a definition for the specific // type. It is used to emit typedef's. - virtual int emit_def(std::ostream&out) const =0; + virtual int emit_def(std::ostream&out, perm_string name) const =0; // This virtual method causes VTypeDef types to emit typedefs // of themselves. The VTypeDef implementation of this method @@ -118,7 +118,7 @@ extern void preload_global_types(void); */ class VTypeERROR : public VType { public: - int emit_def(std::ostream&out) const; + int emit_def(std::ostream&out, perm_string name) const; }; /* @@ -140,7 +140,7 @@ class VTypePrimitive : public VType { type_t type() const { return type_; } int emit_primitive_type(std::ostream&fd) const; - int emit_def(std::ostream&out) const; + int emit_def(std::ostream&out, perm_string name) const; bool can_be_packed() const { return packed_; } @@ -197,8 +197,9 @@ class VTypeArray : public VType { const VType* element_type() const; - int emit_def(std::ostream&out) const; + 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(); } @@ -220,7 +221,7 @@ class VTypeRange : public VType { public: // Virtual methods void write_to_stream(std::ostream&fd) const; - int emit_def(std::ostream&out) const; + int emit_def(std::ostream&out, perm_string name) const; private: const VType*base_; @@ -234,7 +235,7 @@ class VTypeEnum : public VType { ~VTypeEnum(); void show(std::ostream&) const; - int emit_def(std::ostream&out) const; + int emit_def(std::ostream&out, perm_string name) const; private: std::vectornames_; @@ -267,7 +268,7 @@ class VTypeRecord : public VType { void write_to_stream(std::ostream&fd) const; void show(std::ostream&) const; - int emit_def(std::ostream&out) const; + int emit_def(std::ostream&out, perm_string name) const; const element_t* element_by_name(perm_string name) const; @@ -296,7 +297,7 @@ class VTypeDef : public VType { void write_type_to_stream(ostream&fd) const; int emit_typedef(std::ostream&out, typedef_context_t&ctx) const; - int emit_def(std::ostream&out) const; + int emit_def(std::ostream&out, perm_string name) const; private: int emit_decl(std::ostream&out, perm_string name, bool reg_flag) const; diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index baea99a3d..a984db5b6 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -21,7 +21,7 @@ # include "vtype.h" # include "expression.h" -# include +# include # include # include @@ -33,7 +33,6 @@ int VType::decl_t::emit(ostream&out, perm_string name) const return type->emit_decl(out, name, reg_flag); } - int VType::emit_decl(ostream&out, perm_string name, bool reg_flag) const { int errors = 0; @@ -41,9 +40,8 @@ int VType::emit_decl(ostream&out, perm_string name, bool reg_flag) const if (!reg_flag) out << "wire "; - errors += emit_def(out); - - out << " \\" << name << " "; + errors += emit_def(out, name); + out << " "; return errors; } @@ -52,13 +50,55 @@ int VType::emit_typedef(std::ostream&, typedef_context_t&) const return 0; } -int VTypeERROR::emit_def(ostream&out) const +int VTypeERROR::emit_def(ostream&out, perm_string) const { out << "/* ERROR */"; return 1; } -int VTypeArray::emit_def(ostream&out) const +int VTypeArray::emit_def(ostream&out, perm_string name) const +{ + int errors = 0; + + const VTypeArray*cur = this; + while (const VTypeArray*sub = dynamic_cast (cur->etype_)) { + cur = sub; + } + + const VType*raw_base = cur->etype_; + const VTypePrimitive*base = dynamic_cast (raw_base); + stringstream buf; + + if (base) { + assert(dimensions() == 1); + + base->emit_def(buf, empty_perm_string); + if (signed_flag_) + buf << " signed"; + } else { + raw_base->emit_def(buf, empty_perm_string); + } + + string tmp(buf.str()); + out << tmp.substr(0, tmp.length() - 2); // drop the empty type name (\ ) + + if(raw_base->can_be_packed()) { + errors += emit_dimensions(out); + out << " \\" << name; + } else { + out << "\\" << name << " "; + errors += emit_dimensions(out); + } + + return errors; +} + +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 errors = 0; @@ -68,21 +108,6 @@ int VTypeArray::emit_def(ostream&out) const dims.push_back(cur); cur = sub; } - - const VType*raw_base = cur->etype_; - - const VTypePrimitive*base = dynamic_cast (raw_base); - - if (base) { - assert(dimensions() == 1); - - base->emit_def(out); - if (signed_flag_) - out << " signed"; - } else { - raw_base->emit_def(out); - } - dims.push_back(cur); while (! dims.empty()) { @@ -102,12 +127,7 @@ int VTypeArray::emit_def(ostream&out) const return errors; } -int VTypeArray::emit_typedef(std::ostream&out, typedef_context_t&ctx) const -{ - return etype_->emit_typedef(out, ctx); -} - -int VTypeEnum::emit_def(ostream&out) const +int VTypeEnum::emit_def(ostream&out, perm_string name) const { int errors = 0; out << "enum {"; @@ -116,7 +136,7 @@ int VTypeEnum::emit_def(ostream&out) const for (size_t idx = 1 ; idx < names_.size() ; idx += 1) out << ", \\" << names_[idx] << " "; - out << "}"; + out << "} \\" << name << " "; return errors; } @@ -148,22 +168,23 @@ int VTypePrimitive::emit_primitive_type(ostream&out) const return errors; } -int VTypePrimitive::emit_def(ostream&out) const +int VTypePrimitive::emit_def(ostream&out, perm_string name) const { int errors = 0; errors += emit_primitive_type(out); + out << " \\" << name << " "; return errors; } -int VTypeRange::emit_def(ostream&out) const +int VTypeRange::emit_def(ostream&out, perm_string name) const { int errors = 0; out << "/* Internal error: Don't know how to emit range */"; - errors += base_->emit_def(out); + errors += base_->emit_def(out, name); return errors; } -int VTypeRecord::emit_def(ostream&out) const +int VTypeRecord::emit_def(ostream&out, perm_string name) const { int errors = 0; out << "struct packed {"; @@ -172,11 +193,11 @@ int VTypeRecord::emit_def(ostream&out) const ; cur != elements_.end() ; ++cur) { perm_string element_name = (*cur)->peek_name(); const VType*element_type = (*cur)->peek_type(); - element_type->emit_def(out); + element_type->emit_def(out, empty_perm_string); out << " \\" << element_name << " ; "; } - out << "}"; + out << "} \\ " << name << " "; return errors; } @@ -185,7 +206,7 @@ int VTypeRecord::emit_def(ostream&out) 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) const +int VTypeDef::emit_def(ostream&out, perm_string) const { int errors = 0; out << "\\" << name_ << " "; @@ -200,7 +221,7 @@ int VTypeDef::emit_decl(ostream&out, perm_string name, bool reg_flag) const else out << "wire "; - errors += type_->emit_def(out); + errors += type_->emit_def(out, name); out << " \\" << name << " "; return errors; } @@ -227,8 +248,14 @@ int VTypeDef::emit_typedef(ostream&out, typedef_context_t&ctx) const int errors = type_->emit_typedef(out, ctx); flag = MARKED; + // Array types are used directly anyway and typedefs for unpacked + // arrays do not work currently + if(dynamic_cast(type_)) + out << "// "; + out << "typedef "; - errors += type_->emit_def(out); - out << " \\" << name_ << " ;" << endl; + errors += type_->emit_def(out, name_); + out << " ;" << endl; + return errors; } From 0a2100c87fb6b4ee182e91b3ab4a219bdcac096d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 22 Aug 2014 16:22:59 +0200 Subject: [PATCH 08/19] vhdlpp: Turn on the reg_flag for types that cannot be packed. --- vhdlpp/expression_emit.cc | 4 ++++ vhdlpp/vsignal.cc | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 8ba1d1120..b74c57f72 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -244,6 +244,10 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V // Emit the elements as a concatenation. This works great for // vectors of bits. We implement VHDL arrays as packed arrays, // so this should be generally correct. + // TODO uncomment this once ivl supports assignments of '{} + /*if(!peek_type()->can_be_packed()) + out << "'";*/ + out << "{"; for (int64_t idx = use_msb ; idx >= use_lsb ; idx -= 1) { choice_element*cur = element_map[idx]; diff --git a/vhdlpp/vsignal.cc b/vhdlpp/vsignal.cc index a53d6bf36..0c4a9cce4 100644 --- a/vhdlpp/vsignal.cc +++ b/vhdlpp/vsignal.cc @@ -68,7 +68,7 @@ int Signal::emit(ostream&out, Entity*ent, Architecture*arc) VType::decl_t decl; type_elaborate_(decl); - if (peek_refcnt_sequ_() > 0) + if (peek_refcnt_sequ_() > 0 || !peek_type()->can_be_packed()) decl.reg_flag = true; errors += decl.emit(out, peek_name_()); @@ -87,7 +87,7 @@ int Variable::emit(ostream&out, Entity*, Architecture*) VType::decl_t decl; type_elaborate_(decl); - if (peek_refcnt_sequ_() > 0) + if (peek_refcnt_sequ_() > 0 || !peek_type()->can_be_packed()) decl.reg_flag = true; errors += decl.emit(out, peek_name_()); out << ";" << endl; From 10446df80e672adb0f496e3f21c6f6d7518f69c7 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 22 Aug 2014 16:23:22 +0200 Subject: [PATCH 09/19] vhdlpp: Invert range in ExpAggregate when necessary. --- vhdlpp/expression_emit.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index b74c57f72..f2e312f8a 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -159,7 +159,8 @@ int ExpAggregate::emit_array_(ostream&out, Entity*ent, Architecture*arc, const V ivl_assert(*this, rc); rc = rang.lsb()->evaluate(ent, arc, use_lsb); ivl_assert(*this, rc); - ivl_assert(*this, use_msb >= use_lsb); + if(use_msb < use_lsb) + swap(use_msb, use_lsb); map element_map; choice_element*element_other = 0; From c846b2cf3f4696842829bcfc1d9155c4fa6e6ee2 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 22 Aug 2014 16:45:17 +0200 Subject: [PATCH 10/19] vhdlpp: 'integer' is emitted as 'integer' instead of 'bool [31:0]'. --- vhdlpp/vtype_emit.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index a984db5b6..fd65f9649 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -153,7 +153,7 @@ int VTypePrimitive::emit_primitive_type(ostream&out) const out << "logic"; break; case INTEGER: - out << "bool [31:0]"; + out << "integer"; break; case REAL: out << "real"; From b1d15436fdee44fc3823b8fb5bacbd97143330b0 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 7 Aug 2014 09:48:35 +0200 Subject: [PATCH 11/19] Removed ExpReal::evaluate().Its signature does not match the one meant to be overridden. --- vhdlpp/expression.cc | 6 ------ vhdlpp/expression.h | 1 - 2 files changed, 7 deletions(-) diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 526d06be2..feeddd88e 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -307,12 +307,6 @@ ExpReal::~ExpReal() { } -bool ExpReal::evaluate(ScopeBase*, double&val) const -{ - val = value_; - return true; -} - ExpLogical::ExpLogical(ExpLogical::fun_t ty, Expression*op1, Expression*op2) : ExpBinary(op1, op2), fun_(ty) { diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 185622f91..2cf89b78c 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -519,7 +519,6 @@ class ExpReal : public Expression { int emit(ostream&out, Entity*ent, Architecture*arc); int emit_package(std::ostream&out); bool is_primary(void) const; - bool evaluate(ScopeBase*scope, double&val) const; void dump(ostream&out, int indent = 0) const; virtual ostream& dump_inline(ostream&out) const; From 6765e32ab984dc6a33e99a0b5fcb02f921238861 Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 7 Aug 2014 16:24:32 -0700 Subject: [PATCH 12/19] Add message that L-value concatenation is not supported in synthesis --- syn-rules.y | 10 ++++++++-- synth2.cc | 12 ++++++++++-- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/syn-rules.y b/syn-rules.y index 1507b08df..8a86fe6e5 100644 --- a/syn-rules.y +++ b/syn-rules.y @@ -1,7 +1,7 @@ %{ /* - * Copyright (c) 2000-2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -100,7 +100,13 @@ static void hookup_DFF_CE(NetFF*ff, NetESignal*d, NetEvProbe*pclk, NetNet*ce, NetAssign_*a, unsigned rval_pinoffset) { - assert(rval_pinoffset == 0); + if (rval_pinoffset != 0) { + cerr << a->get_fileline() << ": sorry: " + << "unable to hook up an R-value with offset " + << rval_pinoffset << " to signal " << a->name() + << "." << endl; + return; + } // a->sig() is a *NetNet, which doesn't have the loff_ and // lwid_ context. Add the correction for loff_ ourselves. diff --git a/synth2.cc b/synth2.cc index d2e54e797..dcc80895d 100644 --- a/synth2.cc +++ b/synth2.cc @@ -82,7 +82,15 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, des->errors += 1; return false; } - assert(lval_->more == 0); + if (lval_->more) { + cerr << get_fileline() << ": sorry: " + << "NetAssignBase::synth_async does not support an " + << "L-value concatenation "; + dump_lval(cerr); + cerr << endl; + des->errors += 1; + return false; + } if (debug_synth2) { cerr << get_fileline() << ": NetAssignBase::synth_async: " @@ -1308,7 +1316,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetBus tmp_out(scope, nex_out.pin_count()); NetBus accumulated_tmp_out(scope, nex_out.pin_count()); flag = if_->synth_async(des, scope, nex_map, tmp_out, accumulated_tmp_out); - ivl_assert(*this, flag); + if (! flag) return false; ivl_assert(*this, tmp_out.pin_count() == ff_aclr.pin_count()); ivl_assert(*this, tmp_out.pin_count() == ff_aset.pin_count()); From 486dc7abebd551973d4ca14a7bcce2c2955ad67e Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sat, 9 Aug 2014 08:04:25 -0700 Subject: [PATCH 13/19] Do a better job with synthesis translate pragmas. --- lexor.lex | 9 +++++++-- parse.y | 9 --------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/lexor.lex b/lexor.lex index 6d3304dd4..2dd3ae0c5 100644 --- a/lexor.lex +++ b/lexor.lex @@ -137,8 +137,13 @@ TU [munpf] current line. These are very easy to handle. The meta-comments format is a little more tricky to handle, but do what we can. */ -"//"{W}*"synthesis"{W}*"translate_on"{W}*\n { return K_MC_TRANSLATE_ON; } -"//"{W}*"synthesis"{W}*"translate_off"{W}*\n { return K_MC_TRANSLATE_OFF; } + /* The lexor detects "// synthesis translate_on/off" meta-comments, + we handle them here by turning on/off a flag. The pform uses + that flag to attach implicit attributes to "initial" and + "always" statements. */ + +"//"{W}*"synthesis"{W}*"translate_on"{W}*\n { pform_mc_translate_on(true); } +"//"{W}*"synthesis"{W}*"translate_off"{W}*\n { pform_mc_translate_on(false); } "//" { comment_enter = YY_START; BEGIN(LCOMMENT); } . { yymore(); } \n { yylloc.first_line += 1; BEGIN(comment_enter); } diff --git a/parse.y b/parse.y index 64716c371..07bd8f189 100644 --- a/parse.y +++ b/parse.y @@ -532,8 +532,6 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %token K_resolveto K_sin K_sinh K_slew K_split K_sqrt K_tan K_tanh %token K_timer K_transition K_units K_white_noise K_wreal %token K_zi_nd K_zi_np K_zi_zd K_zi_zp - /* Support some meta-comments as pragmas. */ -%token K_MC_TRANSLATE_ON K_MC_TRANSLATE_OFF %type from_exclude block_item_decls_opt %type number pos_neg_number @@ -4248,13 +4246,6 @@ module_item /* Modules can contain further sub-module definitions. */ : module - /* The lexor detects "// synthesis translate_on/off" meta-comments, - we handle them here by turning on/off a flag. The pform uses - that flag to attach implicit attributes to "initial" and - "always" statements. */ - | K_MC_TRANSLATE_OFF { pform_mc_translate_on(false); } - | K_MC_TRANSLATE_ON { pform_mc_translate_on(true); } - | attribute_list_opt net_type data_type_or_implicit delay3_opt net_variable_list ';' { data_type_t*data_type = $3; From 86bb269d4763f64f957708c1387ef8e008a21b6b Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 11 Aug 2014 20:23:29 +0100 Subject: [PATCH 14/19] Fix for GitHub issue #33 - Problem with multi-dimensional arrays. normalize_variable_unpacked() was not correctly calculating the minimum expression width required to calculate the canonical index. --- netmisc.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/netmisc.cc b/netmisc.cc index f3984e389..ee69e8e6e 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -594,12 +594,12 @@ NetExpr* normalize_variable_unpacked(const NetNet*net, list&indices) // losses. So calculate a min_wid width. unsigned tmp_wid; unsigned min_wid = tmp->expr_width(); - if (use_stride != 1 && ((tmp_wid = num_bits(use_stride)) >= min_wid)) - min_wid = tmp_wid + 1; if (use_base != 0 && ((tmp_wid = num_bits(use_base)) >= min_wid)) min_wid = tmp_wid + 1; if ((tmp_wid = num_bits(dims[idx].width()+1)) >= min_wid) min_wid = tmp_wid + 1; + if (use_stride != 1) + min_wid += num_bits(use_stride); tmp = pad_to_width(tmp, min_wid, *net); From 447e402d16fcb65ce9fe2a79fabe21fbcd4e3b2e Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 11 Aug 2014 15:02:14 -0700 Subject: [PATCH 15/19] Require a space between the synthesis and translate_* key words --- lexor.lex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lexor.lex b/lexor.lex index 2dd3ae0c5..d14e38694 100644 --- a/lexor.lex +++ b/lexor.lex @@ -142,8 +142,8 @@ TU [munpf] that flag to attach implicit attributes to "initial" and "always" statements. */ -"//"{W}*"synthesis"{W}*"translate_on"{W}*\n { pform_mc_translate_on(true); } -"//"{W}*"synthesis"{W}*"translate_off"{W}*\n { pform_mc_translate_on(false); } +"//"{W}*"synthesis"{W}+"translate_on"{W}*\n { pform_mc_translate_on(true); } +"//"{W}*"synthesis"{W}+"translate_off"{W}*\n { pform_mc_translate_on(false); } "//" { comment_enter = YY_START; BEGIN(LCOMMENT); } . { yymore(); } \n { yylloc.first_line += 1; BEGIN(comment_enter); } From bb66ed8b9d1df345794f3a3aa0e621811bd3e2c4 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 25 Aug 2014 16:51:35 +0200 Subject: [PATCH 16/19] vhdlpp: "integer" is emitted as "bool[31:0" but is marked as accepted to be used in packed arrays. --- vhdlpp/library.cc | 2 +- vhdlpp/vtype_emit.cc | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index 91c197267..08a67d586 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -345,7 +345,7 @@ static void import_ieee_use(ActiveScope*res, perm_string package, perm_string na const VTypePrimitive primitive_BOOLEAN(VTypePrimitive::BOOLEAN, true); const VTypePrimitive primitive_BIT(VTypePrimitive::BIT, true); -const VTypePrimitive primitive_INTEGER(VTypePrimitive::INTEGER); +const VTypePrimitive primitive_INTEGER(VTypePrimitive::INTEGER, true); const VTypePrimitive primitive_REAL(VTypePrimitive::REAL); const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC, true); const VTypePrimitive primitive_CHARACTER(VTypePrimitive::CHARACTER); diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index fd65f9649..d0dea54bd 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -153,11 +153,11 @@ int VTypePrimitive::emit_primitive_type(ostream&out) const out << "logic"; break; case INTEGER: - out << "integer"; + out << "bool[31:0]"; + break; + case REAL: + out << "real"; break; - case REAL: - out << "real"; - break; case CHARACTER: out << "char"; break; From 150fe088a65dd1dee3ded1580b1e05f27fc62d6d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 25 Aug 2014 16:55:26 +0200 Subject: [PATCH 17/19] vhdlpp: VTypeRecord is marked as acceptable in packed arrays. VTypeDef is accepted depending on the base type. --- vhdlpp/vtype.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index ed264e762..d8c5f6b9a 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -270,6 +270,8 @@ class VTypeRecord : public VType { void show(std::ostream&) const; int emit_def(std::ostream&out, perm_string name) const; + bool can_be_packed() const { return true; } + const element_t* element_by_name(perm_string name) const; private: @@ -298,6 +300,8 @@ class VTypeDef : public VType { int emit_typedef(std::ostream&out, typedef_context_t&ctx) const; int emit_def(std::ostream&out, perm_string name) const; + + bool can_be_packed() const { return type_->can_be_packed(); } private: int emit_decl(std::ostream&out, perm_string name, bool reg_flag) const; From b0c79d5d1c25b4a61f6181f07ba37ac03c5b0f9d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 25 Aug 2014 16:57:27 +0200 Subject: [PATCH 18/19] vhdlpp: Added VType::emit_name() that skips emission of a name if it is empty (otherwise '\' is outputted). --- vhdlpp/vtype.h | 6 ++++++ vhdlpp/vtype_emit.cc | 25 +++++++++++-------------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index d8c5f6b9a..a52e7d377 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -103,6 +103,12 @@ class VType { bool reg_flag; }; + protected: + inline void emit_name(std::ostream&out, perm_string name) const + { + if(name != empty_perm_string) + out << " \\" << name << " "; + } }; inline std::ostream&operator << (std::ostream&out, const VType&item) diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index d0dea54bd..473107245 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -67,26 +67,22 @@ int VTypeArray::emit_def(ostream&out, perm_string name) const const VType*raw_base = cur->etype_; const VTypePrimitive*base = dynamic_cast (raw_base); - stringstream buf; if (base) { assert(dimensions() == 1); - base->emit_def(buf, empty_perm_string); + base->emit_def(out, empty_perm_string); if (signed_flag_) - buf << " signed"; + out << " signed"; } else { - raw_base->emit_def(buf, empty_perm_string); + raw_base->emit_def(out, empty_perm_string); } - string tmp(buf.str()); - out << tmp.substr(0, tmp.length() - 2); // drop the empty type name (\ ) - if(raw_base->can_be_packed()) { errors += emit_dimensions(out); - out << " \\" << name; + emit_name(out, name); } else { - out << "\\" << name << " "; + emit_name(out, name); errors += emit_dimensions(out); } @@ -136,7 +132,8 @@ int VTypeEnum::emit_def(ostream&out, perm_string name) const for (size_t idx = 1 ; idx < names_.size() ; idx += 1) out << ", \\" << names_[idx] << " "; - out << "} \\" << name << " "; + out << "}"; + emit_name(out, name); return errors; } @@ -172,7 +169,7 @@ int VTypePrimitive::emit_def(ostream&out, perm_string name) const { int errors = 0; errors += emit_primitive_type(out); - out << " \\" << name << " "; + emit_name(out, name); return errors; } @@ -197,7 +194,8 @@ int VTypeRecord::emit_def(ostream&out, perm_string name) const out << " \\" << element_name << " ; "; } - out << "} \\ " << name << " "; + out << "}"; + emit_name(out, name); return errors; } @@ -209,7 +207,7 @@ int VTypeRecord::emit_def(ostream&out, perm_string name) const int VTypeDef::emit_def(ostream&out, perm_string) const { int errors = 0; - out << "\\" << name_ << " "; + emit_name(out, name_); return errors; } @@ -222,7 +220,6 @@ int VTypeDef::emit_decl(ostream&out, perm_string name, bool reg_flag) const out << "wire "; errors += type_->emit_def(out, name); - out << " \\" << name << " "; return errors; } From 0f728b9150bc33987dcac4f4aae66b4028336429 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 25 Aug 2014 17:29:35 +0200 Subject: [PATCH 19/19] vhdlpp: Minor cleaning, fixed copyright notices. --- vhdlpp/library.cc | 9 --------- vhdlpp/parse_misc.h | 3 --- vhdlpp/vsignal.cc | 1 + vhdlpp/vtype.h | 2 +- vhdlpp/vtype_emit.cc | 2 +- 5 files changed, 3 insertions(+), 14 deletions(-) diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index 08a67d586..214d42162 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -383,15 +383,6 @@ bool is_global_type(perm_string name) return false; } -bool can_be_packed(perm_string name) -{ - if (name == "boolean") return true; - if (name == "bit") return true; - if (name == "std_logic") return true; - if (name == "bit_vector") return true; - return true; -} - void library_set_work_path(const char*path) { assert(library_work_path == 0); diff --git a/vhdlpp/parse_misc.h b/vhdlpp/parse_misc.h index a2e6292c9..e4aa9e644 100644 --- a/vhdlpp/parse_misc.h +++ b/vhdlpp/parse_misc.h @@ -67,7 +67,4 @@ extern void generate_global_types(ActiveScope*res); extern bool is_global_type(perm_string type_name); -// Returns true if a type can be used as the base type in Verilog packed array. -extern bool can_be_packed(perm_string type_name); - #endif /* IVL_parse_misc_H */ diff --git a/vhdlpp/vsignal.cc b/vhdlpp/vsignal.cc index 0c4a9cce4..d03dae459 100644 --- a/vhdlpp/vsignal.cc +++ b/vhdlpp/vsignal.cc @@ -1,5 +1,6 @@ /* * Copyright (c) 2011 Stephen Williams (steve@icarus.com) + * Copyright CERN 2014 / 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 diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index a52e7d377..0fce73145 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -2,7 +2,7 @@ #define IVL_vtype_H /* * Copyright (c) 2011-2014 Stephen Williams (steve@icarus.com) - * Copyright CERN 2013 / Stephen Williams (steve@icarus.com), + * Copyright CERN 2014 / Stephen Williams (steve@icarus.com), * Maciej Suminski (maciej.suminski@cern.ch) * * This source code is free software; you can redistribute it diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index 473107245..f932cb8e1 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -21,7 +21,7 @@ # include "vtype.h" # include "expression.h" -# include +# include # include # include