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); 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/expression.h b/vhdlpp/expression.h index 7b54705c6..2cf89b78c 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -638,6 +638,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/expression_emit.cc b/vhdlpp/expression_emit.cc index 8ba1d1120..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; @@ -244,6 +245,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/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; } diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index 7266fcba1..214d42162 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_INTEGER(VTypePrimitive::INTEGER); +const VTypePrimitive primitive_BOOLEAN(VTypePrimitive::BOOLEAN, true); +const VTypePrimitive primitive_BIT(VTypePrimitive::BIT, true); +const VTypePrimitive primitive_INTEGER(VTypePrimitive::INTEGER, true); 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); 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/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/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/vsignal.cc b/vhdlpp/vsignal.cc index 29627f924..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 @@ -33,6 +34,30 @@ 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_); + 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; + } + else { + ExpAggregate*aggr = dynamic_cast(init_expr_); + if(aggr) { + aggr->elaborate_expr(ent, arc, peek_type()); + } + } + } +} + void SigVarBase::type_elaborate_(VType::decl_t&decl) { decl.type = type_; @@ -44,7 +69,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_()); @@ -63,7 +88,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; 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_; } 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..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 @@ -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 @@ -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 @@ -100,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) @@ -115,7 +124,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; }; /* @@ -128,7 +137,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; @@ -137,10 +146,13 @@ 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_; } private: type_t type_; + bool packed_; }; extern const VTypePrimitive primitive_BOOLEAN; @@ -191,8 +203,11 @@ 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(); } private: const VType*etype_; @@ -212,7 +227,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_; @@ -226,7 +241,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_; @@ -259,7 +274,9 @@ 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; + + bool can_be_packed() const { return true; } const element_t* element_by_name(perm_string name) const; @@ -288,7 +305,9 @@ 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; + + bool can_be_packed() const { return type_->can_be_packed(); } 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 d5f8b32da..f932cb8e1 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -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,53 +50,40 @@ 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; - list dims; const VTypeArray*cur = this; while (const VTypeArray*sub = dynamic_cast (cur->etype_)) { - 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); + base->emit_def(out, empty_perm_string); if (signed_flag_) out << " signed"; } else { - raw_base->emit_def(out); + raw_base->emit_def(out, empty_perm_string); } - dims.push_back(cur); - - while (! dims.empty()) { - cur = dims.front(); - dims.pop_front(); - out << "["; - if (cur->dimension(0).msb()) - errors += cur->dimension(0).msb()->emit(out, 0, 0); - else - out << "?error?"; - out << ":"; - if (cur->dimension(0).lsb()) - errors += cur->dimension(0).lsb()->emit(out, 0, 0); - else - out << "?error?"; - out << "]"; + if(raw_base->can_be_packed()) { + errors += emit_dimensions(out); + emit_name(out, name); + } else { + emit_name(out, name); + errors += emit_dimensions(out); } return errors; @@ -109,7 +94,36 @@ 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 VTypeArray::emit_dimensions(std::ostream&out) const +{ + int errors = 0; + + list dims; + const VTypeArray*cur = this; + while (const VTypeArray*sub = dynamic_cast (cur->etype_)) { + dims.push_back(cur); + cur = sub; + } + dims.push_back(cur); + + 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); + } + out << "]"; + } + + return errors; +} + +int VTypeEnum::emit_def(ostream&out, perm_string name) const { int errors = 0; out << "enum {"; @@ -119,6 +133,7 @@ int VTypeEnum::emit_def(ostream&out) const out << ", \\" << names_[idx] << " "; out << "}"; + emit_name(out, name); return errors; } @@ -135,11 +150,11 @@ int VTypePrimitive::emit_primitive_type(ostream&out) const out << "logic"; break; case INTEGER: - out << "bool [31:0]"; + out << "bool[31:0]"; + break; + case REAL: + out << "real"; break; - case REAL: - out << "real"; - break; case CHARACTER: out << "char"; break; @@ -150,22 +165,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); + emit_name(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 {"; @@ -174,11 +190,12 @@ 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 << "}"; + emit_name(out, name); return errors; } @@ -187,10 +204,10 @@ 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_ << " "; + emit_name(out, name_); return errors; } @@ -202,8 +219,7 @@ int VTypeDef::emit_decl(ostream&out, perm_string name, bool reg_flag) const else out << "wire "; - errors += type_->emit_def(out); - out << " \\" << name << " "; + errors += type_->emit_def(out, name); return errors; } @@ -229,8 +245,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; }