From cdf18de10e442b44eeb1b238635de3c0019bba33 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 5 Feb 2015 16:20:49 +0100 Subject: [PATCH 01/15] vhdlpp: Make integer expressions sized during the emission step. --- vhdlpp/expression_emit.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index bf5d47e92..4c65f340e 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -625,7 +625,7 @@ int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope) int ExpInteger::emit(ostream&out, Entity*, ScopeBase*) { - out << value_; + out << "32'd" << value_; return 0; } From 46c41f9be236a6a9bdcd14681df91256c1796a05 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 5 Feb 2015 17:17:33 +0100 Subject: [PATCH 02/15] ivl: Enum type can be used in port declarations. --- pform.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pform.cc b/pform.cc index c0ad24fd9..5fc2645ce 100644 --- a/pform.cc +++ b/pform.cc @@ -2354,6 +2354,11 @@ void pform_module_define_port(const struct vlltype&li, signed_flag = false; prange = 0; + } else if (enum_type_t*enum_type = dynamic_cast(vtype)) { + data_type = enum_type->base_type; + signed_flag = enum_type->signed_flag; + prange = enum_type->range.get(); + } else if (vtype) { VLerror(li, "sorry: Given type %s not supported here (%s:%d).", typeid(*vtype).name(), __FILE__, __LINE__); From fc0728ab6f9f635ab6e9bc1123a446ca7d9e353c Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 5 Feb 2015 17:41:22 +0100 Subject: [PATCH 03/15] vhdlpp: Forward typedefs. It was required to make it possible to use typedefs in port types. Types from packages are emitted in `ifdef..`endif instead of package..endpackage. The purest solution is to keep package..endpackage and emit appropriate prefix. Also, it would be great to have constants emitted in the same way. --- vhdlpp/architec_emit.cc | 10 +++++----- vhdlpp/package_emit.cc | 29 +++++++++++++++-------------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index c344564e0..93b9fe2b9 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -70,12 +70,12 @@ int Architecture::emit(ostream&out, Entity*entity) // of the full definition. typedef_context_t typedef_ctx; - for (map::iterator cur = use_types_.begin() - ; cur != use_types_.end() ; ++cur) { + //for (map::iterator cur = use_types_.begin() + //; cur != use_types_.end() ; ++cur) { - if(const VTypeDef*def = dynamic_cast(cur->second)) - errors += def->emit_typedef(out, typedef_ctx); - } + //if(const VTypeDef*def = dynamic_cast(cur->second)) + //errors += def->emit_typedef(out, typedef_ctx); + //} for (map::iterator cur = cur_types_.begin() ; cur != cur_types_.end() ; ++cur) { diff --git a/vhdlpp/package_emit.cc b/vhdlpp/package_emit.cc index 42ce821a9..d8db4494d 100644 --- a/vhdlpp/package_emit.cc +++ b/vhdlpp/package_emit.cc @@ -32,26 +32,22 @@ int Package::emit_package(ostream&fd) const if (cur_types_.empty() && cur_constants_.empty() && cur_subprograms_.empty()) return 0; - // If this package was imported from a library, then do not - // emit it again. - if (from_library_.str() != 0) { - fd << "/* Suppress package " << name() - << " from library " << from_library_ << " */" << endl; - return 0; - } - int errors = 0; - fd << "package \\" << name() << " ;" << endl; + fd << "`ifndef package_" << name() << endl; + fd << "`define package_" << name() << endl; // Only emit types that were defined within this package. Skip // the types that were imported from elsewhere. + typedef_context_t typedef_ctx; for (map::const_iterator cur = cur_types_.begin() ; cur != cur_types_.end() ; ++ cur) { - fd << "typedef "; - errors += cur->second->emit_def(fd, - dynamic_cast(cur->second) ? empty_perm_string : cur->first); - fd << " ;" << endl; + if(const VTypeDef*def = dynamic_cast(cur->second)) + errors += def->emit_typedef(fd, typedef_ctx); + //fd << "typedef "; + //errors += cur->second->emit_def(fd, + //dynamic_cast(cur->second) ? empty_perm_string : cur->first); + //fd << " ;" << endl; } //for (map::const_iterator cur = use_constants_.begin() @@ -67,14 +63,19 @@ int Package::emit_package(ostream&fd) const //fd << ";" << endl; //} + fd << "package \\" << name() << " ;" << endl; for (map::const_iterator cur = cur_subprograms_.begin() ; cur != cur_subprograms_.end() ; ++ cur) { // Do not emit unbounded functions, we will just need fixed instances later if(!cur->second->unbounded()) errors += cur->second->emit_package(fd); + else + fd << "/* function " << cur->second->name() << + " has to be instantiated, skipping */" << endl; } - fd << "endpackage" << endl; + fd << "endpackage /* " << name() << " */" << endl; + fd << "`endif" << endl; return errors; } From 12b4914b636b8ed4454c8f69cf429f9f2ec90f43 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 6 Feb 2015 10:44:22 +0100 Subject: [PATCH 04/15] vhdlpp: ExpName resolves enum values. --- vhdlpp/expression_elaborate.cc | 4 ++++ vhdlpp/parse.y | 3 +++ vhdlpp/scope.cc | 15 +++++++++++++++ vhdlpp/scope.h | 6 ++++++ vhdlpp/vtype.cc | 6 ++++++ vhdlpp/vtype.h | 3 +++ 6 files changed, 37 insertions(+) diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index d16f63db4..8471407e7 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -906,6 +906,10 @@ const VType* ExpName::probe_type(Entity*ent, ScopeBase*scope) const if (arc && (gtype = arc->probe_genvar_type(name_))) { return gtype; } + + if (scope->is_enum_name(name_)) { + return &primitive_INTEGER; + } } cerr << get_fileline() << ": error: Signal/variable " << name_ diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index a509d8fa6..464624a44 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -2393,6 +2393,9 @@ type_declaration tmp->set_definition($4); active_scope->incomplete_types.erase(cur); } + if(const VTypeEnum*enum_type = dynamic_cast($4)) { + active_scope->use_enum(enum_type); + } } delete[]$2; } diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index eac3ece1e..2ce681697 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -59,6 +59,8 @@ ScopeBase::ScopeBase(const ActiveScope&ref) use_subprograms_ = ref.use_subprograms_; cur_subprograms_ = ref.cur_subprograms_; + use_enums_ = ref.use_enums_; + // This constructor is invoked when the parser is finished with // an active scope and is making the actual scope. At this point // we know that "this" is the parent scope for the subprograms, @@ -181,6 +183,17 @@ Subprogram* ScopeBase::find_subprogram(perm_string name) const return 0; } +bool ScopeBase::is_enum_name(perm_string name) const +{ + for(list::const_iterator it = use_enums_.begin(); + it != use_enums_.end(); ++it) { + if((*it)->has_name(name)) + return true; + } + + return false; +} + /* * This method is only used by the ActiveScope derived class to import * definition from another scope. @@ -219,6 +232,8 @@ void ScopeBase::do_use_from(const ScopeBase*that) ; cur != that->cur_constants_.end() ; ++ cur) { use_constants_[cur->first] = cur->second; } + + use_enums_ = that->use_enums_; } void ScopeBase::transfer_from(ScopeBase&ref) diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index 6bb7ed4e5..ea4c55d64 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -58,6 +58,7 @@ class ScopeBase { Variable* find_variable(perm_string by_name) const; virtual const InterfacePort* find_param(perm_string by_name) const; Subprogram* find_subprogram(perm_string by_name) const; + bool is_enum_name(perm_string name) const; // Moves all signals, variables and components from another scope to // this one. After the transfer new_* maps are emptied in the another scope. void transfer_from(ScopeBase&ref); @@ -114,6 +115,8 @@ class ScopeBase { std::map use_subprograms_; //imported std::map cur_subprograms_; //current + std::list use_enums_; + void do_use_from(const ScopeBase*that); }; @@ -199,6 +202,9 @@ class ActiveScope : public ScopeBase { cur_types_[name] = t; } + inline void use_enum(const VTypeEnum* t) + { use_enums_.push_back(t); } + inline void use_name(perm_string name, const VType* t) { use_types_[name] = t; } diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index 4a05d82aa..efda4d1a1 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -23,6 +23,7 @@ # include # include # include +# include using namespace std; @@ -251,6 +252,11 @@ void VTypeEnum::show(ostream&out) const out << ")"; } +bool VTypeEnum::has_name(perm_string name) const +{ + return std::find(names_.begin(), names_.end(), name) != names_.end(); +} + VTypeRecord::VTypeRecord(std::list*elements) : elements_(elements->size()) { diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 595ca381c..562ebb155 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -295,6 +295,9 @@ class VTypeEnum : public VType { void show(std::ostream&) const; int emit_def(std::ostream&out, perm_string name) const; + // Checks if the name is stored in the enum. + bool has_name(perm_string name) const; + private: std::vectornames_; }; From 49b6ddf93c2403e0443d380a45a8327cbde1a941 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 9 Feb 2015 15:36:40 +0100 Subject: [PATCH 05/15] vhdlpp: Signal/variable assignments can have labels. --- vhdlpp/parse.y | 62 ++++++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 22 deletions(-) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 464624a44..7cb62d0dd 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -314,7 +314,7 @@ static void touchup_interface_for_functions(std::list*ports) %type concurrent_statement component_instantiation_statement %type concurrent_conditional_signal_assignment -%type concurrent_signal_assignment_statement +%type concurrent_signal_assignment_statement concurrent_simple_signal_assignment %type for_generate_statement generate_statement if_generate_statement %type process_statement %type architecture_statement_part generate_statement_body @@ -348,14 +348,14 @@ static void touchup_interface_for_functions(std::list*ports) %type architecture_body_start package_declaration_start %type package_body_start -%type identifier_opt identifier_colon_opt logical_name suffix +%type identifier_opt identifier_colon_opt logical_name suffix instantiated_unit %type logical_name_list identifier_list %type enumeration_literal_list enumeration_literal %type if_statement_else sequence_of_statements subprogram_statement_part -%type sequential_statement if_statement signal_assignment_statement +%type sequential_statement if_statement signal_assignment signal_assignment_statement %type case_statement procedure_call procedure_call_statement -%type loop_statement variable_assignment_statement +%type loop_statement variable_assignment variable_assignment_statement %type return_statement %type range @@ -677,22 +677,27 @@ component_declaration } ; +instantiated_unit + : IDENTIFIER + | K_component IDENTIFIER { $$ = $2; } + ; + component_instantiation_statement - : IDENTIFIER ':' K_component_opt IDENTIFIER generic_map_aspect_opt port_map_aspect_opt ';' + : IDENTIFIER ':' instantiated_unit generic_map_aspect_opt port_map_aspect_opt ';' { perm_string iname = lex_strings.make($1); - perm_string cname = lex_strings.make($4); - ComponentInstantiation*tmp = new ComponentInstantiation(iname, cname, $5, $6); + perm_string cname = lex_strings.make($3); + ComponentInstantiation*tmp = new ComponentInstantiation(iname, cname, $4, $5); + delete $4; delete $5; - delete $6; FILE_NAME(tmp, @1); delete[]$1; - delete[]$4; + delete[]$3; $$ = tmp; } - | IDENTIFIER ':' K_component_opt IDENTIFIER error ';' + | IDENTIFIER ':' instantiated_unit error ';' { errormsg(@4, "Errors in component instantiation.\n"); delete[]$1; - delete[]$4; + delete[]$3; $$ = 0; } ; @@ -726,7 +731,6 @@ composite_type_definition { $$ = $1; } ; - /* The when...else..when...else syntax is not a general expression in VHDL but a specific sort of assignment statement model. We create Exppression objects for it, but the parser will only @@ -763,6 +767,17 @@ concurrent_conditional_signal_assignment /* IEEE 1076-2008 P11.6 */ } ; +concurrent_simple_signal_assignment + : name LEQ waveform ';' + { ExpName*name = dynamic_cast ($1); + assert(name); + SignalAssignment*tmp = new SignalAssignment(name, *$3); + FILE_NAME(tmp, @1); + + $$ = tmp; + delete $3; + } + else_when_waveforms : else_when_waveforms else_when_waveform { list*tmp = $1; @@ -790,18 +805,14 @@ else_when_waveform ; concurrent_signal_assignment_statement /* IEEE 1076-2008 P11.6 */ - : name LEQ waveform ';' - { ExpName*name = dynamic_cast ($1); - assert(name); - SignalAssignment*tmp = new SignalAssignment(name, *$3); - FILE_NAME(tmp, @1); + : concurrent_simple_signal_assignment - $$ = tmp; - delete $3; - } + | IDENTIFIER ':' concurrent_simple_signal_assignment { $$ = $3; } | concurrent_conditional_signal_assignment + | IDENTIFIER ':' concurrent_conditional_signal_assignment { $$ = $3; } + | name LEQ error ';' { errormsg(@2, "Syntax error in signal assignment waveform.\n"); delete $1; @@ -2206,7 +2217,7 @@ simple_expression_terms } ; -signal_assignment_statement +signal_assignment : name LEQ waveform ';' { SignalSeqAssignment*tmp = new SignalSeqAssignment($1, $3); FILE_NAME(tmp, @1); @@ -2221,6 +2232,10 @@ signal_assignment_statement } ; +signal_assignment_statement + : signal_assignment + | IDENTIFIER ':' signal_assignment { $$ = $3; } + subprogram_body_start : subprogram_specification K_is { assert(!active_sub); @@ -2452,6 +2467,10 @@ use_clauses_opt ; variable_assignment_statement /* IEEE 1076-2008 P10.6.1 */ + : variable_assignment + | IDENTIFIER ':' variable_assignment { $$ = $3; } + +variable_assignment : name VASSIGN expression ';' { VariableSeqAssignment*tmp = new VariableSeqAssignment($1, $3); FILE_NAME(tmp, @1); @@ -2518,7 +2537,6 @@ waveform_element /* Some keywords are optional in some contexts. In all such cases, a similar rule is used, as described here. */ K_architecture_opt : K_architecture | ; -K_component_opt : K_component | ; K_configuration_opt: K_configuration| ; K_entity_opt : K_entity | ; K_is_opt : K_is | ; From 763c6fe3c95ac350ada1714e71665b177fac6097 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 10 Feb 2015 14:11:56 +0100 Subject: [PATCH 06/15] vhdlpp: Support for shift operators (SRL, SRR, SRA, SLA). To be done: ROR & ROL. --- vhdlpp/expression.cc | 5 +++++ vhdlpp/expression.h | 21 ++++++++++++++++++++ vhdlpp/expression_debug.cc | 30 ++++++++++++++++++++++++++++ vhdlpp/expression_elaborate.cc | 13 ++++++++++++ vhdlpp/expression_emit.cc | 30 ++++++++++++++++++++++++++++ vhdlpp/expression_evaluate.cc | 34 ++++++++++++++++++++++++++++++++ vhdlpp/expression_stream.cc | 33 +++++++++++++++++++++++++++++++ vhdlpp/parse.y | 36 +++++++++++++++++++++++++++++++++- 8 files changed, 201 insertions(+), 1 deletion(-) diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index e8c71ee12..42991461d 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -494,6 +494,11 @@ ExpRelation::~ExpRelation() { } +ExpShift::ExpShift(ExpShift::shift_t op, Expression*op1, Expression*op2) +: ExpBinary(op1, op2), shift_(op) +{ +} + ExpString::ExpString(const char* value) : value_(strlen(value)) { diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 058533f86..422f1167c 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -692,6 +692,27 @@ class ExpRelation : public ExpBinary { fun_t fun_; }; +class ExpShift : public ExpBinary { + public: + enum shift_t { SRL, SLL, SRA, SLA, ROL, ROR }; + + public: + ExpShift(ExpShift::shift_t op, Expression*op1, Expression*op2); + + Expression*clone() const { + return new ExpShift(shift_, peek_operand1()->clone(), peek_operand2()->clone()); + } + + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); + void write_to_stream(std::ostream&fd) const; + int emit(ostream&out, Entity*ent, ScopeBase*scope); + virtual bool evaluate(ScopeBase*scope, int64_t&val) const; + void dump(ostream&out, int indent = 0) const; + + private: + shift_t shift_; +}; + class ExpString : public Expression { public: diff --git a/vhdlpp/expression_debug.cc b/vhdlpp/expression_debug.cc index deeb3099e..1a7b44e8c 100644 --- a/vhdlpp/expression_debug.cc +++ b/vhdlpp/expression_debug.cc @@ -82,3 +82,33 @@ void ExpNew::dump(ostream&out, int indent) const out << "New dynamic array size: "; size_->dump(out, indent); } + +void ExpShift::dump(ostream&out, int indent) const +{ + const char*fun_name = "?"; + switch (shift_) { + case SRL: + fun_name = "srl"; + break; + case SLL: + fun_name = "sll"; + break; + case SLA: + fun_name = "sla"; + break; + case SRA: + fun_name = "sra"; + break; + case ROR: + fun_name = "ror"; + break; + case ROL: + fun_name = "rol"; + break; + } + + out << setw(indent) << "" << "Shift " << fun_name + << " at " << get_fileline() << endl; + dump_operands(out, indent+4); +} + diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 8471407e7..c5c67e9e6 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -961,6 +961,19 @@ int ExpRelation::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) return errors; } +int ExpShift::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) +{ + int errors = 0; + + if (ltype == 0) { + ltype = probe_type(ent, scope); + } + + ivl_assert(*this, ltype != 0); + errors += elaborate_exprs(ent, scope, ltype); + return errors; +} + /* * When a string appears in a concatenation, then the type of the * string is an array with the same element type of the concatenation, diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 4c65f340e..eadf3cc0f 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -766,6 +766,36 @@ int ExpRelation::emit(ostream&out, Entity*ent, ScopeBase*scope) return errors; } +int ExpShift::emit(ostream&out, Entity*ent, ScopeBase*scope) +{ + int errors = 0; + + errors += emit_operand1(out, ent, scope); + + switch (shift_) { + case SRL: + out << " >> "; + break; + case SLL: + out << " << "; + break; + case SRA: + out << " >>> "; + break; + case SLA: + out << " <<< "; + break; + case ROR: + case ROL: + out << " /* ?ror/rol? */ "; + break; + } + + errors += emit_operand2(out, ent, scope); + + return errors; +} + bool ExpString::is_primary(void) const { return true; diff --git a/vhdlpp/expression_evaluate.cc b/vhdlpp/expression_evaluate.cc index d53c707f3..8280c08e7 100644 --- a/vhdlpp/expression_evaluate.cc +++ b/vhdlpp/expression_evaluate.cc @@ -216,3 +216,37 @@ bool ExpName::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const return evaluate(scope, val); } + +bool ExpShift::evaluate(ScopeBase*scope, int64_t&val) const +{ + int64_t val1, val2; + bool rc; + + rc = eval_operand1(scope, val1); + if (rc == false) + return false; + + rc = eval_operand2(scope, val2); + if (rc == false) + return false; + + switch (shift_) { + case SRL: + val = (uint64_t)val1 >> (uint64_t)val2; + break; + case SLL: + val = (uint64_t)val1 << (uint64_t)val2; + break; + case SRA: + val = (int64_t)val1 >> (int64_t)val2; + break; + case SLA: + val = (int64_t)val1 << (int64_t)val2; + break; + case ROR: + case ROL: + return false; + } + + return true; +} diff --git a/vhdlpp/expression_stream.cc b/vhdlpp/expression_stream.cc index 5c682a5cd..c379795bf 100644 --- a/vhdlpp/expression_stream.cc +++ b/vhdlpp/expression_stream.cc @@ -236,6 +236,39 @@ void ExpRelation::write_to_stream(ostream&fd) const peek_operand2()->write_to_stream(fd); } +void ExpShift::write_to_stream(ostream&out) const +{ + out << "("; + write_to_stream_operand1(out); + out << ")"; + + switch (shift_) { + case SRL: + out << "srl"; + break; + case SLL: + out << "sll"; + break; + case SLA: + out << "sla"; + break; + case SRA: + out << "sra"; + break; + case ROR: + out << "ror"; + break; + case ROL: + out << "rol"; + break; + } + + out << "("; + write_to_stream_operand2(out); + out << ")"; +} + + void ExpString::write_to_stream(ostream&fd) const { fd << "\""; diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 7cb62d0dd..f824f3bad 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -2139,7 +2139,41 @@ sequential_statement } ; -shift_expression : simple_expression { $$ = $1; } ; +shift_expression + : simple_expression + | simple_expression K_srl simple_expression + { ExpShift*tmp = new ExpShift(ExpShift::SRL, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } + | simple_expression K_sll simple_expression + { ExpShift*tmp = new ExpShift(ExpShift::SLL, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } + | simple_expression K_sra simple_expression + { ExpShift*tmp = new ExpShift(ExpShift::SRA, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } + | simple_expression K_sla simple_expression + { ExpShift*tmp = new ExpShift(ExpShift::SLA, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } + | simple_expression K_ror simple_expression + { sorrymsg(@2, "ROR is not supported.\n"); + ExpShift*tmp = new ExpShift(ExpShift::ROR, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } + | simple_expression K_rol simple_expression + { sorrymsg(@2, "ROL is not supported.\n"); + ExpShift*tmp = new ExpShift(ExpShift::ROL, $1, $3); + FILE_NAME(tmp, @2); + $$ = tmp; + } + ; sign : '+' From f51c037432b2eadff4415d10da2d22b3267d6831 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 11 Feb 2015 11:44:08 +0100 Subject: [PATCH 07/15] vhdlpp: Generics from external packages are accepted (warning instead of error). --- vhdlpp/architec_elaborate.cc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index 62a368813..7161bd93e 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -98,9 +98,8 @@ int ComponentInstantiation::elaborate(Entity*ent, Architecture*arc) // exists in the component declaration const InterfacePort*iparm = base->find_generic(cur->first); if (iparm == 0) { - cerr << get_fileline() << ": error: No generic " << cur->first + cerr << get_fileline() << ": warning: No generic " << cur->first << " in component " << cname_ << "." << endl; - errors += 1; continue; } From 0046e9eca08de0b9a75fd67d5ab79c686a7c99da Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 16 Feb 2015 12:06:33 +0100 Subject: [PATCH 08/15] vhdlpp: ActiveScope::is_vector_name() checks also for constants. --- vhdlpp/scope.cc | 7 ++++++- vhdlpp/scope.h | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index 2ce681697..a617e0778 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -104,7 +104,7 @@ const VType*ScopeBase::find_type(perm_string by_name) return cur->second; } -bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*&exp) +bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const { map::const_iterator cur = cur_constants_.find(by_name); if (cur == cur_constants_.end()) { @@ -281,6 +281,11 @@ bool ActiveScope::is_vector_name(perm_string name) const if (find_variable(name)) return true; + const VType*dummy_type; + Expression*dummy_exp; + if (find_constant(name, dummy_type, dummy_exp)) + return true; + if (context_entity_ && context_entity_->find_port(name)) return true; diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index ea4c55d64..5f1d4c33a 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -53,7 +53,7 @@ class ScopeBase { virtual ~ScopeBase() =0; const VType* find_type(perm_string by_name); - bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp); + bool find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const; Signal* find_signal(perm_string by_name) const; Variable* find_variable(perm_string by_name) const; virtual const InterfacePort* find_param(perm_string by_name) const; From ee840391d659e29bdcbd1d74c7658cadd4132346 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 16 Feb 2015 17:53:18 +0100 Subject: [PATCH 09/15] vhdlpp: std_logic_vector, signed & unsigned are considered global types. --- vhdlpp/library.cc | 3 +++ vhdlpp/package.cc | 8 -------- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index 1eb5fc54f..d906f58dc 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -417,10 +417,13 @@ bool is_global_type(perm_string name) if (name == "integer") return true; if (name == "real") return true; if (name == "std_logic") return true; + if (name == "std_logic_vector") return true; if (name == "character") return true; if (name == "bit_vector") return true; if (name == "string") return true; if (name == "natural") return true; + if (name == "signed") return true; + if (name == "unsigned") return true; return false; } diff --git a/vhdlpp/package.cc b/vhdlpp/package.cc index 240eb37a1..df8f60c41 100644 --- a/vhdlpp/package.cc +++ b/vhdlpp/package.cc @@ -73,12 +73,6 @@ void Package::write_to_stream(ostream&fd) const // Do not include global types in types dump if (is_global_type(cur->first)) continue; - if (cur->first == "std_logic_vector") - continue; - if (cur->first == "signed") - continue; - if (cur->first == "unsigned") - continue; fd << "type " << cur->first << " is "; cur->second->write_type_to_stream(fd); @@ -90,8 +84,6 @@ void Package::write_to_stream(ostream&fd) const // Do not include global types in types dump if (is_global_type(cur->first)) continue; - if (cur->first == "std_logic_vector") - continue; fd << "type " << cur->first << " is "; cur->second->write_type_to_stream(fd); From e569e07d4ee6abdffbbbfa7116586c9308651b5b Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 17 Feb 2015 14:58:33 +0100 Subject: [PATCH 10/15] vhdlpp: Type 'NATURAL' is translated to 'int unsigned'. --- vhdlpp/expression_elaborate.cc | 2 +- vhdlpp/library.cc | 3 +-- vhdlpp/vtype.cc | 5 ++++- vhdlpp/vtype.h | 3 ++- vhdlpp/vtype_emit.cc | 3 +++ vhdlpp/vtype_stream.cc | 3 +++ 6 files changed, 14 insertions(+), 5 deletions(-) diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index c5c67e9e6..19c79b591 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -570,7 +570,7 @@ const VType* ExpAttribute::probe_type(Entity*ent, ScopeBase*scope) const base_->probe_type(ent, scope); if (name_ == "length" || name_ == "left" || name_ == "right") { - return &primitive_INTEGER; + return &primitive_NATURAL; } return 0; diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index d906f58dc..61ae426df 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -387,12 +387,11 @@ static void import_std_use(const YYLTYPE&loc, ActiveScope*/*res*/, perm_string p const VTypePrimitive primitive_BOOLEAN(VTypePrimitive::BOOLEAN, true); const VTypePrimitive primitive_BIT(VTypePrimitive::BIT, true); const VTypePrimitive primitive_INTEGER(VTypePrimitive::INTEGER); +const VTypePrimitive primitive_NATURAL(VTypePrimitive::NATURAL); const VTypePrimitive primitive_REAL(VTypePrimitive::REAL); const VTypePrimitive primitive_STDLOGIC(VTypePrimitive::STDLOGIC, true); const VTypePrimitive primitive_CHARACTER(VTypePrimitive::CHARACTER); -const VTypeRange primitive_NATURAL(&primitive_INTEGER, INT64_MAX, 0); - static const VTypeArray primitive_BIT_VECTOR(&primitive_BIT, vector (1)); static const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector (1)); static const VTypeArray primitive_STRING(&primitive_CHARACTER, vector (1)); diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index efda4d1a1..9acfcacee 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -67,11 +67,14 @@ void VTypePrimitive::show(ostream&out) const case INTEGER: out << "INTEGER"; break; + case NATURAL: + out << "NATURAL"; + break; case REAL: out << "REAL"; break; case STDLOGIC: - out << "std_logic"; + out << "STD_LOGIC"; break; } } diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 562ebb155..c5cdff9a4 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -151,7 +151,7 @@ class VTypeERROR : public VType { class VTypePrimitive : public VType { public: - enum type_t { BOOLEAN, BIT, INTEGER, REAL, STDLOGIC, CHARACTER }; + enum type_t { BOOLEAN, BIT, INTEGER, NATURAL, REAL, STDLOGIC, CHARACTER }; public: VTypePrimitive(type_t tt, bool packed = false); @@ -177,6 +177,7 @@ class VTypePrimitive : public VType { extern const VTypePrimitive primitive_BOOLEAN; extern const VTypePrimitive primitive_BIT; extern const VTypePrimitive primitive_INTEGER; +extern const VTypePrimitive primitive_NATURAL; extern const VTypePrimitive primitive_REAL; extern const VTypePrimitive primitive_STDLOGIC; extern const VTypePrimitive primitive_CHARACTER; diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index 7675568f9..e64e18aa5 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -154,6 +154,9 @@ int VTypePrimitive::emit_primitive_type(ostream&out) const case STDLOGIC: out << "logic"; break; + case NATURAL: + out << "int unsigned"; + break; case INTEGER: out << "int"; break; diff --git a/vhdlpp/vtype_stream.cc b/vhdlpp/vtype_stream.cc index 3e4572049..6d24b6d74 100644 --- a/vhdlpp/vtype_stream.cc +++ b/vhdlpp/vtype_stream.cc @@ -140,6 +140,9 @@ void VTypePrimitive::write_to_stream(ostream&fd) const case INTEGER: fd << "integer"; break; + case NATURAL: + fd << "natural"; + break; case REAL: fd << "real"; break; From a1a4f47894cbcc77c2d18e6104e650b1ac0ee9fc Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 17 Feb 2015 15:04:50 +0100 Subject: [PATCH 11/15] vhdlpp: Unnecessary comment. --- vhdlpp/architec_elaborate.cc | 2 -- 1 file changed, 2 deletions(-) diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index 7161bd93e..9bade14e8 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -370,8 +370,6 @@ int SignalAssignment::elaborate(Entity*ent, Architecture*arc) for (list::iterator cur = rval_.begin() ; cur != rval_.end() ; ++cur) { (*cur)->elaborate_expr(ent, arc, lval_type); - - // Handle functions that return unbounded arrays } return errors; From 5884879b0214cf8995fd6b7c1481031c999a2bfc Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Tue, 17 Feb 2015 15:07:05 +0100 Subject: [PATCH 12/15] vhdlpp: to_integer() function. --- vhdlpp/expression_emit.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index eadf3cc0f..5689e29c1 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -552,7 +552,12 @@ int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; - if (name_ == "unsigned" && argv_.size()==1) { + // SystemVerilog takes care of signs, depending on the lvalue + if (name_ == "to_integer" && argv_.size()==1) { + errors += argv_[0]->emit(out, ent, scope); + } + + else if (name_ == "unsigned" && argv_.size()==1) { // Handle the special case that this is a cast to // unsigned. This function is brought in as part of the // std numeric library, but we interpret it as the same From cd55f30a279ef5a987397f263d03edf00abaae3d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 19 Feb 2015 17:01:14 +0100 Subject: [PATCH 13/15] vhdlpp: Minor change to ScopeBase::find_constant(). --- vhdlpp/scope.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index a617e0778..49f8775f7 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -106,6 +106,9 @@ const VType*ScopeBase::find_type(perm_string by_name) bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression*&exp) const { + typ = NULL; + exp = NULL; + map::const_iterator cur = cur_constants_.find(by_name); if (cur == cur_constants_.end()) { cur = use_constants_.find(by_name); @@ -121,6 +124,8 @@ bool ScopeBase::find_constant(perm_string by_name, const VType*&typ, Expression* exp = cur->second->val; return true; } + + return false; } Signal* ScopeBase::find_signal(perm_string by_name) const From 0f0bef32f24463afea6d8f987f2c5fa9823e6377 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 19 Feb 2015 17:01:32 +0100 Subject: [PATCH 14/15] vhdlpp: Architecture elaboration counts errors coming from expression elaboration. --- vhdlpp/architec_elaborate.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index 9bade14e8..bdbd206dd 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -369,7 +369,7 @@ int SignalAssignment::elaborate(Entity*ent, Architecture*arc) for (list::iterator cur = rval_.begin() ; cur != rval_.end() ; ++cur) { - (*cur)->elaborate_expr(ent, arc, lval_type); + errors += (*cur)->elaborate_expr(ent, arc, lval_type); } return errors; From 9ca754b6db20030965b899bcbfa9a81c26bfce77 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 19 Feb 2015 17:04:04 +0100 Subject: [PATCH 15/15] vhdlpp: Support for accessing words in constant arrays. --- vhdlpp/expression_elaborate.cc | 76 +++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 1 deletion(-) diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 19c79b591..a2cdbe3aa 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -922,13 +922,87 @@ const VType* ExpName::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*)co return probe_type(ent, scope); } -int ExpName::elaborate_expr(Entity*, ScopeBase*, const VType*ltype) +int ExpName::elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype) { + const VType*type = NULL; + Expression*exp = NULL; + if (ltype) { ivl_assert(*this, ltype != 0); set_type(ltype); } + // Currently constant arrays of vectors are flattened to single one-dimensional + // localparams. If the user wants to access a particular word, then it is + // necessary to extract the adequate part of the localparam. + // e.g. + // declarations: + // == VHDL == + // type uns_array is array (natural range <>) of unsigned(7 downto 0); + // constant const_array : uns_array(2 downto 0) := + // (0 => "00110011", 1 => "101010101", 2=> "00001111"); + // == SystemVerilog == + // localparam const_array = { 8'b00110011, 8'b10101010, 8'b00001111 }; + // + // access: + // == VHDL == + // target_var := const_array(1); + // == SystemVerilog == + // target_var = const_array[15:8]; // <- indices adjusted to pick the word + + if(index_ && scope) { + if(!scope->find_constant(name_, type, exp)) + return 0; + + const VTypeArray*arr = dynamic_cast(type); + ivl_assert(*this, arr); // if there is an index, it should be an array, right? + + const VType*element = arr->element_type(); + const VTypeArray*arr_element = dynamic_cast(element); + if(!arr_element) { + // index adjustments are not necessary, it is not an array of vectors + return 0; + } + + ivl_assert(*this, arr_element->dimensions() == 1); + if(arr_element->dimensions() != 1) { + cerr << get_fileline() << ": Sorry, only one-dimensional constant arrays are handled." << endl; + return 1; + } + + int64_t start_val; + bool start_rc = arr_element->dimension(0).msb()->evaluate(ent, scope, start_val); + + int64_t finish_val; + bool finish_rc = arr_element->dimension(0).lsb()->evaluate(ent, scope, finish_val); + + if(!start_rc || !finish_rc) { + cerr << get_fileline() << ": Could not evaluate the word size." << endl; + return 1; + } + + int word_size = abs(start_val - finish_val) + 1; + + ExpInteger*size = new ExpInteger(word_size); + Expression*new_index, *new_lsb; + + // new indices = [index_ * word_size + word_size : lsb_ * word_size] + if(lsb_) { + ExpArithmetic*tmp = new ExpArithmetic(ExpArithmetic::MULT, index_->clone(), size->clone()); + new_index = new ExpArithmetic(ExpArithmetic::PLUS, tmp, size->clone()); + new_lsb = new ExpArithmetic(ExpArithmetic::MULT, lsb_->clone(), size->clone()); + } else { + new_lsb = new ExpArithmetic(ExpArithmetic::MULT, index_->clone(), size->clone()); + new_index = new ExpArithmetic(ExpArithmetic::PLUS, new_lsb->clone(), size->clone()); + } + delete index_; + delete lsb_; + delete size; + + index_ = new_index; + lsb_ = new_lsb; + } + return 0; }