From d352d8ead36424ea7093e1890ff7f3d5de6bfe3d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 20 Apr 2015 10:57:49 +0200 Subject: [PATCH 1/7] vhdlpp: Stop compilation on invalid attributes. --- vhdlpp/expression_evaluate.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vhdlpp/expression_evaluate.cc b/vhdlpp/expression_evaluate.cc index 983c0ed6b..b67cbd5da 100644 --- a/vhdlpp/expression_evaluate.cc +++ b/vhdlpp/expression_evaluate.cc @@ -105,9 +105,10 @@ bool ExpAttribute::evaluate(ScopeBase*scope, int64_t&val) const const VTypeArray*arr = dynamic_cast(base_type); if (arr == 0) { - cerr << get_fileline() << ": error: " + cerr << endl << get_fileline() << ": error: " << "Cannot apply the 'length attribute to non-array objects" << endl; + ivl_assert(*this, false); return false; } @@ -145,9 +146,10 @@ bool ExpAttribute::evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const const VTypeArray*arr = dynamic_cast(base_type); if (arr == 0) { - cerr << get_fileline() << ": error: " + cerr << endl << get_fileline() << ": error: " << "Cannot apply the '" << name_ << " attribute to non-array objects" << endl; + ivl_assert(*this, false); return false; } From a5138e238ffc1b8da73e9816ba2bab3141483445 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 20 Apr 2015 22:36:14 +0200 Subject: [PATCH 2/7] vhdlpp: Added missing std_logic values in ExpChar and ExpString::emit(). --- vhdlpp/expression_emit.cc | 81 ++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 39 deletions(-) diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 39e853a71..98b0ebe5c 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -34,6 +34,33 @@ using namespace std; +inline static int emit_logic(char val, ostream& out, const VTypePrimitive::type_t type) +{ +// TODO case 'W': case 'L': case 'H': + + switch (val) { + case '-': case 'U': + val = 'x'; + /* fall through */ + + case 'X': case 'Z': + assert(type == VTypePrimitive::STDLOGIC); + /* fall through */ + + case '0': + case '1': + out << (char) tolower(val); + break; + + default: + assert(false); + out << "x"; + return 1; + } + + return 0; +} + int Expression::emit(ostream&out, Entity*, ScopeBase*) { out << " /* " << get_fileline() << ": internal error: " @@ -396,23 +423,15 @@ int ExpBitstring::emit(ostream&out, Entity*, ScopeBase*) int ExpCharacter::emit_primitive_bit_(ostream&out, Entity*, ScopeBase*, const VTypePrimitive*etype) { - switch (etype->type()) { - case VTypePrimitive::BOOLEAN: - case VTypePrimitive::BIT: - case VTypePrimitive::STDLOGIC: - switch (value_) { - case '0': - case '1': - out << "1'b" << value_; - return 0; - default: - break; - } + out << "1'b"; + int res = emit_logic(value_, out, etype->type()); - default: - return 1; - } - return 1; + if(res) + cerr << get_fileline() << ": internal error: " + << "Don't know how to handle bit " << value_ + << " with etype==" << etype->type() << endl; + + return res; } int ExpCharacter::emit(ostream&out, Entity*ent, ScopeBase*scope) @@ -991,29 +1010,13 @@ int ExpString::emit_as_array_(ostream& out, Entity*, ScopeBase*, const VTypeArra assert(etype->type() != VTypePrimitive::INTEGER); out << value_.size() << "'b"; for (size_t idx = 0 ; idx < value_.size() ; idx += 1) { - switch (value_[idx]) { - case '0': - out << "0"; - break; - case '1': - out << "1"; - break; - case 'z': case 'Z': - assert(etype->type() == VTypePrimitive::STDLOGIC); - out << "z"; - break; - case '-': - assert(etype->type() == VTypePrimitive::STDLOGIC); - out << "x"; - break; - default: - cerr << get_fileline() << ": internal error: " - << "Don't know how to handle bit " << value_[idx] - << " with etype==" << etype->type() << endl; - assert(etype->type() == VTypePrimitive::STDLOGIC); - out << "x"; - break; - } + int res = emit_logic(value_[idx], out, etype->type()); + errors += res; + + if(res) + cerr << get_fileline() << ": internal error: " + << "Don't know how to handle bit " << value_[idx] + << " with etype==" << etype->type() << endl; } return errors; From cfa43c7742191502c73a2940e5c96f7a9a977803 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 22 Apr 2015 18:02:53 +0200 Subject: [PATCH 3/7] vhdlpp: Support for reports & asserts. --- vhdlpp/lexor_keyword.gperf | 4 +++ vhdlpp/parse.y | 51 +++++++++++++++++++++++++--- vhdlpp/sequential.cc | 21 ++++++++++++ vhdlpp/sequential.h | 35 +++++++++++++++++++ vhdlpp/sequential_debug.cc | 15 +++++++++ vhdlpp/sequential_elaborate.cc | 5 +++ vhdlpp/sequential_emit.cc | 61 ++++++++++++++++++++++++++++++++++ 7 files changed, 187 insertions(+), 5 deletions(-) diff --git a/vhdlpp/lexor_keyword.gperf b/vhdlpp/lexor_keyword.gperf index 42fd1bc0d..1b086f147 100644 --- a/vhdlpp/lexor_keyword.gperf +++ b/vhdlpp/lexor_keyword.gperf @@ -45,7 +45,9 @@ else, GN_KEYWORD_2008, K_else elsif, GN_KEYWORD_2008, K_elsif end, GN_KEYWORD_2008, K_end entity, GN_KEYWORD_2008, K_entity +error, GN_KEYWORD_2008, K_error exit, GN_KEYWORD_2008, K_exit +failure, GN_KEYWORD_2008, K_failure fairness, GN_KEYWORD_2008, K_fairness file, GN_KEYWORD_2008, K_file for, GN_KEYWORD_2008, K_for @@ -73,6 +75,7 @@ new, GN_KEYWORD_2008, K_new next, GN_KEYWORD_2008, K_next nor, GN_KEYWORD_2008, K_nor not, GN_KEYWORD_2008, K_not +note, GN_KEYWORD_2008, K_note null, GN_KEYWORD_2008, K_null of, GN_KEYWORD_2008, K_of on, GN_KEYWORD_2008, K_on @@ -124,6 +127,7 @@ vmode, GN_KEYWORD_2008, K_vmode vprop, GN_KEYWORD_2008, K_vprop vunit, GN_KEYWORD_2008, K_vunit wait, GN_KEYWORD_2008, K_wait +warning, GN_KEYWORD_2008, K_warning when, GN_KEYWORD_2008, K_when while, GN_KEYWORD_2008, K_while with, GN_KEYWORD_2008, K_with diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 146f984ac..40121df37 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -260,6 +260,8 @@ static void touchup_interface_for_functions(std::list*ports) Architecture::Statement* arch_statement; std::list* arch_statement_list; + ReportStmt::severity_t severity; + Subprogram*subprogram; }; @@ -269,13 +271,13 @@ static void touchup_interface_for_functions(std::list*ports) %token K_begin K_block K_body K_buffer K_bus %token K_case K_component K_configuration K_constant K_context K_cover %token K_default K_disconnect K_downto -%token K_else K_elsif K_end K_entity K_exit -%token K_fairness K_file K_for K_force K_function +%token K_else K_elsif K_end K_entity K_error K_exit +%token K_failure K_fairness K_file K_for K_force K_function %token K_generate K_generic K_group K_guarded %token K_if K_impure K_in K_inertial K_inout K_is %token K_label K_library K_linkage K_literal K_loop %token K_map K_mod -%token K_nand K_new K_next K_nor K_not K_null +%token K_nand K_new K_next K_nor K_not K_note K_null %token K_of K_on K_open K_or K_others K_out %token K_package K_parameter K_port K_postponed K_procedure K_process %token K_property K_protected K_pure @@ -286,7 +288,7 @@ static void touchup_interface_for_functions(std::list*ports) %token K_then K_to K_transport K_type %token K_unaffected K_units K_until K_use %token K_variable K_vmode K_vprop K_vunit -%token K_wait K_when K_while K_with +%token K_wait K_warning K_when K_while K_with %token K_xnor K_xor /* Identifiers that are not keywords are identifiers. */ %token IDENTIFIER @@ -349,6 +351,7 @@ 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 instantiated_unit + %type logical_name_list identifier_list %type enumeration_literal_list enumeration_literal @@ -356,7 +359,7 @@ static void touchup_interface_for_functions(std::list*ports) %type sequential_statement if_statement signal_assignment signal_assignment_statement %type case_statement procedure_call procedure_call_statement %type loop_statement variable_assignment variable_assignment_statement -%type return_statement +%type assertion_statement report_statement return_statement %type range %type range_list index_constraint @@ -371,6 +374,7 @@ static void touchup_interface_for_functions(std::list*ports) %type else_when_waveforms %type function_specification subprogram_specification subprogram_body_start +%type severity severity_opt %% @@ -433,6 +437,22 @@ architecture_statement_part } ; +assertion_statement + : K_assert expression report_statement + { ReportStmt*report = dynamic_cast($3); + assert(report); + AssertStmt*tmp = new AssertStmt($2, report->message().c_str(), report->severity()); + delete report; + FILE_NAME(tmp,@2); + $$ = tmp; + } + | K_assert expression severity_opt ';' + { AssertStmt*tmp = new AssertStmt($2, NULL, $3); + FILE_NAME(tmp,@2); + $$ = tmp; + } + ; + association_element : IDENTIFIER ARROW expression { named_expr_t*tmp = new named_expr_t(lex_strings.make($1), $3); @@ -2029,6 +2049,14 @@ relation } ; +report_statement + : K_report STRING_LITERAL severity_opt ';' + { ReportStmt*tmp = new ReportStmt($2, $3); + FILE_NAME(tmp,@2); + delete[]$2; + $$ = tmp; + } + return_statement : K_return expression ';' { ReturnStmt*tmp = new ReturnStmt($2); @@ -2136,6 +2164,8 @@ sequential_statement | procedure_call_statement { $$ = $1; } | loop_statement { $$ = $1; } | return_statement { $$ = $1; } + | report_statement { $$ = $1; } + | assertion_statement { $$ = $1; } | K_null ';' { $$ = 0; } | error ';' { errormsg(@1, "Syntax error in sequential statement.\n"); @@ -2144,6 +2174,17 @@ sequential_statement } ; +severity + : K_severity K_note { $$ = ReportStmt::NOTE; } + | K_severity K_warning { $$ = ReportStmt::WARNING; } + | K_severity K_error { $$ = ReportStmt::ERROR; } + | K_severity K_failure { $$ = ReportStmt::FAILURE; } + ; + +severity_opt + : severity { $$ = $1; } + | { $$ = ReportStmt::UNSPECIFIED; } + shift_expression : simple_expression | simple_expression K_srl simple_expression diff --git a/vhdlpp/sequential.cc b/vhdlpp/sequential.cc index f6fe41d0d..95497a987 100644 --- a/vhdlpp/sequential.cc +++ b/vhdlpp/sequential.cc @@ -263,3 +263,24 @@ BasicLoopStatement::BasicLoopStatement(perm_string lname, list* BasicLoopStatement::~BasicLoopStatement() { } + +ReportStmt::ReportStmt(const char*msg, severity_t sev) +: msg_(msg), severity_(sev) +{ + if(sev == ReportStmt::UNSPECIFIED) + severity_ = ReportStmt::NOTE; +} + +AssertStmt::AssertStmt(Expression*condition, const char*msg, ReportStmt::severity_t sev) +: ReportStmt("", sev), cond_(condition) +{ + if(msg == NULL) + msg_ = default_msg_; + else + msg_ = std::string(msg); + + if(sev == ReportStmt::UNSPECIFIED) + severity_ = ReportStmt::ERROR; +} + +const std::string AssertStmt::default_msg_ = std::string("Assertion violation."); diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index c9f039fea..d561b0559 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -273,4 +273,39 @@ class BasicLoopStatement : public LoopStatement { void dump(ostream&out, int indent) const; }; +class ReportStmt : public SequentialStmt { + public: + typedef enum { UNSPECIFIED, NOTE, WARNING, ERROR, FAILURE } severity_t; + + ReportStmt(const char*message, severity_t severity = NOTE); + virtual ~ReportStmt() {} + + void dump(ostream&out, int indent) const; + int emit(ostream&out, Entity*entity, ScopeBase*scope); + void write_to_stream(std::ostream&fd); + + inline const std::string& message() const { return msg_; } + inline severity_t severity() const { return severity_; } + + protected: + std::string msg_; + severity_t severity_; +}; + +class AssertStmt : public ReportStmt { + public: + AssertStmt(Expression*condition, const char*message, ReportStmt::severity_t severity = ReportStmt::ERROR); + + void dump(ostream&out, int indent) const; + int elaborate(Entity*ent, ScopeBase*scope); + int emit(ostream&out, Entity*entity, ScopeBase*scope); + void write_to_stream(std::ostream&fd); + + private: + Expression*cond_; + + // Message displayed when there is no report assigned. + static const std::string default_msg_; +}; + #endif /* IVL_sequential_H */ diff --git a/vhdlpp/sequential_debug.cc b/vhdlpp/sequential_debug.cc index 31f3655d2..786fa5cc6 100644 --- a/vhdlpp/sequential_debug.cc +++ b/vhdlpp/sequential_debug.cc @@ -165,3 +165,18 @@ void BasicLoopStatement::dump(ostream&out, int indent) const out << setw(indent) << "" << "BasicLoopStatement at file=" << get_fileline() << endl; LoopStatement::dump(out, indent+2); } + +void ReportStmt::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "ReportStmt at file=" << get_fileline() << endl; + out << setw(indent+3) << "" << "severity: " << severity_ << endl; + out << setw(indent+3) << "" << "message: " << msg_ << endl; +} + +void AssertStmt::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "AssertStmt at file=" << get_fileline() << endl; + out << setw(indent+3) << "" << "condition: "; + cond_->dump(out, indent+3); + ReportStmt::dump(out, indent+3); +} diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index 29b4e4914..2c342030b 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -192,3 +192,8 @@ int BasicLoopStatement::elaborate(Entity*, ScopeBase*) { return 0; } + +int AssertStmt::elaborate(Entity*ent, ScopeBase*scope) +{ + return cond_->elaborate_expr(ent, scope, 0); +} diff --git a/vhdlpp/sequential_emit.cc b/vhdlpp/sequential_emit.cc index 895d1d839..29f488b80 100644 --- a/vhdlpp/sequential_emit.cc +++ b/vhdlpp/sequential_emit.cc @@ -451,3 +451,64 @@ int ForLoopStatement::emit_runtime_(ostream&out, Entity*ent, ScopeBase*scope) return errors; } + +int ReportStmt::emit(ostream&out, Entity*, ScopeBase*) +{ + out << "$display(\""; + + switch(severity_) + { + case NOTE: out << "** Note: "; break; + case WARNING: out << "** Warning: "; break; + case ERROR: out << "** Error: "; break; + case FAILURE: out << "** Failure: "; break; + case UNSPECIFIED: ivl_assert(*this, false); break; + } + + out << msg_; + out << " (" << get_fileline() << ")\");"; + + if(severity_ == FAILURE) + out << "$finish();"; + + out << std::endl; + + return 0; +} + +void ReportStmt::write_to_stream(std::ostream&fd) +{ + fd << "report \"" << msg_ << "\"" << std::endl; + + fd << "severity "; + switch(severity_) + { + case NOTE: fd << "NOTE"; break; + case WARNING: fd << "WARNING"; break; + case ERROR: fd << "ERROR"; break; + case FAILURE: fd << "FAILURE"; break; + case UNSPECIFIED: break; + } + fd << ";" << std::endl; +} + +int AssertStmt::emit(ostream&out, Entity*ent, ScopeBase*scope) +{ + int errors = 0; + + out << "if(!("; + errors += cond_->emit(out, ent, scope); + out << ")) begin" << std::endl; + errors += ReportStmt::emit(out, ent, scope); + out << "end" << std::endl; + + return errors; +} + +void AssertStmt::write_to_stream(std::ostream&fd) +{ + fd << "assert "; + cond_->write_to_stream(fd); + fd << std::endl; + ReportStmt::write_to_stream(fd); +} From 7c0a1916264d28853faba64133b5d8834599fe08 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 22 Apr 2015 18:03:35 +0200 Subject: [PATCH 4/7] vhdlpp: Handle true/false values. --- vhdlpp/lexor_keyword.gperf | 2 ++ vhdlpp/parse.y | 15 +++++++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/vhdlpp/lexor_keyword.gperf b/vhdlpp/lexor_keyword.gperf index 1b086f147..9ee02c5a9 100644 --- a/vhdlpp/lexor_keyword.gperf +++ b/vhdlpp/lexor_keyword.gperf @@ -49,6 +49,7 @@ error, GN_KEYWORD_2008, K_error exit, GN_KEYWORD_2008, K_exit failure, GN_KEYWORD_2008, K_failure fairness, GN_KEYWORD_2008, K_fairness +false, GN_KEYWORD_2008, K_false file, GN_KEYWORD_2008, K_file for, GN_KEYWORD_2008, K_for force, GN_KEYWORD_2008, K_force @@ -117,6 +118,7 @@ subtype, GN_KEYWORD_2008, K_subtype then, GN_KEYWORD_2008, K_then to, GN_KEYWORD_2008, K_to transport, GN_KEYWORD_2008, K_transport +true, GN_KEYWORD_2008, K_true type, GN_KEYWORD_2008, K_type unaffected, GN_KEYWORD_2008, K_unaffected units, GN_KEYWORD_2008, K_units diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 40121df37..34a352e40 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -272,7 +272,7 @@ static void touchup_interface_for_functions(std::list*ports) %token K_case K_component K_configuration K_constant K_context K_cover %token K_default K_disconnect K_downto %token K_else K_elsif K_end K_entity K_error K_exit -%token K_failure K_fairness K_file K_for K_force K_function +%token K_failure K_fairness K_false K_file K_for K_force K_function %token K_generate K_generic K_group K_guarded %token K_if K_impure K_in K_inertial K_inout K_is %token K_label K_library K_linkage K_literal K_loop @@ -285,7 +285,7 @@ static void touchup_interface_for_functions(std::list*ports) %token K_restrict K_restrict_guarantee K_return K_reverse_range K_rol K_ror %token K_select K_sequence K_severity K_signal K_shared %token K_sla K_sll K_sra K_srl K_strong K_subtype -%token K_then K_to K_transport K_type +%token K_then K_to K_transport K_true K_type %token K_unaffected K_units K_until K_use %token K_variable K_vmode K_vprop K_vunit %token K_wait K_warning K_when K_while K_with @@ -1827,6 +1827,17 @@ primary delete[]$1; $$ = tmp; } + | K_true + { ExpBitstring*tmp = new ExpBitstring("1"); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | K_false + { ExpBitstring*tmp = new ExpBitstring("0"); + FILE_NAME(tmp, @1); + $$ = tmp; + } + /*XXXX Caught up in element_association_list? | '(' expression ')' { $$ = $2; } From bed5ee4529b6f6aaa9943019d641847a4545bac8 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 24 Apr 2015 12:04:41 +0200 Subject: [PATCH 5/7] vhdlpp: Handle 'severity' statements without using keywords. --- vhdlpp/lexor_keyword.gperf | 4 ---- vhdlpp/parse.y | 27 ++++++++++++++++++--------- 2 files changed, 18 insertions(+), 13 deletions(-) diff --git a/vhdlpp/lexor_keyword.gperf b/vhdlpp/lexor_keyword.gperf index 9ee02c5a9..b5faffce4 100644 --- a/vhdlpp/lexor_keyword.gperf +++ b/vhdlpp/lexor_keyword.gperf @@ -45,9 +45,7 @@ else, GN_KEYWORD_2008, K_else elsif, GN_KEYWORD_2008, K_elsif end, GN_KEYWORD_2008, K_end entity, GN_KEYWORD_2008, K_entity -error, GN_KEYWORD_2008, K_error exit, GN_KEYWORD_2008, K_exit -failure, GN_KEYWORD_2008, K_failure fairness, GN_KEYWORD_2008, K_fairness false, GN_KEYWORD_2008, K_false file, GN_KEYWORD_2008, K_file @@ -76,7 +74,6 @@ new, GN_KEYWORD_2008, K_new next, GN_KEYWORD_2008, K_next nor, GN_KEYWORD_2008, K_nor not, GN_KEYWORD_2008, K_not -note, GN_KEYWORD_2008, K_note null, GN_KEYWORD_2008, K_null of, GN_KEYWORD_2008, K_of on, GN_KEYWORD_2008, K_on @@ -129,7 +126,6 @@ vmode, GN_KEYWORD_2008, K_vmode vprop, GN_KEYWORD_2008, K_vprop vunit, GN_KEYWORD_2008, K_vunit wait, GN_KEYWORD_2008, K_wait -warning, GN_KEYWORD_2008, K_warning when, GN_KEYWORD_2008, K_when while, GN_KEYWORD_2008, K_while with, GN_KEYWORD_2008, K_with diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 34a352e40..4b288a78b 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -271,13 +271,13 @@ static void touchup_interface_for_functions(std::list*ports) %token K_begin K_block K_body K_buffer K_bus %token K_case K_component K_configuration K_constant K_context K_cover %token K_default K_disconnect K_downto -%token K_else K_elsif K_end K_entity K_error K_exit -%token K_failure K_fairness K_false K_file K_for K_force K_function +%token K_else K_elsif K_end K_entity K_exit +%token K_fairness K_false K_file K_for K_force K_function %token K_generate K_generic K_group K_guarded %token K_if K_impure K_in K_inertial K_inout K_is %token K_label K_library K_linkage K_literal K_loop %token K_map K_mod -%token K_nand K_new K_next K_nor K_not K_note K_null +%token K_nand K_new K_next K_nor K_not K_null %token K_of K_on K_open K_or K_others K_out %token K_package K_parameter K_port K_postponed K_procedure K_process %token K_property K_protected K_pure @@ -288,7 +288,7 @@ static void touchup_interface_for_functions(std::list*ports) %token K_then K_to K_transport K_true K_type %token K_unaffected K_units K_until K_use %token K_variable K_vmode K_vprop K_vunit -%token K_wait K_warning K_when K_while K_with +%token K_wait K_when K_while K_with %token K_xnor K_xor /* Identifiers that are not keywords are identifiers. */ %token IDENTIFIER @@ -2186,11 +2186,20 @@ sequential_statement ; severity - : K_severity K_note { $$ = ReportStmt::NOTE; } - | K_severity K_warning { $$ = ReportStmt::WARNING; } - | K_severity K_error { $$ = ReportStmt::ERROR; } - | K_severity K_failure { $$ = ReportStmt::FAILURE; } - ; + : K_severity IDENTIFIER + { if(!strcasecmp($2, "NOTE")) + $$ = ReportStmt::NOTE; + else if(!strcasecmp($2, "WARNING")) + $$ = ReportStmt::WARNING; + else if(!strcasecmp($2, "ERROR")) + $$ = ReportStmt::ERROR; + else if(!strcasecmp($2, "FAILURE")) + $$ = ReportStmt::FAILURE; + else { + errormsg(@1, "Invalid severity level (possible values: NOTE, WARNING, ERROR, FAILURE).\n"); + $$ = ReportStmt::UNSPECIFIED; + } + } severity_opt : severity { $$ = $1; } From 5101b3b64b56a443e4afa05196e5a35a57006f34 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 24 Apr 2015 13:37:04 +0200 Subject: [PATCH 6/7] vhdlpp: Boolean values handled without using keywords. --- vhdlpp/lexor_keyword.gperf | 2 -- vhdlpp/parse.y | 29 +++++++++++++---------------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/vhdlpp/lexor_keyword.gperf b/vhdlpp/lexor_keyword.gperf index b5faffce4..42fd1bc0d 100644 --- a/vhdlpp/lexor_keyword.gperf +++ b/vhdlpp/lexor_keyword.gperf @@ -47,7 +47,6 @@ end, GN_KEYWORD_2008, K_end entity, GN_KEYWORD_2008, K_entity exit, GN_KEYWORD_2008, K_exit fairness, GN_KEYWORD_2008, K_fairness -false, GN_KEYWORD_2008, K_false file, GN_KEYWORD_2008, K_file for, GN_KEYWORD_2008, K_for force, GN_KEYWORD_2008, K_force @@ -115,7 +114,6 @@ subtype, GN_KEYWORD_2008, K_subtype then, GN_KEYWORD_2008, K_then to, GN_KEYWORD_2008, K_to transport, GN_KEYWORD_2008, K_transport -true, GN_KEYWORD_2008, K_true type, GN_KEYWORD_2008, K_type unaffected, GN_KEYWORD_2008, K_unaffected units, GN_KEYWORD_2008, K_units diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 4b288a78b..9e60453b1 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -272,7 +272,7 @@ static void touchup_interface_for_functions(std::list*ports) %token K_case K_component K_configuration K_constant K_context K_cover %token K_default K_disconnect K_downto %token K_else K_elsif K_end K_entity K_exit -%token K_fairness K_false K_file K_for K_force K_function +%token K_fairness K_file K_for K_force K_function %token K_generate K_generic K_group K_guarded %token K_if K_impure K_in K_inertial K_inout K_is %token K_label K_library K_linkage K_literal K_loop @@ -285,7 +285,7 @@ static void touchup_interface_for_functions(std::list*ports) %token K_restrict K_restrict_guarantee K_return K_reverse_range K_rol K_ror %token K_select K_sequence K_severity K_signal K_shared %token K_sla K_sll K_sra K_srl K_strong K_subtype -%token K_then K_to K_transport K_true K_type +%token K_then K_to K_transport K_type %token K_unaffected K_units K_until K_use %token K_variable K_vmode K_vprop K_vunit %token K_wait K_when K_while K_with @@ -1590,10 +1590,17 @@ mode_opt : mode {$$ = $1;} | {$$ = PORT_NONE;} ; name /* IEEE 1076-2008 P8.1 */ : IDENTIFIER /* simple_name (IEEE 1076-2008 P8.2) */ - { ExpName*tmp = new ExpName(lex_strings.make($1)); - FILE_NAME(tmp, @1); - delete[]$1; - $$ = tmp; + { Expression*tmp; + if(!strcasecmp($1, "true")) + tmp = new ExpBitstring("1"); + else if(!strcasecmp($1, "false")) + tmp = new ExpBitstring("0"); + else + tmp = new ExpName(lex_strings.make($1)); + + FILE_NAME(tmp, @1); + delete[]$1; + $$ = tmp; } | selected_name @@ -1827,16 +1834,6 @@ primary delete[]$1; $$ = tmp; } - | K_true - { ExpBitstring*tmp = new ExpBitstring("1"); - FILE_NAME(tmp, @1); - $$ = tmp; - } - | K_false - { ExpBitstring*tmp = new ExpBitstring("0"); - FILE_NAME(tmp, @1); - $$ = tmp; - } /*XXXX Caught up in element_association_list? | '(' expression ')' From c8fe897446c0cb83b66c50bf7fc1eb7d57ad9570 Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Thu, 23 Apr 2015 17:08:26 -0700 Subject: [PATCH 7/7] vhdlpp: and_reduce() and or_reduce() functions. --- vhdlpp/expression_elaborate.cc | 7 +++++++ vhdlpp/expression_emit.cc | 10 ++++++++++ 2 files changed, 17 insertions(+) diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 30ddd4e2f..4c64ff186 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -877,6 +877,12 @@ const VType* ExpFunc::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) c return new VTypeArray(element, width, 0, sign); } + if(name_ == "and_reduce" || name_ == "or_reduce") { + ivl_assert(*this, argv_.size() == 1); + const VType*element = &primitive_STDLOGIC; + return new VTypeArray(element, 0, 0, false); + } + // Other cases Subprogram*prog = def_; @@ -888,6 +894,7 @@ const VType* ExpFunc::fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*) c if(!prog) prog = library_find_subprogram(name_); + cerr << get_fileline() << ": sorry: VHDL function " << name_ << " not yet implemented" << endl; ivl_assert(*this, prog); return def_->peek_return_type(); diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index 98b0ebe5c..b0ccefc5e 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -647,6 +647,16 @@ int ExpFunc::emit(ostream&out, Entity*ent, ScopeBase*scope) errors += argv_[0]->emit(out, ent, scope); out << ")"; + } else if (name_ == "and_reduce" && argv_.size() == 1) { + out << "&("; + errors += argv_[0]->emit(out, ent, scope); + out << ")"; + + } else if (name_ == "or_reduce" && argv_.size() == 1) { + out << "|("; + errors += argv_[0]->emit(out, ent, scope); + out << ")"; + } else { // If this function has an elaborated definition, and if // that definition is in a package, then include the