From d352d8ead36424ea7093e1890ff7f3d5de6bfe3d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 20 Apr 2015 10:57:49 +0200 Subject: [PATCH 001/595] 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 002/595] 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 003/595] 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 004/595] 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 005/595] 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 006/595] 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 007/595] 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 From 9e3f1ef1ff153f2c27563c7dc82ca7b4ceef4e02 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 5 May 2015 22:55:15 +0100 Subject: [PATCH 008/595] Only apply linker renaming of strtod() when using 32-bit MinGW. mingw-w64 doesn't need this, and the 64-bit version doesn't support it. --- aclocal.m4 | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/aclocal.m4 b/aclocal.m4 index 99bfe9516..f44632fe2 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -223,8 +223,9 @@ AC_SUBST(strip_dynamic) # ------------- AC_DEFUN([AX_C99_STRTOD], [# On MinGW we need to jump through hoops to get a C99 compliant strtod(). + # mingw-w64 doesn't need this, and the 64-bit version doesn't support it. case "${host}" in - *-*-mingw*) + *-*-mingw32) LDFLAGS+=" -Wl,--undefined=___strtod,--wrap,strtod,--defsym,___wrap_strtod=___strtod" ;; esac From 45dc13e496367bc0c33bb14a6956e83c71008dbd Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 5 May 2015 23:00:09 +0100 Subject: [PATCH 009/595] Use uintptr_t/intptr_t when casting between pointer and integer. The code was using (unsigned) long, but a long is 32-bits in the Windows 64-bit ABI. --- libveriuser/a_fetch_param.c | 2 +- tgt-vlog95/logic_lpm.c | 4 ++-- vpi/fstapi.c | 24 ++++++++++++------------ vpi/sys_fst.c | 6 +++--- vvp/vpi_signal.cc | 2 +- vvp/vvp_net.h | 4 ++-- 6 files changed, 21 insertions(+), 21 deletions(-) diff --git a/libveriuser/a_fetch_param.c b/libveriuser/a_fetch_param.c index 5993a47da..bf7b5ba8c 100644 --- a/libveriuser/a_fetch_param.c +++ b/libveriuser/a_fetch_param.c @@ -36,7 +36,7 @@ double acc_fetch_paramval(handle object) fprintf(pli_trace, "acc_fetch_paramval(%s) --> \"%s\"\n", vpi_get_str(vpiName, object), val.value.str); } - return (double) (long)val.value.str; + return (double) (intptr_t)val.value.str; default: vpi_printf("XXXX: parameter %s has type %d\n", diff --git a/tgt-vlog95/logic_lpm.c b/tgt-vlog95/logic_lpm.c index 7e390d809..1cffbd1e0 100644 --- a/tgt-vlog95/logic_lpm.c +++ b/tgt-vlog95/logic_lpm.c @@ -1900,7 +1900,7 @@ void emit_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig) { ivl_nexus_t nex = ivl_signal_nex(sig, 0); unsigned idx, count = ivl_nexus_ptrs(nex); - unsigned long emitted = (unsigned long) ivl_nexus_get_private(nex); + unsigned long emitted = (uintptr_t) ivl_nexus_get_private(nex); for (idx = 0; idx < count; idx += 1) { ivl_nexus_ptr_t nex_ptr = ivl_nexus_ptr(nex, idx); ivl_net_const_t net_const = ivl_nexus_ptr_con(nex_ptr); @@ -1930,7 +1930,7 @@ void emit_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig) fprintf(vlog_out, "\n"); /* Increment the emitted constant count by one. */ ivl_nexus_set_private(nex, - (void *) ((unsigned long) ivl_nexus_get_private(nex) + 1U)); + (void *) ((uintptr_t) ivl_nexus_get_private(nex) + 1U)); return; } /* We must find the constant in the nexus. */ diff --git a/vpi/fstapi.c b/vpi/fstapi.c index 5ec842da2..693722ce3 100644 --- a/vpi/fstapi.c +++ b/vpi/fstapi.c @@ -1449,12 +1449,12 @@ for(i=0;imaxhandle;i++) PPvoid_t pv = JudyHSIns(&PJHSArray, dmem, destlen, NULL); if(*pv) { - uint32_t pvi = (long)(*pv); + uint32_t pvi = (intptr_t)(*pv); vm4ip[2] = -pvi; } else { - *pv = (void *)(long)(i+1); + *pv = (void *)(intptr_t)(i+1); #endif fpos += fstWriterVarint(f, wrlen); fpos += destlen; @@ -1469,12 +1469,12 @@ for(i=0;imaxhandle;i++) PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL); if(*pv) { - uint32_t pvi = (long)(*pv); + uint32_t pvi = (intptr_t)(*pv); vm4ip[2] = -pvi; } else { - *pv = (void *)(long)(i+1); + *pv = (void *)(intptr_t)(i+1); #endif fpos += fstWriterVarint(f, 0); fpos += wrlen; @@ -1504,12 +1504,12 @@ for(i=0;imaxhandle;i++) PPvoid_t pv = JudyHSIns(&PJHSArray, dmem, rc, NULL); if(*pv) { - uint32_t pvi = (long)(*pv); + uint32_t pvi = (intptr_t)(*pv); vm4ip[2] = -pvi; } else { - *pv = (void *)(long)(i+1); + *pv = (void *)(intptr_t)(i+1); #endif fpos += fstWriterVarint(f, wrlen); fpos += rc; @@ -1524,12 +1524,12 @@ for(i=0;imaxhandle;i++) PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL); if(*pv) { - uint32_t pvi = (long)(*pv); + uint32_t pvi = (intptr_t)(*pv); vm4ip[2] = -pvi; } else { - *pv = (void *)(long)(i+1); + *pv = (void *)(intptr_t)(i+1); #endif fpos += fstWriterVarint(f, 0); fpos += wrlen; @@ -1546,12 +1546,12 @@ for(i=0;imaxhandle;i++) PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL); if(*pv) { - uint32_t pvi = (long)(*pv); + uint32_t pvi = (intptr_t)(*pv); vm4ip[2] = -pvi; } else { - *pv = (void *)(long)(i+1); + *pv = (void *)(intptr_t)(i+1); #endif fpos += fstWriterVarint(f, 0); fpos += wrlen; @@ -2307,14 +2307,14 @@ if(xc && path && path[0]) PPvoid_t pv = JudyHSIns(&(xc->path_array), path2, slen, NULL); if(*pv) { - sidx = (long)(*pv); + sidx = (intptr_t)(*pv); } else { char *rp = NULL; sidx = ++xc->path_array_count; - *pv = (void *)(long)(xc->path_array_count); + *pv = (void *)(intptr_t)(xc->path_array_count); if(use_realpath) { diff --git a/vpi/sys_fst.c b/vpi/sys_fst.c index f8c26404f..a0a770c6b 100644 --- a/vpi/sys_fst.c +++ b/vpi/sys_fst.c @@ -623,18 +623,18 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) new_ident = fstWriterCreateVar(dump_file, type, dir, size, buf, - (fstHandle)(long)ident); + (fstHandle)(intptr_t)ident); free(buf); } else { new_ident = fstWriterCreateVar(dump_file, type, dir, size, escname, - (fstHandle)(long)ident); + (fstHandle)(intptr_t)ident); } free(escname); if (!ident) { if (nexus_id) set_nexus_ident(nexus_id, - (const char *)(long)new_ident); + (const char *)(intptr_t)new_ident); /* Add a callback for the signal. */ info = malloc(sizeof(*info)); diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index 81b10cece..8750c3a65 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -580,7 +580,7 @@ static int signal_get(int code, vpiHandle ref) // This private property must return zero when undefined. case _vpiNexusId: if (rfp->msb.get_value() == rfp->lsb.get_value()) - return (int) (unsigned long) rfp->node; + return (int) (uintptr_t) rfp->node; else return 0; diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index d86f3a1ba..6e89a1850 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -1039,7 +1039,7 @@ template class vvp_sub_pointer_t { vvp_sub_pointer_t(T*ptr__, unsigned port__) { - bits_ = reinterpret_cast (ptr__); + bits_ = reinterpret_cast (ptr__); assert( (bits_ & 3) == 0 ); assert( (port__ & ~3) == 0 ); bits_ |= port__; @@ -1061,7 +1061,7 @@ template class vvp_sub_pointer_t { bool operator != (vvp_sub_pointer_t that) const { return bits_ != that.bits_; } private: - unsigned long bits_; + uintptr_t bits_; }; typedef vvp_sub_pointer_t vvp_net_ptr_t; From 9de4ced133e79d4d6e918c95e145bd8de8c5cb4f Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 20 Apr 2015 10:57:49 +0200 Subject: [PATCH 010/595] 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 6df297999821dff1b5405094f67d5938b152f496 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 20 Apr 2015 22:36:14 +0200 Subject: [PATCH 011/595] 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 5438464d67960cf081f958a8eb51f14e9056ff47 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 22 Apr 2015 18:02:53 +0200 Subject: [PATCH 012/595] vhdlpp: Support for reports & asserts. --- vhdlpp/parse.y | 52 ++++++++++++++++++++++++++++- vhdlpp/sequential.cc | 21 ++++++++++++ vhdlpp/sequential.h | 35 +++++++++++++++++++ vhdlpp/sequential_debug.cc | 15 +++++++++ vhdlpp/sequential_elaborate.cc | 5 +++ vhdlpp/sequential_emit.cc | 61 ++++++++++++++++++++++++++++++++++ 6 files changed, 188 insertions(+), 1 deletion(-) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 146f984ac..0e0c0ce1e 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; }; @@ -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,26 @@ sequential_statement } ; +severity + : 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; } + | { $$ = 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 4304fd503e52aaf85af6781ebd2ff7eadb08f7eb Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Thu, 23 Apr 2015 17:08:26 -0700 Subject: [PATCH 013/595] 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 From 08e5aa021a0fc7e814c1ccea0b9e913afb9bca47 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 6 May 2015 15:07:53 +0200 Subject: [PATCH 014/595] vhdlpp: Emits typedef for boolean type. --- vhdlpp/library.cc | 8 ++++++++ vhdlpp/library.h | 1 + vhdlpp/main.cc | 2 ++ vhdlpp/vtype_emit.cc | 2 ++ 4 files changed, 13 insertions(+) diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index 61ae426df..87cf41fa2 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -409,6 +409,14 @@ void generate_global_types(ActiveScope*res) res->use_name(perm_string::literal("natural"), &primitive_NATURAL); } +void emit_std_types(ostream&out) +{ + out << "`ifndef __VHDL_STD_TYPES" << endl; + out << "`define __VHDL_STD_TYPES" << endl; + out << "typedef enum bit { \\false , \\true } boolean ;" << endl; + out << "`endif" << endl; +} + bool is_global_type(perm_string name) { if (name == "boolean") return true; diff --git a/vhdlpp/library.h b/vhdlpp/library.h index ab6464f45..fe04aad23 100644 --- a/vhdlpp/library.h +++ b/vhdlpp/library.h @@ -26,6 +26,7 @@ extern void library_add_directory(const char*directory); extern Subprogram*library_find_subprogram(perm_string name); +extern void emit_std_types(ostream&out); extern int emit_packages(void); #endif /* IVL_library_H */ diff --git a/vhdlpp/main.cc b/vhdlpp/main.cc index b142d3845..418e73daa 100644 --- a/vhdlpp/main.cc +++ b/vhdlpp/main.cc @@ -232,6 +232,8 @@ int main(int argc, char*argv[]) return 3; } + emit_std_types(cout); + errors = emit_packages(); if (errors > 0) { fprintf(stderr, "%d errors emitting packages.\n", errors); diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index 64577e004..bfce8e215 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -149,6 +149,8 @@ int VTypePrimitive::emit_primitive_type(ostream&out) const int errors = 0; switch (type_) { case BOOLEAN: + out << "boolean"; + break; case BIT: out << "bool"; break; From e4694cb6cb0c0fecc029136e289d49adbca1aae7 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 6 May 2015 15:59:00 +0200 Subject: [PATCH 015/595] vhdlpp: Changed emitted type from 'bool' to 'bit'. --- vhdlpp/library.cc | 2 +- vhdlpp/vtype_emit.cc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index 87cf41fa2..fda670a34 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -404,7 +404,7 @@ void generate_global_types(ActiveScope*res) res->use_name(perm_string::literal("real"), &primitive_REAL); res->use_name(perm_string::literal("std_logic"), &primitive_STDLOGIC); res->use_name(perm_string::literal("character"), &primitive_CHARACTER); - res->use_name(perm_string::literal("bit_vector"),&primitive_BOOL_VECTOR); + res->use_name(perm_string::literal("bit_vector"),&primitive_BIT_VECTOR); res->use_name(perm_string::literal("string"), &primitive_STRING); res->use_name(perm_string::literal("natural"), &primitive_NATURAL); } diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index bfce8e215..b97d00d7e 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -152,7 +152,7 @@ int VTypePrimitive::emit_primitive_type(ostream&out) const out << "boolean"; break; case BIT: - out << "bool"; + out << "bit"; break; case STDLOGIC: out << "logic"; From 7db01d8ded694e5bc3fc0bb82d14158ba187b873 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 7 May 2015 14:42:31 +0200 Subject: [PATCH 016/595] vhdlpp: ScopeBase::is_enum_name() returns VTypeEnum* instead of bool. --- vhdlpp/expression_elaborate.cc | 15 +++++++-------- vhdlpp/scope.cc | 6 +++--- vhdlpp/scope.h | 4 +++- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 4c64ff186..5f54fc66a 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -1027,19 +1027,18 @@ const VType* ExpName::probe_type(Entity*ent, ScopeBase*scope) const if (Variable*var = scope->find_variable(name_)) return var->peek_type(); - const VType*ctype = 0; + const VType*type = 0; Expression*cval = 0; - if (scope->find_constant(name_, ctype, cval)) - return ctype; + if (scope->find_constant(name_, type, cval)) + return type; - const VType*gtype = 0; Architecture*arc = dynamic_cast(scope); - if (arc && (gtype = arc->probe_genvar_type(name_))) { - return gtype; + if (arc && (type = arc->probe_genvar_type(name_))) { + return type; } - if (scope->is_enum_name(name_)) { - return &primitive_INTEGER; + if ((type = scope->is_enum_name(name_))) { + return type; } } diff --git a/vhdlpp/scope.cc b/vhdlpp/scope.cc index 0682a45d0..49b422e89 100644 --- a/vhdlpp/scope.cc +++ b/vhdlpp/scope.cc @@ -188,15 +188,15 @@ Subprogram* ScopeBase::find_subprogram(perm_string name) const return 0; } -bool ScopeBase::is_enum_name(perm_string name) const +const VTypeEnum* 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 *it; } - return false; + return NULL; } /* diff --git a/vhdlpp/scope.h b/vhdlpp/scope.h index 69e859fb9..709e552ec 100644 --- a/vhdlpp/scope.h +++ b/vhdlpp/scope.h @@ -58,7 +58,9 @@ 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; + // Checks if a string is one of possible enum values. If so, the enum + // type is returned, otherwise NULL. + const VTypeEnum* is_enum_name(perm_string name) const; // Moves signals, variables and components from another scope to // this one. After the transfer new_* maps are cleared in the source scope. From 3069b8dd5164656ee63ac2334ad0449a02e0dc44 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Fri, 8 May 2015 20:15:54 +0100 Subject: [PATCH 017/595] Simplify use of iverilog-vpi under Windows. iverilog-vpi now automatically finds the IVL root directory, eliminating the need for the -ivl option. Also, if the MinGW root path hasn't been added to the registry, it now searches the system path for it. --- driver-vpi/main.c | 218 +++++++++++++++++++++++----------------------- 1 file changed, 107 insertions(+), 111 deletions(-) diff --git a/driver-vpi/main.c b/driver-vpi/main.c index 5acb46b8d..6910f84ee 100644 --- a/driver-vpi/main.c +++ b/driver-vpi/main.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2002-2015 Gus Baldauf (gus@picturel.com) + * Copyright (c) 2002 Gus Baldauf (gus@picturel.com) + * Copyright (c) 2015 Martin Whitaker * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -20,7 +21,7 @@ /* * iverilog-vpi.c * - * this program provides the functionality of iverilog-vpi.sh under Win32 + * this program provides the functionality of iverilog-vpi.sh under Windows */ #include @@ -52,8 +53,8 @@ static struct global_strings { char *pIVL; /* path to IVL directory */ char *pCCFLAGS; /* compiler flags for compiling C source files */ char *pCXFLAGS; /* compiler flags for compiling C++ source files */ - char *pLDLIBS; /* LDLIBS option */ - char *pNewPath; /* new PATH environment variable setting */ + char *pLDLIBS; /* linker flags for final linking stage */ + char *pCCNAME; /* base name of compiler */ char *pLD; /* what to use for a linker */ } gstr; @@ -79,8 +80,8 @@ static void myExit(int exitVal) deInitDynString(gstr.pCCFLAGS); deInitDynString(gstr.pCXFLAGS); deInitDynString(gstr.pLDLIBS); - deInitDynString(gstr.pNewPath); - free(gstr.pLD); + deInitDynString(gstr.pCCNAME); + deInitDynString(gstr.pLD); exit(exitVal); } @@ -89,9 +90,8 @@ static void myExit(int exitVal) static void usage(void) { - fprintf(stderr,"usage: iverilog-vpi" IVERILOG_SUFFIX " [src and obj files]...\n"); + fprintf(stderr,"usage: iverilog-vpi" IVERILOG_SUFFIX " [options] [src and obj files]...\n"); fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -mingw=dir\n"); - fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -ivl=dir\n"); myExit(1); } @@ -111,6 +111,8 @@ static void initDynString(char **str) static void init(void) { + char *ptr; + initDynString(&gstr.pCCSRC); initDynString(&gstr.pCXSRC); initDynString(&gstr.pOBJ); @@ -123,7 +125,14 @@ static void init(void) initDynString(&gstr.pCCFLAGS); initDynString(&gstr.pCXFLAGS); initDynString(&gstr.pLDLIBS); - initDynString(&gstr.pNewPath); + initDynString(&gstr.pCCNAME); + initDynString(&gstr.pLD); + + /* Get the base name of the C compiler. */ + assign(&gstr.pCCNAME, IVERILOG_VPI_CC); + ptr = strchr(gstr.pCCNAME, ' '); + if (ptr != NULL) *ptr = '\0'; + /* By default use the C compiler to link the programs. */ assign(&gstr.pLD, IVERILOG_VPI_CC); } @@ -265,19 +274,22 @@ static int GetRegistryKey(char *key, char **value) static void SetRegistryKey(char *key, char *value) { + long lrv; HKEY hkKey; DWORD res; - if (RegCreateKeyEx( - HKEY_LOCAL_MACHINE, - "Software\\Icarus Verilog", - 0, - "", - REG_OPTION_NON_VOLATILE, - KEY_ALL_ACCESS,NULL, - &hkKey, - &res) != ERROR_SUCCESS) - return; + lrv = RegCreateKeyEx(HKEY_LOCAL_MACHINE, "Software\\Icarus Verilog", 0, "", + REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL, &hkKey, &res); + if (lrv != ERROR_SUCCESS) { + char message[1024]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, lrv, LANG_USER_DEFAULT, + message, sizeof(message), NULL); + fprintf(stderr, "error: couldn't write to registry - %s\n", message); + if (lrv == ERROR_ACCESS_DENIED) { + fprintf(stderr, " try running as administrator\n"); + } + return; + } /* This needs an unsigned char *, but for MinGW the char is signed. */ RegSetValueEx(hkKey, key, 0, REG_SZ, (unsigned char *) value, @@ -302,7 +314,6 @@ static int parse(int argc, char *argv[]) char lib_option[] = "-l"; char inc_option[] = "-I"; char mingw_option[] = "-mingw="; - char ivl_option[] = "-ivl="; char def_option[] = "-D"; if (argc == 1) return 0; @@ -352,10 +363,6 @@ static int parse(int argc, char *argv[]) else if (startsWith(mingw_option, argv[idx])) assignn(&gstr.pMINGW, argv[idx]+sizeof(mingw_option)-1, strlen(argv[idx])-(sizeof(mingw_option)-1)); - /* Check for the -ivl option */ - else if (startsWith(ivl_option, argv[idx])) - assignn(&gstr.pIVL, argv[idx]+sizeof(ivl_option)-1, - strlen(argv[idx])-(sizeof(ivl_option)-1)); /* Check for the --name option */ else if (startsWith(name_option, argv[idx])) { assignn(&gstr.pOUT, argv[idx]+sizeof(name_option)-1, @@ -396,7 +403,7 @@ static int parse(int argc, char *argv[]) /* Check for the --install-dir option */ else if (stricmp("--install-dir", argv[idx]) == 0) { setup_ivl_environment(); - printf("%s\\\\lib\\\\ivl" IVERILOG_SUFFIX "\\\\.\n", gstr.pIVL); + printf("%s\\lib\\ivl" IVERILOG_SUFFIX "\\.\n", gstr.pIVL); myExit(0); } /* This is different than iverilog-vpi.sh, we don't @@ -407,13 +414,14 @@ static int parse(int argc, char *argv[]) /* In case there is a --name without source/object files */ if (0 == srcFileCnt) assign(&gstr.pOUT,""); - /* Normally it's an error if there are no source or object files */ - /* Unless we are setting the IVL or MinGW registry entries */ - if (!*gstr.pOUT) { - if (!*gstr.pMINGW && !*gstr.pIVL) return 0; - } else + if (*gstr.pOUT) { /* We have a valid result file so add the .vpi extension */ append(&gstr.pOUT, ".vpi"); + } else { + /* Unless we are setting the MinGW registry entry, it's + an error if there are no source or object files */ + if (!*gstr.pMINGW) return 0; + } return 1; } @@ -424,26 +432,22 @@ static void checkMingwDir(char *root) { int irv; struct _stat stat_buf; + char *path; - char *path, *comp, *cp; initDynString(&path); assign(&path,gstr.pMINGW); appendBackSlash(&path); append(&path,"bin\\"); - /* Get just the compiler name (the first word) */ - comp = strdup(IVERILOG_VPI_CC); - cp = strchr(comp, ' '); - if (cp != NULL) *cp = '\0'; - append(&path, comp); + append(&path, gstr.pCCNAME); append(&path,".exe"); - free(comp); irv = _stat(path,&stat_buf); deInitDynString(path); if (irv) { - fprintf(stderr,"error: %s does not appear to be the valid root directory\n",root); - fprintf(stderr," of MinGW. Use the -mingw option of iverilog-vpi.exe to\n"); + fprintf(stderr,"error: %s\n", root); + fprintf(stderr," does not appear to be the valid root directory of\n"); + fprintf(stderr," MinGW. Use the -mingw option of iverilog-vpi.exe to\n"); fprintf(stderr," point to the MinGW root directory. For a Windows command\n"); fprintf(stderr," shell the option would be something like -mingw=c:\\mingw\n"); fprintf(stderr," For a Cygwin shell the option would be something like\n"); @@ -452,100 +456,97 @@ static void checkMingwDir(char *root) } } -/* do minimal check that the Icarus Verilog root directory looks valid */ - -static void checkIvlDir(char *root) -{ - int irv; - struct _stat stat_buf; - - char *path; - initDynString(&path); - assign(&path,gstr.pIVL); - appendBackSlash(&path); - append(&path,"bin\\vvp" IVERILOG_SUFFIX ".exe"); - - irv = _stat(path,&stat_buf); - deInitDynString(path); - - if (irv) { - fprintf(stderr,"error: %s does not appear to be the valid root directory of\n",root); - fprintf(stderr," Icarus Verilog. Use the -ivl option of iverilog-vpi" IVERILOG_SUFFIX " to\n"); - fprintf(stderr," point to the Icarus Verilog root directory. For a Windows\n"); - fprintf(stderr," command shell the option would be something like -ivl=c:\\iverilog\n"); - fprintf(stderr," For a Cygwin shell the option would be something like\n"); - fprintf(stderr," -ivl=c:\\\\iverilog\n"); - myExit(6); - } -} - /* see if we can find mingw root */ #define IVL_REGKEY_MINGW "MingwDir" static void setup_mingw_environment(void) { - char *pOldPATH = getenv("PATH"); /* get current path */ + char buffer[1]; /* doesn't matter how big this is, as we don't use the result */ + char *path; if (*gstr.pMINGW) { checkMingwDir(gstr.pMINGW); - SetRegistryKey(IVL_REGKEY_MINGW,gstr.pMINGW); - } else if (!GetRegistryKey(IVL_REGKEY_MINGW,&gstr.pMINGW)) { - fprintf(stderr,"error: can not locate the MinGW root directory, use the -mingw option of\n"); - fprintf(stderr," iverilog-vpi.exe to point to the MinGW root directory. For\n"); - fprintf(stderr," a Windows command shell the option would be something like\n"); - fprintf(stderr," -mingw=c:\\mingw For a Cygwin shell the option would be\n"); - fprintf(stderr," something like -mingw=c:\\\\mingw\n"); - myExit(5); - } + if (!*gstr.pOUT) SetRegistryKey(IVL_REGKEY_MINGW, gstr.pMINGW); + + } else if (GetRegistryKey(IVL_REGKEY_MINGW, &gstr.pMINGW)) { + checkMingwDir(gstr.pMINGW); + + } else if (SearchPath(NULL, gstr.pCCNAME, ".exe", sizeof(buffer), buffer, NULL)) { + return; + + } else { + fprintf(stderr,"error: cannot locate the MinGW C compiler - either add its location\n"); + fprintf(stderr," to the PATH environment variable or use the -mingw option of\n"); + fprintf(stderr," iverilog-vpi.exe to point to the MinGW root directory. For\n"); + fprintf(stderr," a Windows command shell the option would be something like\n"); + fprintf(stderr," -mingw=c:\\mingw For a Cygwin shell the option would be\n"); + fprintf(stderr," something like -mingw=c:\\\\mingw\n"); + myExit(5); + } /* Create new path with MinGW in it */ - assign(&gstr.pNewPath,"PATH="); - append(&gstr.pNewPath,gstr.pMINGW); - appendBackSlash(&gstr.pNewPath); - append(&gstr.pNewPath, "\\"); - append(&gstr.pNewPath,"bin;"); - append(&gstr.pNewPath,pOldPATH); + initDynString(&path); + assign(&path, "PATH="); + append(&path, gstr.pMINGW); + appendBackSlash(&path); + append(&path, "bin;"); + append(&path, getenv("PATH")); /* Place new path in environment */ - _putenv(gstr.pNewPath); + _putenv(path); + deInitDynString(path); } -/* see if we can find iverilog root */ - -#define IVL_REGKEY_IVL "InstallDir" +/* find the iverilog root and initialise the compiler options */ static void setup_ivl_environment(void) { - if (*gstr.pIVL) { - checkIvlDir(gstr.pIVL); - SetRegistryKey(IVL_REGKEY_IVL,gstr.pIVL); - } else if (!GetRegistryKey(IVL_REGKEY_IVL,&gstr.pIVL)) { - fprintf(stderr,"error: can not locate the Icarus Verilog root directory, use the -ivl option\n"); - fprintf(stderr," of iverilog-vpi" IVERILOG_SUFFIX " to point to the Icarus Verilog root directory.\n"); - fprintf(stderr," For a Windows command shell the option would be something like\n"); - fprintf(stderr," -ivl=c:\\iverilog For a Cygwin shell the option would be something\n"); - fprintf(stderr," like -ivl=c:\\\\iverilog\n"); - myExit(6); - } + char path[4096]; + char *ptr; + + /* Extract the Icarus Verilog root directory from the path to the + command. The command path will look something like this: + + C:\iverilog\bin\iverilog-vpi.exe + + The corresponding root directory is + + C:\iverilog + + so we chop off the file name and the last directory. */ + GetModuleFileName(NULL, path, sizeof(path)); + ptr = strrchr(path, '\\'); + if (!ptr) { + fprintf(stderr,"error: couldn't find start of program name in command path '%s'\n", path); + myExit(6); + } + *ptr = 0; + ptr = strrchr(path, '\\'); + if (!ptr) { + fprintf(stderr,"error: couldn't find start of bin directory in command path '%s'\n", path); + myExit(6); + } + *ptr = 0; + assign(&gstr.pIVL, path); /* Build up the CCFLAGS option string */ - assign(&gstr.pCCFLAGS,IVERILOG_VPI_CFLAGS " -I\""); - append(&gstr.pCCFLAGS,gstr.pIVL); + assign(&gstr.pCCFLAGS, IVERILOG_VPI_CFLAGS " -I\""); + append(&gstr.pCCFLAGS, gstr.pIVL); appendBackSlash(&gstr.pCCFLAGS); - append(&gstr.pCCFLAGS,"\\include\\\\iverilog\"" IVERILOG_SUFFIX); + append(&gstr.pCCFLAGS, "include\\iverilog\"" IVERILOG_SUFFIX); /* Build up the CXFLAGS option string */ - assign(&gstr.pCXFLAGS,IVERILOG_VPI_CXXFLAGS " -I\""); - append(&gstr.pCXFLAGS,gstr.pIVL); + assign(&gstr.pCXFLAGS, IVERILOG_VPI_CXXFLAGS " -I\""); + append(&gstr.pCXFLAGS, gstr.pIVL); appendBackSlash(&gstr.pCXFLAGS); - append(&gstr.pCXFLAGS,"\\include\\\\iverilog\"" IVERILOG_SUFFIX); + append(&gstr.pCXFLAGS, "include\\iverilog\"" IVERILOG_SUFFIX); /* Build up the LDFLAGS option string */ - assign(&gstr.pLDLIBS,"-L\""); - append(&gstr.pLDLIBS,gstr.pIVL); + assign(&gstr.pLDLIBS, "-L\""); + append(&gstr.pLDLIBS, gstr.pIVL); appendBackSlash(&gstr.pLDLIBS); - append(&gstr.pLDLIBS,"\\lib\" " IVERILOG_VPI_LDLIBS); + append(&gstr.pLDLIBS, "lib\" " IVERILOG_VPI_LDLIBS); } /* compile source modules */ @@ -609,12 +610,7 @@ static void compile_and_link(void) /* To make the output match iverilog-vpi.sh do not print out the * root directories */ - // printf("MinGW root directory: %s.\n", gstr.pMINGW); - checkMingwDir(gstr.pMINGW); - -// printf("Icarus Verilog root directory: %s.\n", gstr.pIVL); - checkIvlDir(gstr.pIVL); /* compile the C source files (*.c) */ compile(gstr.pCCSRC, gstr.pCCFLAGS, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CC ); From 6a3edc63d5ff68633d7d635e511e955083051b40 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Fri, 8 May 2015 20:20:14 +0100 Subject: [PATCH 018/595] Fix printf format for size_t values when using 64-bit MinGW. The Microsoft C runtime does not support the %zu and %zd formats. Previously these were replaced with %u and %d, but for 64-bit we need to use %llu and %lld. --- config.h.in | 14 ++++++++++++++ configure.in | 1 + ivlpp/lexor.lex | 6 +----- vvp/config.h.in | 12 ++++++++++++ vvp/main.cc | 24 ++++-------------------- vvp/udp.cc | 6 +----- 6 files changed, 33 insertions(+), 30 deletions(-) diff --git a/config.h.in b/config.h.in index 30470a22b..8bac481be 100644 --- a/config.h.in +++ b/config.h.in @@ -27,6 +27,10 @@ # endif #endif +# define SIZEOF_UNSIGNED_LONG_LONG 0 + +# define SIZEOF_SIZE_T 0 + # undef NEED_LU # undef NEED_TU # undef WLU @@ -62,4 +66,14 @@ */ # undef CHECK_WITH_VALGRIND +#ifdef __MINGW32__ +# if SIZEOF_SIZE_T == SIZEOF_UNSIGNED_LONG_LONG +# define SIZE_FMT_D "llu" +# else +# define SIZE_FMT_D "u" +# endif +#else +# define SIZE_FMT_D "zu" +#endif + #endif /* IVL_config_H */ diff --git a/configure.in b/configure.in index 7fa9bc8e4..8d9be4ad9 100644 --- a/configure.in +++ b/configure.in @@ -131,6 +131,7 @@ CXXFLAGS="$iverilog_temp_cxxflags" AC_CHECK_SIZEOF(unsigned long long) AC_CHECK_SIZEOF(unsigned long) AC_CHECK_SIZEOF(unsigned) +AC_CHECK_SIZEOF(size_t) # vvp uses these... AC_CHECK_LIB(termcap, tputs) diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index f7d76422d..38b78c995 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -1898,11 +1898,7 @@ static int load_next_input(void) static void do_dump_precompiled_defines(FILE* out, struct define_t* table) { if (!table->keyword) -#ifdef __MINGW32__ /* MinGW does not know about z. */ - fprintf(out, "%s:%d:%d:%s\n", table->name, table->argc, strlen(table->value), table->value); -#else - fprintf(out, "%s:%d:%zd:%s\n", table->name, table->argc, strlen(table->value), table->value); -#endif + fprintf(out, "%s:%d:%" SIZE_FMT_D ":%s\n", table->name, table->argc, strlen(table->value), table->value); if (table->left) do_dump_precompiled_defines(out, table->left); diff --git a/vvp/config.h.in b/vvp/config.h.in index 24b0aa802..1a7151ac3 100644 --- a/vvp/config.h.in +++ b/vvp/config.h.in @@ -33,6 +33,8 @@ #endif # define SIZEOF_UNSIGNED 0 +# define SIZEOF_SIZE_T 0 + # undef NEED_LU # undef NEED_TU # undef WLU @@ -133,6 +135,16 @@ typedef unsigned long vvp_time64_t; #endif /* HAVE_INTTYPES_H */ +#ifdef __MINGW32__ +# if SIZEOF_SIZE_T == SIZEOF_UNSIGNED_LONG_LONG +# define SIZE_FMT_U "llu" +# else +# define SIZE_FMT_U "u" +# endif +#else +# define SIZE_FMT_U "zu" +#endif + # include /* getrusage, /proc/self/statm */ diff --git a/vvp/main.cc b/vvp/main.cc index ae2457155..801ee4e35 100644 --- a/vvp/main.cc +++ b/vvp/main.cc @@ -464,34 +464,18 @@ int main(int argc, char*argv[]) } if (verbose_flag) { -#ifdef __MINGW32__ /* MinGW does not know about z. */ - vpi_mcd_printf(1, " ... %8lu functors (net_fun pool=%u bytes)\n", -#else - vpi_mcd_printf(1, " ... %8lu functors (net_fun pool=%zu bytes)\n", -#endif + vpi_mcd_printf(1, " ... %8lu functors (net_fun pool=%" SIZE_FMT_U " bytes)\n", count_functors, vvp_net_fun_t::heap_total()); vpi_mcd_printf(1, " %8lu logic\n", count_functors_logic); vpi_mcd_printf(1, " %8lu bufif\n", count_functors_bufif); vpi_mcd_printf(1, " %8lu resolv\n",count_functors_resolv); vpi_mcd_printf(1, " %8lu signals\n", count_functors_sig); -#ifdef __MINGW32__ /* MinGW does not know about z. */ - vpi_mcd_printf(1, " ... %8lu filters (net_fil pool=%u bytes)\n", -#else - vpi_mcd_printf(1, " ... %8lu filters (net_fil pool=%zu bytes)\n", -#endif + vpi_mcd_printf(1, " ... %8lu filters (net_fil pool=%" SIZE_FMT_U " bytes)\n", count_filters, vvp_net_fil_t::heap_total()); -#ifdef __MINGW32__ /* MinGW does not know about z. */ - vpi_mcd_printf(1, " ... %8lu opcodes (%u bytes)\n", -#else - vpi_mcd_printf(1, " ... %8lu opcodes (%zu bytes)\n", -#endif + vpi_mcd_printf(1, " ... %8lu opcodes (%" SIZE_FMT_U " bytes)\n", count_opcodes, size_opcodes); vpi_mcd_printf(1, " ... %8lu nets\n", count_vpi_nets); -#ifdef __MINGW32__ /* MinGW does not know about z. */ - vpi_mcd_printf(1, " ... %8lu vvp_nets (%u bytes)\n", -#else - vpi_mcd_printf(1, " ... %8lu vvp_nets (%zu bytes)\n", -#endif + vpi_mcd_printf(1, " ... %8lu vvp_nets (%" SIZE_FMT_U " bytes)\n", count_vvp_nets, size_vvp_nets); vpi_mcd_printf(1, " ... %8lu arrays (%lu words)\n", count_net_arrays, count_net_array_words); diff --git a/vvp/udp.cc b/vvp/udp.cc index 407952c6b..8ea8b8e06 100644 --- a/vvp/udp.cc +++ b/vvp/udp.cc @@ -266,11 +266,7 @@ void vvp_udp_comb_s::compile_table(char**tab) cur.maskx = 0; if (port_count() > 8*sizeof(cur.mask0)) { fprintf(stderr, "internal error: primitive port count=%u " -#ifdef __MINGW32__ /* MinGW does not know about z. */ - " > %u\n", port_count(), sizeof(cur.mask0)); -#else - " > %zu\n", port_count(), sizeof(cur.mask0)); -#endif + " > %" SIZE_FMT_U "\n", port_count(), sizeof(cur.mask0)); assert(port_count() <= 8*sizeof(cur.mask0)); } for (unsigned pp = 0 ; pp < port_count() ; pp += 1) { From e530b4e642d82e8a1482092fc8197e586104568f Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 8 May 2015 16:35:10 -0700 Subject: [PATCH 019/595] Update fstapi.c to the latest from GTKWave --- vpi/fstapi.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/vpi/fstapi.c b/vpi/fstapi.c index 693722ce3..0afd73a8f 100644 --- a/vpi/fstapi.c +++ b/vpi/fstapi.c @@ -2299,12 +2299,14 @@ if(xc && path && path[0]) #ifndef _WAVE_HAVE_JUDY const uint32_t hashmask = FST_PATH_HASHMASK; const unsigned char *path2 = (const unsigned char *)path; + PPvoid_t pv; #else char *path2 = alloca(slen + 1); /* judy lacks const qualifier in its JudyHSIns definition */ + PPvoid_t pv; strcpy(path2, path); #endif - PPvoid_t pv = JudyHSIns(&(xc->path_array), path2, slen, NULL); + pv = JudyHSIns(&(xc->path_array), path2, slen, NULL); if(*pv) { sidx = (intptr_t)(*pv); From cfbc90812bb8a650cc073094940a8dcdba37b0ce Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 10 May 2015 11:45:42 +0100 Subject: [PATCH 020/595] Enable use of MinGW ANSI stdio routines. Defining __USE_MINGW_ANSI_STDIO=1 provides C99 compatible printf and scanf routines, which avoids the need for workarounds for the various failings of the Microsoft C runtime library. --- config.h.in | 14 -------------- configure.in | 5 ++++- ivlpp/lexor.lex | 2 +- tgt-vvp/draw_net_input.c | 4 ---- tgt-vvp/draw_vpi.c | 4 ---- tgt-vvp/modpath.c | 4 ---- tgt-vvp/stmt_assign.c | 5 ----- tgt-vvp/vvp_priv.h | 5 ----- tgt-vvp/vvp_process.c | 4 ---- vpi_user.h | 9 ++++++++- vvp/config.h.in | 18 ------------------ vvp/main.cc | 8 ++++---- vvp/udp.cc | 2 +- vvp/vpi_mcd.cc | 26 -------------------------- 14 files changed, 18 insertions(+), 92 deletions(-) diff --git a/config.h.in b/config.h.in index 8bac481be..30470a22b 100644 --- a/config.h.in +++ b/config.h.in @@ -27,10 +27,6 @@ # endif #endif -# define SIZEOF_UNSIGNED_LONG_LONG 0 - -# define SIZEOF_SIZE_T 0 - # undef NEED_LU # undef NEED_TU # undef WLU @@ -66,14 +62,4 @@ */ # undef CHECK_WITH_VALGRIND -#ifdef __MINGW32__ -# if SIZEOF_SIZE_T == SIZEOF_UNSIGNED_LONG_LONG -# define SIZE_FMT_D "llu" -# else -# define SIZE_FMT_D "u" -# endif -#else -# define SIZE_FMT_D "zu" -#endif - #endif /* IVL_config_H */ diff --git a/configure.in b/configure.in index 8d9be4ad9..1ddbfa86b 100644 --- a/configure.in +++ b/configure.in @@ -131,7 +131,6 @@ CXXFLAGS="$iverilog_temp_cxxflags" AC_CHECK_SIZEOF(unsigned long long) AC_CHECK_SIZEOF(unsigned long) AC_CHECK_SIZEOF(unsigned) -AC_CHECK_SIZEOF(size_t) # vvp uses these... AC_CHECK_LIB(termcap, tputs) @@ -224,6 +223,10 @@ case "${host}" in CPPFLAGS="-mieee $CPPFLAGS" CFLAGS="-mieee $CFLAGS" ;; + *-*-mingw*) + CXXFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $CXXFLAGS" + CFLAGS="-D__USE_MINGW_ANSI_STDIO=1 $CFLAGS" + ;; esac # Do some more operating system specific setup. We put the file64_support diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index 38b78c995..ea84b86e0 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -1898,7 +1898,7 @@ static int load_next_input(void) static void do_dump_precompiled_defines(FILE* out, struct define_t* table) { if (!table->keyword) - fprintf(out, "%s:%d:%" SIZE_FMT_D ":%s\n", table->name, table->argc, strlen(table->value), table->value); + fprintf(out, "%s:%d:%zd:%s\n", table->name, table->argc, strlen(table->value), table->value); if (table->left) do_dump_precompiled_defines(out, table->left); diff --git a/tgt-vvp/draw_net_input.c b/tgt-vvp/draw_net_input.c index 906be39a0..fe040601b 100644 --- a/tgt-vvp/draw_net_input.c +++ b/tgt-vvp/draw_net_input.c @@ -26,10 +26,6 @@ # include # include "ivl_alloc.h" -#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */ -#define snprintf _snprintf -#endif - static ivl_signal_type_t signal_type_of_nexus(ivl_nexus_t nex) { unsigned idx; diff --git a/tgt-vvp/draw_vpi.c b/tgt-vvp/draw_vpi.c index 8e7f21642..3587815eb 100644 --- a/tgt-vvp/draw_vpi.c +++ b/tgt-vvp/draw_vpi.c @@ -23,10 +23,6 @@ # include # include "ivl_alloc.h" -#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */ -#define snprintf _snprintf -#endif - struct args_info { char*text; /* True ('s' or 'u' if this argument is a calculated vec4. */ diff --git a/tgt-vvp/modpath.c b/tgt-vvp/modpath.c index 4c904496d..bdaf72e93 100644 --- a/tgt-vvp/modpath.c +++ b/tgt-vvp/modpath.c @@ -23,10 +23,6 @@ # include # include "ivl_alloc.h" -#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */ -#define snprintf _snprintf -#endif - static ivl_signal_t find_path_source_port(ivl_delaypath_t path) { unsigned idx; diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index e2456ae25..7a788e807 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -22,11 +22,6 @@ # include # include -#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */ -#define snprintf _snprintf -#endif - - /* * These functions handle the blocking assignment. Use the %set * instruction to perform the actual assignment, and calculate any diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index 7f0fbac77..e23916e03 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -23,11 +23,6 @@ # include "ivl_target.h" # include -#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */ -#define snprintf _snprintf -#endif - - extern int debug_draw; /* diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index ffa07493c..3980b9575 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -23,10 +23,6 @@ # include # include -#ifdef __MINGW32__ /* MinGW has inconsistent %p output. */ -#define snprintf _snprintf -#endif - static int show_statement(ivl_statement_t net, ivl_scope_t sscope); unsigned local_count = 0; diff --git a/vpi_user.h b/vpi_user.h index 7bef96669..52f9a5f78 100644 --- a/vpi_user.h +++ b/vpi_user.h @@ -421,10 +421,17 @@ extern PLI_UINT32 vpi_mcd_open(char *name); extern PLI_UINT32 vpi_mcd_close(PLI_UINT32 mcd); extern char *vpi_mcd_name(PLI_UINT32 mcd); extern PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, const char*fmt, ...) +#ifdef __MINGW32__ + __attribute__((format (gnu_printf,2,3))); +#else __attribute__((format (printf,2,3))); - +#endif extern PLI_INT32 vpi_printf(const char*fmt, ...) +#ifdef __MINGW32__ + __attribute__((format (gnu_printf,1,2))); +#else __attribute__((format (printf,1,2))); +#endif extern PLI_INT32 vpi_vprintf(const char*fmt, va_list ap); extern PLI_INT32 vpi_mcd_vprintf(PLI_UINT32 mcd, const char*fmt, va_list ap); diff --git a/vvp/config.h.in b/vvp/config.h.in index 1a7151ac3..f21883dbe 100644 --- a/vvp/config.h.in +++ b/vvp/config.h.in @@ -33,8 +33,6 @@ #endif # define SIZEOF_UNSIGNED 0 -# define SIZEOF_SIZE_T 0 - # undef NEED_LU # undef NEED_TU # undef WLU @@ -88,15 +86,9 @@ typedef uint64_t vvp_time64_t; -#ifdef __MINGW32__ -# define TIME_FMT_O "I64o" -# define TIME_FMT_U "I64u" -# define TIME_FMT_X "I64x" -#else # define TIME_FMT_O PRIo64 # define TIME_FMT_U PRIu64 # define TIME_FMT_X PRIx64 -#endif # ifdef UINT64_T_AND_ULONG_SAME # define UL_AND_TIME64_SAME @@ -135,16 +127,6 @@ typedef unsigned long vvp_time64_t; #endif /* HAVE_INTTYPES_H */ -#ifdef __MINGW32__ -# if SIZEOF_SIZE_T == SIZEOF_UNSIGNED_LONG_LONG -# define SIZE_FMT_U "llu" -# else -# define SIZE_FMT_U "u" -# endif -#else -# define SIZE_FMT_U "zu" -#endif - # include /* getrusage, /proc/self/statm */ diff --git a/vvp/main.cc b/vvp/main.cc index 801ee4e35..94909d076 100644 --- a/vvp/main.cc +++ b/vvp/main.cc @@ -464,18 +464,18 @@ int main(int argc, char*argv[]) } if (verbose_flag) { - vpi_mcd_printf(1, " ... %8lu functors (net_fun pool=%" SIZE_FMT_U " bytes)\n", + vpi_mcd_printf(1, " ... %8lu functors (net_fun pool=%zu bytes)\n", count_functors, vvp_net_fun_t::heap_total()); vpi_mcd_printf(1, " %8lu logic\n", count_functors_logic); vpi_mcd_printf(1, " %8lu bufif\n", count_functors_bufif); vpi_mcd_printf(1, " %8lu resolv\n",count_functors_resolv); vpi_mcd_printf(1, " %8lu signals\n", count_functors_sig); - vpi_mcd_printf(1, " ... %8lu filters (net_fil pool=%" SIZE_FMT_U " bytes)\n", + vpi_mcd_printf(1, " ... %8lu filters (net_fil pool=%zu bytes)\n", count_filters, vvp_net_fil_t::heap_total()); - vpi_mcd_printf(1, " ... %8lu opcodes (%" SIZE_FMT_U " bytes)\n", + vpi_mcd_printf(1, " ... %8lu opcodes (%zu bytes)\n", count_opcodes, size_opcodes); vpi_mcd_printf(1, " ... %8lu nets\n", count_vpi_nets); - vpi_mcd_printf(1, " ... %8lu vvp_nets (%" SIZE_FMT_U " bytes)\n", + vpi_mcd_printf(1, " ... %8lu vvp_nets (%zu bytes)\n", count_vvp_nets, size_vvp_nets); vpi_mcd_printf(1, " ... %8lu arrays (%lu words)\n", count_net_arrays, count_net_array_words); diff --git a/vvp/udp.cc b/vvp/udp.cc index 8ea8b8e06..b311debd4 100644 --- a/vvp/udp.cc +++ b/vvp/udp.cc @@ -266,7 +266,7 @@ void vvp_udp_comb_s::compile_table(char**tab) cur.maskx = 0; if (port_count() > 8*sizeof(cur.mask0)) { fprintf(stderr, "internal error: primitive port count=%u " - " > %" SIZE_FMT_U "\n", port_count(), sizeof(cur.mask0)); + " > %zu\n", port_count(), sizeof(cur.mask0)); assert(port_count() <= 8*sizeof(cur.mask0)); } for (unsigned pp = 0 ; pp < port_count() ; pp += 1) { diff --git a/vvp/vpi_mcd.cc b/vvp/vpi_mcd.cc index d02bf174a..7a092c3c7 100644 --- a/vvp/vpi_mcd.cc +++ b/vvp/vpi_mcd.cc @@ -191,31 +191,6 @@ vpi_mcd_vprintf(PLI_UINT32 mcd, const char*fmt, va_list ap) } va_copy(saved_ap, ap); -#ifdef __MINGW32__ - /* - * The MinGW runtime (version 3.14) fixes some things, but breaks - * %f for us, so we have to us the underlying version. - */ - rc = _vsnprintf(buffer, sizeof buffer, fmt, ap); - /* - * Windows returns -1 to indicate the result was truncated (thanks for - * following the standard!). Since we don't know how big to make the - * buffer just keep doubling it until it works. - */ - if (rc == -1) { - size_t buf_size = sizeof buffer; - buf_ptr = NULL; - need_free = true; - while (rc == -1) { - va_list tmp_ap; - va_copy(tmp_ap, saved_ap); - buf_size *= 2; - buf_ptr = (char *)realloc(buf_ptr, buf_size); - rc = vsnprintf(buf_ptr, buf_size, fmt, tmp_ap); - va_end(tmp_ap); - } - } -#else rc = vsnprintf(buffer, sizeof buffer, fmt, ap); assert(rc >= 0); /* @@ -227,7 +202,6 @@ vpi_mcd_vprintf(PLI_UINT32 mcd, const char*fmt, va_list ap) need_free = true; rc = vsnprintf(buf_ptr, rc+1, fmt, saved_ap); } -#endif va_end(saved_ap); for(int i = 0; i < 31; i++) { From 6069cbfc3c64cea8a137cd1c9245dca6315d4e73 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 10 May 2015 12:03:58 +0100 Subject: [PATCH 021/595] Remove outdated instructions in mingw.txt and point to the Wiki instead. --- mingw.txt | 284 +----------------------------------------------------- 1 file changed, 3 insertions(+), 281 deletions(-) diff --git a/mingw.txt b/mingw.txt index b5dc25307..5f65922a6 100644 --- a/mingw.txt +++ b/mingw.txt @@ -1,282 +1,4 @@ -Please NOTE: +Please see the Icarus Verilog Wiki for instruction on building and installing +Icarus Verilog as a native Windows application using the MinGW tools: -These directions are slightly outdated and need to be updated. -The plan is to rewrite all this using the latest MinGW at -some time in the not too distant future (CR Aug. 2009) - - -MINGW PORT OF ICARUS VERILOG - - Copyright 2006 Stephen Williams - - -Icarus Verilog source can be compiled with the mingw C/C++ compilers -to get a Windows binary that does not require the POSIX compatibility -cruft of the Cygwin.dll library. The resulting program can be run with -or without Cygwin, so this is the preferred Windows distribution form. -The configure scripts automatically detect that the compilers in use -are the mingw compilers and will configure the Makefiles appropriately. - -The mingw patch doesn't contain tools beyond the compiler, but there -is the "msys" package that the makers of Mingw publish that has enough -extra tools to get most everything else working. There are a few extra -packages needed beyond mingw and msys, and the following instructions -explain how to get them and install them. - -* Some Preliminary Comments -- PLEASE READ ME -- - -The Windows port of Icarus Verilog is the most difficult of all the -ports. The Windows system off the shelf is completely stripped, devoid -of any support for software development. Everything needed to compile -Icarus Verilog must be collected from various sources and stitched -together by hand. Normal human beings with a basic understanding of -software development can do this, but some patience (and access to the -Internet) is required. You may choose to print these instructions. FOR -BEST RESULTS, FOLLOW THESE INSTRUCTIONS CAREFULLY. - -NOTE that if you have Cygwin installed, it is best to not use a cygwin -window to do the build, as the Cygwin tools will intermix with the -mingw tools such that it is hard to be sure you are using the right -compiler. Thus, it is recommended that these steps be *not* done in a -Cygwin window. Use an MSYS window instead, and be careful that your -msys/mingw tools are not masked by paths that point to Cygwin binaries. - -I have no plans to intentionally support MSVC++ compilation. Don't ask. - -* Summary of Prerequisites - -This is a brief list of prerequisite packages, along with the URL -where each can be found. In most cases, the specific version is not -critical, but these are the versions I use. - - msys-1.0 - msysDTK-1.0 - Mingw32-5.x - ... including the sub-packages binutils, gcc-core and gcc-g++ - if you are given the option. - readline-5.0-1 - bzip2-1.0.3 - zlib-1.2.3 - gperf-3.0.1 - bison-2.1 - flex-2.5.4a - -The above table lists the packages required. It is convenient to -install them in the above order. Many of these packages are also -collected into the directory: - - - -Incidentally, besides Mingw32, none of these packages are needed after -installation of Icarus Verilog is complete. These are only needed to -build the compiler. The Mingw32 package can be used to compile VPI -modules if you choose. - -* Install MSYS and msysDTK - -The msys package is available from the mingw download site. This is -not the compiler but a collection of *nix tools ported to Windows and -wrapped in a convenient installer. The msys package is all the various -basic tools (shells, file utils, etc) and the msysDTK is extra -developer tools other than the compiler. - -Download the msys-1.x.x.exe and msysdtc-1.x.x.exe binaries. These are -self-installing packages. Install msys first, and then msysDTC. Most -likely, you want to install them in c:/msys. (The msysDTK is installed -in the same location, as it is an add-on.) - -This install should be easy and reliable. - -The installation will leave an "msys" icon on your desktop and in the -mingw sub-menu of your Start menu. This icon brings up a shell window -(a command line) that has paths all set up for executing msys and -mingw commands. This is what you will want to use while executing -commands below. - -* Install Mingw32 - -The obvious step 2, then, is install the mingw compilers. These can be -found at the web page . The Mingw-5.x.x package -is a convenient remote installer. Download this program and run -it. The installer will ask which components you want to install. You -need only the base C compiler and the C++ compiler. (You may install -other languages if you wish.) - -When I install Mingw32 (using the installer) I typically set a -destination directory of d:\mingw or the like. You will be using -that path later. - - NOTES: - If you intend to compile VPI modules for Icarus Verilog, you - need Mingw32, even if you are using a precompiled binary. VPI - modules only require Mingw32, and none of the other libraries. - -Finally, as part of installing the mingw32 compilers, remember to add -the mingw/bin directory to your path. You will need that to be able to -find the compilers later. - -* Install GnuWin32 Packages - -The GnuWin32 project is a collections of open source programs and -libraries ported to Windows. These also work well with the Mingw -compiler, and in fact Icarus Verilog uses a few pieces from this -collection. - -You will need these gnuwin32 packages to compile Icarus Verilog: - - - bzip2-1.0.3.exe - zlib-1.2.3.exe - gperf-3.0.1.exe - bison-2.1.exe - flex-2.5.4a.exe - readline-5.0-1.exe - -I suggest creating a common directory for holding all your gnuwin32 -packages. I use C:\gnuwin32. The download page at the gnuwin32 site -has a "setup" link for each of these packages. Click the setup to -download the installer for each of the desired programs, then execute -the downloaded .exe files to invoke the installer. Install into the -c:\gunwin32 directory. - - NOTES: - You need the binaries and the developer files, but you do not - need the source to these packages. The installer gives you the - choice. - -After you are done installing the gnuwin32 tools, you should add the -c:\gnuwin32\bin directory (assuming you installed in c:\gnuwin32) to -your Windows path. The msys shell will pick up your Windows path. - -* Unpack Icarus Verilog source - -Unpack the compressed tar file (.tar.gz) of the source with a command -like this: - - $ gunzip -d verilog-xxxxxxxx.tar.gz | tar xvf - - -This will create a directory "verilog-xxxxxxxx" that contains all the -source for Icarus Verilog. Descend into that directory, as that is -where we will work from now on. - - $ cd verilog-xxxxxxxx - - NOTES: - The exact name of the file will vary according to the - snapshot. The 20030303 name is only an example. - - Unpack the source into a directory that has no spaces. The - makefiles included in the source get confused by white space in - directory names. - -* Preconfigure Icarus Verilog (Not normally needed) - -Under certain cases, you may need to "preconfigure" the Icarus Verilog -source tree. You should only need to do this if you are getting the -Icarus Verilog source tree from git, or you are using an existing -source tree that you've patched to cause configure.in files to change. - - NOTE: If you are building from a fresh, bundled source tree that - you downloaded from an FTP site, then SKIP THIS STEP. Go on to - the "Configure Icarus Verilog" step below. - -First, remove any autom4te.cache directories that may exist in your -source tree. These can make a mess of autoconf runs. Then, generate -configure scripts with this command: - - $ sh autoconf.sh - -This script will run the "autoconf" command (part of the msysDTK) to -generate all the necessary "configure" scripts. This will take a few -minutes. This should go smoothly. - -* Configure Icarus Verilog - -Now we are all set to configure and compile Icarus Verilog. Choose a -destination path where you will want to install the binaries. I chose -on my system the directory "D:\iverilog". This choice is not -permanent, so don't get too much angst over it. Just choose a name -without white space. - -Now, configure the source to make the makefiles and configuration -details. Run these commands: - - $ CPPFLAGS="-Ic:/gnuwin32/include - $ LDFLAGS="-Lc:/gnuwin32/lib - $ export CPPFLAGS LDFLAGS - $ ./configure --prefix=c:/iverilog - - NOTES: - The CPPFLAGS and LDFLAGS variables tell configure where - the gnuwin32 packages are. The configure program will - write these values into the Makefiles, so you only need to - keep these variables long enough for the configure program - to work. - - Your PATH variable was set in the previous step. - - Use forward slashes as directory characters. All the various - tools prefer the forward slash. - -Substitute your chosen directory for the prefix. This will cause the -makefiles to build and the source code to configure. The configure -program will detect that this is a mingw environment and set things up -to build properly. - -(For a prefix, use the drive letter notation; the mingw compiled parts -require it, and the Cygwin tools should be able to handle it. You may -need to check or upgrade your Cygwin installation if this causes -problems for you.) - - -* Compile Icarus Verilog - -This, believe it or not, should be the easy part: - - $ make - -It could take a while. Now is a good time to go get some coffee or -take a tea break. - - -* Install Icarus Verilog - -If the compile ran OK, then next you install Icarus Verilog in the -directory you have chosen. When you are ready, install like this: - - $ make install - -This is part of what the configure program did for you. The Makefiles -now know to put the files under the D:\iverilog directory (or whatever -directory you chose) and away you go. - -You may find that you need to put some of the prerequisite DLLs into -the d:\iverilog\bin directory. These include: - - c:\mingw\bin\mingw10.dll - c:\gnuwin32\bin\readline.dll - c:\gnuwin32\bin\history.dll - c:\gnuwin32\bin\bzip2.dll - c:\gnuwin32\bin\zlib.dll - -If you already have these in your Windows path (i.e. your system32 -directory) then you do not need to copy them into the iverilog -directory. However, prepackaged Icarus Verilog binaries include these -files. - -* Running Icarus Verilog - -Finally, put the C:\iverilog\bin directory in your Windows path, and -you should be able to run the iverilog and vvp commands to your -heart's content. - -Currently, the iverilog.exe uses the path to itself to locate the -libraries and modules associated with itself. In other words, if you -execute the C:\iverilog\bin\iverilog.exe program, it will locate its -subparts in the C:\iverilog directory and subdirectories below -that. This means you can move the Icarus Verilog installation by -simply moving the root directory and all its contents. - -The vvp.pdf and iverilog.pdf files document the main commands. View -these with Acrobat reader, or any other viewer capable of displaying -PDF format files. + http://iverilog.wikia.com/wiki/Installation_Guide#Compiling_on_MS_Windows_.28MinGW.29 From 676d23f9731477dd8b23f7b26b2f47fe6d71fee3 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 10 May 2015 13:19:16 +0100 Subject: [PATCH 022/595] Add extra whitespace in driver-vpi/main.c for readability. --- driver-vpi/main.c | 88 +++++++++++++++++++++++------------------------ 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/driver-vpi/main.c b/driver-vpi/main.c index 6910f84ee..19ed5cbe7 100644 --- a/driver-vpi/main.c +++ b/driver-vpi/main.c @@ -90,8 +90,8 @@ static void myExit(int exitVal) static void usage(void) { - fprintf(stderr,"usage: iverilog-vpi" IVERILOG_SUFFIX " [options] [src and obj files]...\n"); - fprintf(stderr," or iverilog-vpi" IVERILOG_SUFFIX " -mingw=dir\n"); + fprintf(stderr, "usage: iverilog-vpi" IVERILOG_SUFFIX " [options] [src and obj files]...\n"); + fprintf(stderr, " or iverilog-vpi" IVERILOG_SUFFIX " -mingw=dir\n"); myExit(1); } @@ -100,7 +100,7 @@ static void initDynString(char **str) *str = (char *) malloc(1); if (!*str) { - fprintf(stderr,"error: out of memory\n"); + fprintf(stderr, "error: out of memory\n"); myExit(4); } @@ -148,7 +148,7 @@ static int endsIn (char *end, char *str) ext = str + (strlen(str) - strlen(end)); - return stricmp(end,ext) ? 0 : 1; + return stricmp(end, ext) ? 0 : 1; } /* return true if "str" begins with "prefix", case insensitive */ @@ -158,7 +158,7 @@ static int startsWith (char *prefix, char *str) if (strlen(prefix) >= strlen(str)) return 0; - return strnicmp(prefix,str,strlen(prefix)) ? 0 : 1; + return strnicmp(prefix, str, strlen(prefix)) ? 0 : 1; } /* append "app" to "ptr", allocating memory as needed */ @@ -167,26 +167,26 @@ static int startsWith (char *prefix, char *str) static void appendn (char **ptr, char *app, size_t count) { char *nptr = (char *) realloc(*ptr, strlen(*ptr) + - (count?count:strlen(app)) + 1); + (count ? count : strlen(app)) + 1); if (nptr == NULL) { - fprintf(stderr,"error: out of memory\n"); + fprintf(stderr, "error: out of memory\n"); free(*ptr); myExit(4); } *ptr = nptr; if (count) - strncat(*ptr,app,count); + strncat(*ptr, app, count); else - strcat(*ptr,app); + strcat(*ptr, app); } /* append "app" to "ptr", allocating memory as needed */ static void append (char **ptr, char *app) { - appendn(ptr,app,0); + appendn(ptr, app, 0); } /* if the string does not end with a backslash, add one */ @@ -194,7 +194,7 @@ static void append (char **ptr, char *app) static void appendBackSlash(char **str) { if ((*str)[strlen(*str)-1] != '\\') - append(str,"\\"); + append(str, "\\"); } /* copy count characters of "str" to "ptr", allocating memory as needed */ @@ -202,28 +202,28 @@ static void appendBackSlash(char **str) static void assignn (char **ptr, char *str, size_t count) { - char *nptr = (char *) realloc(*ptr, (count?count:strlen(str)) + 1); + char *nptr = (char *) realloc(*ptr, (count ? count : strlen(str)) + 1); if (nptr == NULL) { - fprintf(stderr,"error: out of memory\n"); + fprintf(stderr, "error: out of memory\n"); free(*ptr); myExit(4); } *ptr = nptr; if (count) { - strncpy(*ptr,str,count); + strncpy(*ptr, str, count); (*ptr)[count] = 0; } else - strcpy(*ptr,str); + strcpy(*ptr, str); } /* copy count characters of "str" to "ptr", allocating memory as needed */ static void assign (char **ptr, char *str) { - assignn(ptr,str,0); + assignn(ptr, str, 0); } /* get a copy of a Icarus Verilog registry string key */ @@ -235,11 +235,11 @@ static int GetRegistryKey(char *key, char **value) char *regKeyBuffer; DWORD regKeyType, regKeySize; - lrv = RegOpenKeyEx(HKEY_LOCAL_MACHINE,"Software\\Icarus Verilog",0,KEY_QUERY_VALUE,&hkKey); + lrv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, "Software\\Icarus Verilog", 0, KEY_QUERY_VALUE, &hkKey); if (lrv != ERROR_SUCCESS) return 0; - lrv = RegQueryValueEx(hkKey,key,NULL,®KeyType,NULL,®KeySize); + lrv = RegQueryValueEx(hkKey, key, NULL, ®KeyType, NULL, ®KeySize); if ((lrv != ERROR_SUCCESS) || (regKeyType != REG_SZ) || (!regKeySize)) { lrv = RegCloseKey(hkKey); return 0; @@ -248,7 +248,7 @@ static int GetRegistryKey(char *key, char **value) regKeyBuffer = (char *) malloc(regKeySize+1); if (!regKeyBuffer) { lrv = RegCloseKey(hkKey); - fprintf(stderr,"error: out of memory\n"); + fprintf(stderr, "error: out of memory\n"); myExit(4); } regKeyBuffer[regKeySize] = 0; /* makes sure there is a trailing NULL */ @@ -264,7 +264,7 @@ static int GetRegistryKey(char *key, char **value) RegCloseKey(hkKey); - assign(value,regKeyBuffer); + assign(value, regKeyBuffer); free(regKeyBuffer); return 1; @@ -296,8 +296,8 @@ static void SetRegistryKey(char *key, char *value) strlen(value)+1); RegCloseKey(hkKey); - printf("info: storing %s in Windows' registry entry\n",value); - printf(" HKEY_LOCAL_MACHINE\\Software\\Icarus Verilog\\%s\n",key); + printf("info: storing %s in Windows' registry entry\n", value); + printf(" HKEY_LOCAL_MACHINE\\Software\\Icarus Verilog\\%s\n", key); } /* parse the command line, assign results to global variable strings */ @@ -353,7 +353,7 @@ static int parse(int argc, char *argv[]) /* Check for compiled object files */ else if (endsIn(dot_o_ext, argv[idx])) { ++srcFileCnt; - append(&gstr.pOBJ," "); + append(&gstr.pOBJ, " "); append(&gstr.pOBJ, argv[idx]); if (!*gstr.pOUT) assignn(&gstr.pOUT, argv[idx], @@ -412,7 +412,7 @@ static int parse(int argc, char *argv[]) } /* In case there is a --name without source/object files */ - if (0 == srcFileCnt) assign(&gstr.pOUT,""); + if (0 == srcFileCnt) assign(&gstr.pOUT, ""); if (*gstr.pOUT) { /* We have a valid result file so add the .vpi extension */ @@ -435,23 +435,23 @@ static void checkMingwDir(char *root) char *path; initDynString(&path); - assign(&path,gstr.pMINGW); + assign(&path, gstr.pMINGW); appendBackSlash(&path); - append(&path,"bin\\"); + append(&path, "bin\\"); append(&path, gstr.pCCNAME); - append(&path,".exe"); + append(&path, ".exe"); irv = _stat(path,&stat_buf); deInitDynString(path); if (irv) { - fprintf(stderr,"error: %s\n", root); - fprintf(stderr," does not appear to be the valid root directory of\n"); - fprintf(stderr," MinGW. Use the -mingw option of iverilog-vpi.exe to\n"); - fprintf(stderr," point to the MinGW root directory. For a Windows command\n"); - fprintf(stderr," shell the option would be something like -mingw=c:\\mingw\n"); - fprintf(stderr," For a Cygwin shell the option would be something like\n"); - fprintf(stderr," -mingw=c:\\\\mingw\n"); + fprintf(stderr, "error: %s\n", root); + fprintf(stderr, " does not appear to be the valid root directory of\n"); + fprintf(stderr, " MinGW. Use the -mingw option of iverilog-vpi.exe to\n"); + fprintf(stderr, " point to the MinGW root directory. For a Windows command\n"); + fprintf(stderr, " shell the option would be something like -mingw=c:\\mingw\n"); + fprintf(stderr, " For a Cygwin shell the option would be something like\n"); + fprintf(stderr, " -mingw=c:\\\\mingw\n"); myExit(5); } } @@ -476,12 +476,12 @@ static void setup_mingw_environment(void) return; } else { - fprintf(stderr,"error: cannot locate the MinGW C compiler - either add its location\n"); - fprintf(stderr," to the PATH environment variable or use the -mingw option of\n"); - fprintf(stderr," iverilog-vpi.exe to point to the MinGW root directory. For\n"); - fprintf(stderr," a Windows command shell the option would be something like\n"); - fprintf(stderr," -mingw=c:\\mingw For a Cygwin shell the option would be\n"); - fprintf(stderr," something like -mingw=c:\\\\mingw\n"); + fprintf(stderr, "error: cannot locate the MinGW C compiler - either add its location\n"); + fprintf(stderr, " to the PATH environment variable or use the -mingw option of\n"); + fprintf(stderr, " iverilog-vpi.exe to point to the MinGW root directory. For\n"); + fprintf(stderr, " a Windows command shell the option would be something like\n"); + fprintf(stderr, " -mingw=c:\\mingw For a Cygwin shell the option would be\n"); + fprintf(stderr, " something like -mingw=c:\\\\mingw\n"); myExit(5); } @@ -518,13 +518,13 @@ static void setup_ivl_environment(void) GetModuleFileName(NULL, path, sizeof(path)); ptr = strrchr(path, '\\'); if (!ptr) { - fprintf(stderr,"error: couldn't find start of program name in command path '%s'\n", path); + fprintf(stderr, "error: couldn't find start of program name in command path '%s'\n", path); myExit(6); } *ptr = 0; ptr = strrchr(path, '\\'); if (!ptr) { - fprintf(stderr,"error: couldn't find start of bin directory in command path '%s'\n", path); + fprintf(stderr, "error: couldn't find start of bin directory in command path '%s'\n", path); myExit(6); } *ptr = 0; @@ -618,7 +618,7 @@ static void compile_and_link(void) compile(gstr.pCXSRC, gstr.pCXFLAGS, &gstr.pOBJ, &compile_errors, IVERILOG_VPI_CXX); if (compile_errors) { - fprintf(stderr,"iverilog-vpi: %d file(s) failed to compile.\n", + fprintf(stderr, "iverilog-vpi: %d file(s) failed to compile.\n", compile_errors); myExit(2); } @@ -649,7 +649,7 @@ int main(int argc, char *argv[]) { init(); - if (!parse(argc,argv)) usage(); + if (!parse(argc, argv)) usage(); setup_mingw_environment(); setup_ivl_environment(); From ac4f4cf1a0f87f5d14b30c31941286cd75ec1d2b Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 10 May 2015 13:19:51 +0100 Subject: [PATCH 023/595] Update man pages. Removed obsolete -m32 and -ivl options from iverilog-vpi man page and revised description of -mingw option. Also removed duplicate descriptions of --cflags, --ldflags, and --ldlibs options. Updated link to main iverilog web page in all man pages. --- driver/iverilog.man.in | 6 ++-- iverilog-vpi.man.in | 81 ++++++++++++++++++------------------------ vvp/vvp.man.in | 6 ++-- 3 files changed, 40 insertions(+), 53 deletions(-) diff --git a/driver/iverilog.man.in b/driver/iverilog.man.in index 07b12cea1..cbb78989a 100644 --- a/driver/iverilog.man.in +++ b/driver/iverilog.man.in @@ -1,4 +1,4 @@ -.TH iverilog 1 "December 16th, 2014" "" "Version %M.%m.%n %E" +.TH iverilog 1 "May 10th, 2015" "" "Version %M.%m.%n %E" .SH NAME iverilog - Icarus Verilog compiler @@ -520,14 +520,14 @@ Steve Williams (steve@icarus.com) .SH SEE ALSO vvp(1), -.BR "" +.BR "" Tips on using, debugging, and developing the compiler can be found at .BR "" .SH COPYRIGHT .nf -Copyright \(co 2002\-2014 Stephen Williams +Copyright \(co 2002\-2015 Stephen Williams This document can be freely redistributed according to the terms of the GNU General Public License version 2.0 diff --git a/iverilog-vpi.man.in b/iverilog-vpi.man.in index b1708bddf..e2814fced 100644 --- a/iverilog-vpi.man.in +++ b/iverilog-vpi.man.in @@ -1,10 +1,10 @@ -.TH iverilog-vpi 1 "April 17th, 2009" "" "Version %M.%m.%n %E" +.TH iverilog-vpi 1 "May 10th, 2015" "" "Version %M.%m.%n %E" .SH NAME iverilog-vpi - Compile front end for VPI modules .SH SYNOPSIS .B iverilog-vpi -[\-\-name=\fIname\fP] +[options] \fIsourcefile\fP... .SH DESCRIPTION @@ -15,9 +15,9 @@ list of C or C++ source files, and generates as output a linked VPI module. See the \fBvvp\fP(1) man page for a description of how the linked module is loaded by a simulation. -The output is named after the first source file. For example, if the -first source file is named \fIfoo.c\fP, the output becomes -\fIfoo.vpi\fP. +By default the output is named after the first source file. For +example, if the first source file is named \fIfoo.c\fP, the output +becomes \fIfoo.vpi\fP. .SH OPTIONS \fIiverilog\-vpi\fP accepts the following options: @@ -28,8 +28,8 @@ VPI modules to further reference external libraries. .TP 8 .B -I\fIdirectory\fP -Add \fIdirectory\fP to the list of directories that will be search for -header files. +Add \fIdirectory\fP to the list of directories that will be searched +for header files. .TP 8 .B -D\fIdefine\fP @@ -41,46 +41,38 @@ Normally, the output VPI module will be named after the first source file passed to the command. This flag sets the name (without the .vpi suffix) of the output vpi module. -.TP 8 -.B --install-dir -This flag causes the program to print the install directory for VPI -modules, then exit. It is a convenience for makefiles or automated -plug-in installers. - -.TP 8 -.B --cflags, --ldflags and --ldlibs -These flags provide compile time information. - .SH "PC-ONLY OPTIONS" -The PC port of \fIiverilog\-vpi\fP includes two special flags needed to -support the more intractable development environment. These flags help -the program locate parts that it needs. +When built as a native Windows program (using the MinGW toolchain), +by default \fIiverilog\-vpi\fP will attempt to locate the MinGW tools +needed to compile a VPI module on the system path (as set by the PATH +environment variable). As an alternative, the user may specify the +location of the MinGW tools via the following option. .TP 8 .B -mingw=\fIpath\fP -Tell the program the root of the Mingw compiler tool suite. The +Tell the program the root of the MinGW compiler tool suite. The \fBvvp\fP runtime is compiled with this compiler, and this is the -compiler that \fIiverilog\-vpi\fP expects to use to compile your source -code. This is normally not needed, and if you do use it, it is only -needed once. The compiler will save the \fIpath\fP in the registry for -use later. +compiler that \fIiverilog\-vpi\fP expects to use to compile your +source code. If this option accompanies a list of files, it will +apply to the current build only. If this option is provided on its +own, \fIiverilog\-vpi\fP will save the \fIpath\fP in the registry +and use that path in preference to the system path for subsequent +operations, avoiding the need to specify it on the command line +every time. + +.SH "INFORMATIONAL OPTIONS" + +\fIiverilog\-vpi\fP includes additional flags to let Makefile gurus +peek at the configuration of the \fIiverilog\fP installation. This way, +Makefiles can be written that handle complex VPI builds natively, and +without hard-coding values that depend on the system and installation. +If used at all, these options must be used one at a time, and without +any other options or directives. .TP 8 -.B -ivl=\fIpath\fP -Set for the use during compilation the root if the Icarus Verilog -install. This is the place where you installed Icarus Verilog when you -ran the installer. This flag is also only needed once, and the path is -stored in the registry for future use. - -.SH "UNIX-ONLY OPTIONS" - -The UNIX version of \fIiverilog\-vpi\fP includes additional flags to -let Makefile gurus peek at the configuration of the \fIiverilog\fP -installation. This way, Makefiles can be written that handle complex VPI -builds natively, and without hard-coding values that depend on the -system and installation. If used at all, these options must be -used one at a time, and without any other options or directives. +.B --install-dir +Print the install directory for VPI modules. .TP 8 .B --cflags @@ -95,11 +87,6 @@ Print the linker flags (LDFLAGS) needed to link a VPI module. .B --ldlibs Print the libraries (LDLIBS) needed to link a VPI module. -.TP 8 -.B -m32 -On 64bit systems that support it (and support vvp32) this flag -requests a 32bit vpi binary instead of the default 64bit binary. - .P Example GNU makefile that takes advantage of these flags: .IP "" 4 @@ -123,12 +110,12 @@ Steve Williams (steve@icarus.com) .SH SEE ALSO iverilog(1), vvp(1), -.BR "", -.BR "", +.BR "", +.BR "", .SH COPYRIGHT .nf -Copyright \(co 2002\-2009 Stephen Williams +Copyright \(co 2002\-2015 Stephen Williams This document can be freely redistributed according to the terms of the GNU General Public License version 2.0 diff --git a/vvp/vvp.man.in b/vvp/vvp.man.in index a6600b505..37a5bcb7c 100644 --- a/vvp/vvp.man.in +++ b/vvp/vvp.man.in @@ -1,4 +1,4 @@ -.TH vvp 1 "May 23rd, 2010" "" "Version %M.%m.%n %E" +.TH vvp 1 "May 10th, 2015" "" "Version %M.%m.%n %E" .SH NAME vvp - Icarus Verilog vvp runtime engine @@ -182,11 +182,11 @@ Steve Williams (steve@icarus.com) .SH SEE ALSO iverilog(1), iverilog\-vpi(1), -.BR "" +.BR "" .SH COPYRIGHT .nf -Copyright \(co 2001\-2010 Stephen Williams +Copyright \(co 2001\-2015 Stephen Williams This document can be freely redistributed according to the terms of the GNU General Public License version 2.0 From bb444b6178911505cb36baed6466cc28ea3c7b3d Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 13 May 2015 10:21:19 -0700 Subject: [PATCH 024/595] Snapshot 2015-05-13 --- verilog.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/verilog.spec b/verilog.spec index b3095447e..aae298568 100644 --- a/verilog.spec +++ b/verilog.spec @@ -1,6 +1,6 @@ #norootforbuild # -%define rev_date 20150105 +%define rev_date 20150513 # Normally, the suff-ix is %nil, meaning the suffix is to not be used. # But if the builder wants to make a suffixed package, he may set this # to a value (i.e. -test) to cause suffixes to be put in all the right From b6304129facb4c8d709bac9ce65ee02e27954419 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Fri, 15 May 2015 22:30:03 +0100 Subject: [PATCH 025/595] Fix for GutHub issue #64 - vvp interrupt/continue in Windows. Windows implements the original UNIX semantics for signal(), which means you have to re-establish the signal handler each time a signal is caught. --- vvp/schedule.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vvp/schedule.cc b/vvp/schedule.cc index a3dc7800f..9ed169fab 100644 --- a/vvp/schedule.cc +++ b/vvp/schedule.cc @@ -531,6 +531,12 @@ bool schedule_stopped(void) */ extern "C" void signals_handler(int) { +#ifdef __MINGW32__ + // Windows implements the original UNIX semantics for signal, + // so we have to re-establish the signal handler each time a + // signal is caught. + signal(SIGINT, &signals_handler); +#endif schedule_stopped_flag = true; } From c75498b1d486f05b7c8708074de04f12514b5feb Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 16 May 2015 00:39:03 +0100 Subject: [PATCH 026/595] Add -i (interactive) option to vvp. This forces to be unbuffered. This is useful when using the mintty terminal emulator in Windows (as used by MSYS2 and CygWin), which identifies as a pipe, not a tty. --- vvp/main.cc | 8 ++++++-- vvp/vvp.man.in | 5 ++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/vvp/main.cc b/vvp/main.cc index 94909d076..917f6322f 100644 --- a/vvp/main.cc +++ b/vvp/main.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2015 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 @@ -316,12 +316,13 @@ int main(int argc, char*argv[]) /* For non-interactive runs we do not want to run the interactive * debugger, so make $stop just execute a $finish. */ stop_is_finish = false; - while ((opt = getopt(argc, argv, "+hl:M:m:nNsvV")) != EOF) switch (opt) { + while ((opt = getopt(argc, argv, "+hil:M:m:nNsvV")) != EOF) switch (opt) { case 'h': fprintf(stderr, "Usage: vvp [options] input-file [+plusargs...]\n" "Options:\n" " -h Print this help message.\n" + " -i Interactive mode (unbuffered stdio).\n" " -l file Logfile, '-' for \n" " -M path VPI module directory\n" " -M - Clear VPI module path\n" @@ -332,6 +333,9 @@ int main(int argc, char*argv[]) " -v Verbose progress messages.\n" " -V Print the version information.\n" ); exit(0); + case 'i': + setvbuf(stdout, 0, _IONBF, 0); + break; case 'l': logfile_name = optarg; break; diff --git a/vvp/vvp.man.in b/vvp/vvp.man.in index 37a5bcb7c..650e853c4 100644 --- a/vvp/vvp.man.in +++ b/vvp/vvp.man.in @@ -4,7 +4,7 @@ vvp - Icarus Verilog vvp runtime engine .SH SYNOPSIS .B vvp -[\-nNsvV] [\-Mpath] [\-mmodule] [\-llogfile] inputfile [extended-args...] +[\-inNsvV] [\-Mpath] [\-mmodule] [\-llogfile] inputfile [extended-args...] .SH DESCRIPTION .PP @@ -16,6 +16,9 @@ command is not by itself executable on any platform. Instead, the .SH OPTIONS \fIvvp\fP accepts the following options: .TP 8 +.B -i +This flag causes all output to to be unbuffered. +.TP 8 .B -l\fIlogfile\fP This flag specifies a logfile where all MCI output goes. Specify logfile as '\-' to send log output to . $display and From a479bd6b163053f82c4aee35f49b67ddea07bf8c Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 17 May 2015 20:05:45 +0100 Subject: [PATCH 027/595] Fix for br977 - preprocessor macros substitute text inside token. When replacing macro formal parameters, the preprocessor should not replace matching strings that are not complete tokens. The test for this was incorrect, and failed when a match was found at the start of the replacement text. --- ivlpp/lexor.lex | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index ea84b86e0..5a95e4f6a 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -950,6 +950,11 @@ static size_t magic_cnt = 0; #define _STR1(x) #x #define _STR2(x) _STR1(x) +static int is_id_char(char c) +{ + return isalnum((int)c) || c == '_' || c == '$'; +} + /* * Find an argument, but only if it is not directly preceded by something * that would make it part of another simple identifier ([a-zA-Z0-9_$]). @@ -964,12 +969,8 @@ static char *find_arg(char*ptr, char*head, char*arg) cp = strstr(cp, arg); if (!cp) break; - /* If we are not at the start of the string verify that this - * match is not in the middle of another identifier. - */ - if (cp != head && - (isalnum((int)*(cp-1)) || *(cp-1) == '_' || *(cp-1) == '$' || - isalnum((int)*(cp+len)) || *(cp+len) == '_' || *(cp+len) == '$')) { + /* Verify that this match is not in the middle of another identifier. */ + if ((cp != head && is_id_char(cp[-1])) || is_id_char(cp[len])) { cp++; continue; } From 578a2543f7d19b8dd50a147e108e200914a0d999 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 17 May 2015 20:54:53 +0100 Subject: [PATCH 028/595] Fix for br975 - assertion failure due to duplicate declaration of struct var. Added proper error handling for duplicate declarations of all variable types. --- pform.cc | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/pform.cc b/pform.cc index 79cc05cf5..61965ef70 100644 --- a/pform.cc +++ b/pform.cc @@ -2422,7 +2422,10 @@ static PWire* pform_get_or_make_wire(const vlltype&li, perm_string name, ivl_variable_type_t dtype) { PWire*cur = pform_get_wire_in_scope(name); - if (cur) { + + // If the wire already exists but isn't yet fully defined, + // carry on adding details. + if (cur && cur->get_data_type() == IVL_VT_NO_TYPE) { // If this is not implicit ("implicit" meaning we don't // know what the type is yet) then set the type now. if (type != NetNet::IMPLICIT) { @@ -2440,6 +2443,18 @@ static PWire* pform_get_or_make_wire(const vlltype&li, perm_string name, return cur; } + // If the wire already exists and is fully defined, this + // must be a redeclaration. Start again with a new wire. + if (cur) { + LineInfo tloc; + FILE_NAME(&tloc, li); + cerr << tloc.get_fileline() << ": error: duplicate declaration " + "for net or variable '" << name << "' in '" + << pform_cur_module.front()->mod_name() << "'." << endl; + error_count += 1; + delete cur; + } + cur = new PWire(name, type, ptype, dtype); FILE_NAME(cur, li.text, li.first_line); @@ -3224,18 +3239,12 @@ template static void pform_set2_data_type(const struct vlltype&li, T*d } } -static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, +static void pform_set_enum(enum_type_t*enum_type, perm_string name, NetNet::Type net_type, std::list*attr) { PWire*cur = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, enum_type->base_type); - // A NULL is returned for a duplicate enumeration. - if (! cur) { - cerr << li.get_fileline() << ": error: Found duplicate " - << "enumeration named " << name << "." << endl; - error_count += 1; - return; - } + assert(cur); cur->set_signed(enum_type->signed_flag); @@ -3273,7 +3282,7 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, for (list::iterator cur = names->begin() ; cur != names->end() ; ++ cur) { perm_string txt = *cur; - pform_set_enum(li, enum_type, txt, net_type, attr); + pform_set_enum(enum_type, txt, net_type, attr); } } From 71b1546a7dd8d704a0c76f0a4262e3bd4b2c07d3 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 17 May 2015 21:59:05 +0100 Subject: [PATCH 029/595] Fail gracefully when an unpacked struct is declared. --- parse.y | 6 +++++- pform_struct_type.cc | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/parse.y b/parse.y index 948437000..787f409cb 100644 --- a/parse.y +++ b/parse.y @@ -1044,7 +1044,11 @@ data_type /* IEEE1800-2005: A.2.2.1 */ $$ = tmp; } | struct_data_type - { $$ = $1; } + { if (!$1->packed_flag) { + yyerror(@1, "sorry: Unpacked structs not supported."); + } + $$ = $1; + } | enum_data_type { $$ = $1; } | atom2_type signed_unsigned_opt diff --git a/pform_struct_type.cc b/pform_struct_type.cc index 766fc77e3..433e66a91 100644 --- a/pform_struct_type.cc +++ b/pform_struct_type.cc @@ -79,8 +79,8 @@ static void pform_set_struct_type(struct_type_t*struct_type, perm_string name, N return; } - // For now, can only handle packed structs. - ivl_assert(*struct_type, 0); + // For now, can only handle packed structs. The parser generates + // a "sorry" message, so no need to do anything here. } void pform_set_struct_type(struct_type_t*struct_type, list*names, NetNet::Type net_type, list*attr) From 61ace52f3179070c2969637bff6651f50aed8567 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 18 May 2015 23:16:53 +0100 Subject: [PATCH 030/595] Fix vlog95 target to not output data types in port declarations. This avoids variable redeclaration errors. --- tgt-vlog95/scope.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tgt-vlog95/scope.c b/tgt-vlog95/scope.c index e5043fa77..1f939d8d2 100644 --- a/tgt-vlog95/scope.c +++ b/tgt-vlog95/scope.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2014 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2010-2015 Cary R. (cygcary@yahoo.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -432,10 +432,13 @@ static void emit_sig_type(ivl_signal_t sig) } /* Check to see if we have a variable (reg) or a net. */ if (type == IVL_SIT_REG) { + /* The variable data type will be declared later, so here + we just want to declare the range and whether or not it + is signed. */ if (ivl_signal_integer(sig)) { - fprintf(vlog_out, " integer"); + /* nothing to do */ } else if (ivl_signal_data_type(sig) == IVL_VT_REAL) { - fprintf(vlog_out, " real"); + /* nothing to do */ } else { int msb, lsb; get_sig_msb_lsb(sig, &msb, &lsb); From a33bbecc98b91941f9fdb38bf9482f12f8c25592 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 24 Apr 2015 17:00:21 +0200 Subject: [PATCH 031/595] vhdlpp: VTypeRange::write_to_stream uses to/downto depending on the range boundaries. --- vhdlpp/vtype.cc | 6 ++---- vhdlpp/vtype.h | 6 +++--- vhdlpp/vtype_stream.cc | 6 ++++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index 17001977f..ee43570e7 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -273,11 +273,9 @@ void VTypeArray::evaluate_ranges(ScopeBase*scope) { } } -VTypeRange::VTypeRange(const VType*base, int64_t max_val, int64_t min_val) -: base_(base) +VTypeRange::VTypeRange(const VType*base, int64_t end_val, int64_t start_val) +: base_(base), end_(end_val), start_(start_val) { - max_ = max_val; - min_ = min_val; } VTypeRange::~VTypeRange() diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 5b00bc885..62b528240 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -275,10 +275,10 @@ class VTypeArray : public VType { class VTypeRange : public VType { public: - VTypeRange(const VType*base, int64_t max_val, int64_t min_val); + VTypeRange(const VType*base, int64_t end, int64_t start); ~VTypeRange(); - VType*clone() const { return new VTypeRange(base_->clone(), max_, min_); } + VType*clone() const { return new VTypeRange(base_->clone(), start_, end_); } // Get the type that is limited by the range. inline const VType* base_type() const { return base_; } @@ -289,7 +289,7 @@ class VTypeRange : public VType { private: const VType*base_; - int64_t max_, min_; + int64_t end_, start_; }; class VTypeEnum : public VType { diff --git a/vhdlpp/vtype_stream.cc b/vhdlpp/vtype_stream.cc index f625f190a..0ded586de 100644 --- a/vhdlpp/vtype_stream.cc +++ b/vhdlpp/vtype_stream.cc @@ -171,14 +171,16 @@ void VTypeRange::write_to_stream(ostream&fd) const // Detect some special cases that can be written as ieee or // standard types. if (const VTypePrimitive*tmp = dynamic_cast (base_)) { - if (min_==0 && max_==INT64_MAX && tmp->type()==VTypePrimitive::INTEGER) { + if (start_==0 && end_==INT64_MAX && tmp->type()==VTypePrimitive::INTEGER) { fd << "natural"; return; } } base_->write_to_stream(fd); - fd << " range " << min_ << " to " << max_; + fd << " range " << start_; + fd << (start_ < end_ ? " to " : " downto "); + fd << end_; } void VTypeRecord::write_to_stream(ostream&fd) const From ddc204391ee0829bd6b182cec193488b567a454b Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 24 Apr 2015 17:01:11 +0200 Subject: [PATCH 032/595] vhdlpp: Add 'sub' prefix for subtypes while emitting packages. --- vhdlpp/package.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/vhdlpp/package.cc b/vhdlpp/package.cc index df8f60c41..167c8a279 100644 --- a/vhdlpp/package.cc +++ b/vhdlpp/package.cc @@ -74,6 +74,9 @@ void Package::write_to_stream(ostream&fd) const if (is_global_type(cur->first)) continue; + if(!dynamic_cast(cur->second)) + fd << "sub"; + fd << "type " << cur->first << " is "; cur->second->write_type_to_stream(fd); fd << "; -- imported" << endl; @@ -85,6 +88,9 @@ void Package::write_to_stream(ostream&fd) const if (is_global_type(cur->first)) continue; + if(!dynamic_cast(cur->second)) + fd << "sub"; + fd << "type " << cur->first << " is "; cur->second->write_type_to_stream(fd); fd << ";" << endl; From 515ab40ffe0b70a3d3d30df259e479e8675df5e0 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 24 Apr 2015 17:15:51 +0200 Subject: [PATCH 033/595] vhdlpp: Special handling for string type emission. --- vhdlpp/vtype_stream.cc | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/vhdlpp/vtype_stream.cc b/vhdlpp/vtype_stream.cc index 0ded586de..2cf159db8 100644 --- a/vhdlpp/vtype_stream.cc +++ b/vhdlpp/vtype_stream.cc @@ -41,14 +41,16 @@ void VTypeArray::write_to_stream(ostream&fd) const // Special cases: std_logic_vector & string if (etype_ == &primitive_STDLOGIC) { fd << "std_logic_vector"; - if (! ranges_.empty() && ! ranges_[0].is_box()) { + if (!ranges_.empty() && !ranges_[0].is_box()) { + write_range_to_stream_(fd); + } + return; + } else if (etype_ == &primitive_CHARACTER) { + fd << "string"; + if (!ranges_.empty() && !ranges_[0].is_box()) { write_range_to_stream_(fd); } return; - } else if (etype_ == &primitive_CHARACTER && - ranges_.size() == 1 && ranges_[0].is_box()) { - fd << "string"; - return; } bool typedefed = false; @@ -104,6 +106,13 @@ void VTypeArray::write_type_to_stream(ostream&fd) const } return; } + else if (etype_ == &primitive_CHARACTER) { + fd << "string"; + if (! ranges_.empty() && ! ranges_[0].is_box()) { + write_range_to_stream_(fd); + } + return; + } fd << "array "; From 25458b8cc20dac76f7ba674e839ec3b11bbeeaa9 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 8 May 2015 15:55:26 +0200 Subject: [PATCH 034/595] vhdlpp: inout direction for ports. --- vhdlpp/entity.h | 2 +- vhdlpp/entity_emit.cc | 8 ++++++-- vhdlpp/entity_stream.cc | 3 +++ vhdlpp/parse.y | 1 + vhdlpp/subprogram_emit.cc | 3 +++ 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/vhdlpp/entity.h b/vhdlpp/entity.h index b93d6a369..8c41e52ab 100644 --- a/vhdlpp/entity.h +++ b/vhdlpp/entity.h @@ -27,7 +27,7 @@ # include "StringHeap.h" # include "LineInfo.h" -typedef enum { PORT_NONE=0, PORT_IN, PORT_OUT } port_mode_t; +typedef enum { PORT_NONE=0, PORT_IN, PORT_OUT, PORT_INOUT } port_mode_t; class Architecture; class Expression; diff --git a/vhdlpp/entity_emit.cc b/vhdlpp/entity_emit.cc index 268b36f7d..fd2077fdc 100644 --- a/vhdlpp/entity_emit.cc +++ b/vhdlpp/entity_emit.cc @@ -74,17 +74,21 @@ int Entity::emit(ostream&out) switch (port->mode) { case PORT_NONE: // Should not happen + cerr << get_fileline() << ": error: Undefined port direction." << endl; out << "NO_PORT " << port->name; break; case PORT_IN: out << "input "; - errors += decl.emit(out, port->name); break; case PORT_OUT: out << "output "; - errors += decl.emit(out, port->name); + break; + case PORT_INOUT: + out << "inout "; break; } + + errors += decl.emit(out, port->name); } cout << ")"; } diff --git a/vhdlpp/entity_stream.cc b/vhdlpp/entity_stream.cc index cd1e67334..dfde97c74 100644 --- a/vhdlpp/entity_stream.cc +++ b/vhdlpp/entity_stream.cc @@ -69,6 +69,9 @@ void ComponentBase::write_to_stream(ostream&fd) const case PORT_OUT: fd << "out "; break; + case PORT_INOUT: + fd << "inout "; + break; } item->type->write_to_stream(fd); diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 9e60453b1..0927022be 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -1584,6 +1584,7 @@ loop_statement mode : K_in { $$ = PORT_IN; } | K_out { $$ = PORT_OUT; } + | K_inout { $$ = PORT_INOUT; } ; mode_opt : mode {$$ = $1;} | {$$ = PORT_NONE;} ; diff --git a/vhdlpp/subprogram_emit.cc b/vhdlpp/subprogram_emit.cc index 5cb43e3a6..c2ae47cd8 100644 --- a/vhdlpp/subprogram_emit.cc +++ b/vhdlpp/subprogram_emit.cc @@ -50,6 +50,9 @@ int Subprogram::emit_package(ostream&fd) const case PORT_OUT: fd << "output "; break; + case PORT_INOUT: + fd << "inout "; + break; case PORT_NONE: fd << "inout /* PORT_NONE? */ "; break; From 9231ad51a41f3f81f2b4189c350410aec7ffe97a Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Sat, 16 May 2015 00:40:26 +0200 Subject: [PATCH 035/595] vhdlpp: generics without a default value are set to 1'bx. --- vhdlpp/entity_emit.cc | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/vhdlpp/entity_emit.cc b/vhdlpp/entity_emit.cc index fd2077fdc..62acac193 100644 --- a/vhdlpp/entity_emit.cc +++ b/vhdlpp/entity_emit.cc @@ -50,11 +50,14 @@ int Entity::emit(ostream&out) const InterfacePort*curp = *cur; if (cur != parms_.begin()) out << ", "; - out << "parameter \\" << curp->name << " "; + out << "parameter \\" << curp->name << " = "; if(curp->expr) { - out << "= "; errors += curp->expr->emit(out, this, 0); - } + } else { + // Unlike VHDL, Verilog module parameter port list + // elements are always assignments. Fill in the blank. + out << "1'bx"; + } } out << ") "; } From bb2e6782fa19a2f2dfba656b6b1766100bc7b1e3 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 18 May 2015 17:32:09 +0200 Subject: [PATCH 036/595] Copy constructor for LineInfo. --- libmisc/LineInfo.cc | 5 +++++ libmisc/LineInfo.h | 1 + vhdlpp/expression.cc | 1 + 3 files changed, 7 insertions(+) diff --git a/libmisc/LineInfo.cc b/libmisc/LineInfo.cc index 753b24970..c0daaff14 100644 --- a/libmisc/LineInfo.cc +++ b/libmisc/LineInfo.cc @@ -27,6 +27,11 @@ LineInfo::LineInfo() { } +LineInfo::LineInfo(const LineInfo&that) : + file_(that.file_), lineno_(that.lineno_) +{ +} + LineInfo::~LineInfo() { } diff --git a/libmisc/LineInfo.h b/libmisc/LineInfo.h index b212bc959..4d4c6beda 100644 --- a/libmisc/LineInfo.h +++ b/libmisc/LineInfo.h @@ -36,6 +36,7 @@ using namespace std; class LineInfo { public: LineInfo(); + LineInfo(const LineInfo&that); virtual ~LineInfo(); // Get a fully formatted file/lineno diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 77d80a4d6..949d568ae 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -311,6 +311,7 @@ ExpConditional::else_t::else_t(Expression*cond, std::list*tru) } ExpConditional::else_t::else_t(const else_t&other) +: LineInfo(other) { cond_ = other.cond_->clone(); for(std::list::const_iterator it = other.true_clause_.begin(); From bc83d2914a4b1ca58d665d8840bf204a1362074d Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 20 May 2015 12:02:22 +0200 Subject: [PATCH 037/595] vhdlpp: Corrected an error message for attributes. --- vhdlpp/expression_evaluate.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vhdlpp/expression_evaluate.cc b/vhdlpp/expression_evaluate.cc index b67cbd5da..54bf704b4 100644 --- a/vhdlpp/expression_evaluate.cc +++ b/vhdlpp/expression_evaluate.cc @@ -106,7 +106,7 @@ bool ExpAttribute::evaluate(ScopeBase*scope, int64_t&val) const const VTypeArray*arr = dynamic_cast(base_type); if (arr == 0) { cerr << endl << get_fileline() << ": error: " - << "Cannot apply the 'length attribute to non-array objects" + << "Cannot apply the '" << name_ << " attribute to non-array objects" << endl; ivl_assert(*this, false); return false; From 7aab315ce533cee5e9de781738ddeefc3ac3fb64 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 20 May 2015 17:30:07 +0200 Subject: [PATCH 038/595] vhdlpp: Allow assigning values to inout ports. --- vhdlpp/expression_elaborate.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 5f54fc66a..30985fa53 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -112,7 +112,7 @@ int ExpName::elaborate_lval_(Entity*ent, ScopeBase*scope, bool is_sequ, ExpName* const VType*found_type = 0; if (const InterfacePort*cur = ent->find_port(name_)) { - if (cur->mode != PORT_OUT) { + if (cur->mode != PORT_OUT && cur->mode != PORT_INOUT) { cerr << get_fileline() << ": error: Assignment to " "input port " << name_ << "." << endl; return errors + 1; @@ -216,7 +216,7 @@ int ExpName::elaborate_lval(Entity*ent, ScopeBase*scope, bool is_sequ) const VType*found_type = 0; if (const InterfacePort*cur = ent->find_port(name_)) { - if (cur->mode != PORT_OUT) { + if (cur->mode != PORT_OUT && cur->mode != PORT_INOUT) { cerr << get_fileline() << ": error: Assignment to " "input port " << name_ << "." << endl; return errors += 1; From 51d7237d5289d380d816a30df0340635aec16339 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 21 May 2015 01:25:34 +0200 Subject: [PATCH 039/595] vhdlpp: Display error message for undefined generic values. --- vhdlpp/architec_emit.cc | 16 ++++++++++++++++ vhdlpp/entity.h | 1 + 2 files changed, 17 insertions(+) diff --git a/vhdlpp/architec_emit.cc b/vhdlpp/architec_emit.cc index cf18cdd84..d0d3fb1ff 100644 --- a/vhdlpp/architec_emit.cc +++ b/vhdlpp/architec_emit.cc @@ -150,6 +150,22 @@ int ComponentInstantiation::emit(ostream&out, Entity*ent, Architecture*arc) arc->set_cur_component(this); + if(ComponentBase*comp = arc->find_component(cname_)) { + const std::vector& generics = comp->get_generics(); + + if(generics.size() != generic_map_.size()) + // Display an error for generics that do not have neither + // default nor component specific value defined + for(vector::const_iterator it = generics.begin(); + it != generics.end(); ++it) { + if(!(*it)->expr && generic_map_.count((*it)->name) == 0) { + cerr << get_fileline() << ": generic " << (*it)->name << + "value is not defined" << endl; + ++errors; + } + } + } + out << cname_; if (! generic_map_.empty()) { out << " #("; diff --git a/vhdlpp/entity.h b/vhdlpp/entity.h index 8c41e52ab..5e183d1a5 100644 --- a/vhdlpp/entity.h +++ b/vhdlpp/entity.h @@ -63,6 +63,7 @@ class ComponentBase : public LineInfo { const InterfacePort* find_port(perm_string by_name) const; const InterfacePort* find_generic(perm_string by_name) const; + const std::vector& get_generics() const { return parms_; } // Declare the ports for the entity. The parser calls this // method with a list of interface elements that were parsed From ab688613ccfd792e824bff22af287cdf0c023f5b Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Thu, 21 May 2015 23:57:45 +0100 Subject: [PATCH 040/595] Fix for br978 - assertion involving addition of $ivlh_to_unsigned() result. $ivlh_to_unsigned, unlike $signed and $signed, can cause a reduction in width. The shared PECallFunction::cast_to_width_ method did not support this. --- elab_expr.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elab_expr.cc b/elab_expr.cc index e309f6162..8c53b6066 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1418,7 +1418,7 @@ NetExpr*PECallFunction::cast_to_width_(NetExpr*expr, unsigned wid) const const. This is a more efficient result. */ if (NetEConst*tmp = dynamic_cast(expr)) { tmp->cast_signed(signed_flag_); - if (wid > tmp->expr_width()) { + if (wid != tmp->expr_width()) { tmp = new NetEConst(verinum(tmp->value(), wid)); tmp->set_line(*this); delete expr; From 0fc10e3e70d4d65e5f31db66fcf710dc97411de5 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Fri, 22 May 2015 18:11:24 +0100 Subject: [PATCH 041/595] Fix for br979 part 1 - strip leading/trailing space from macro actual args. Although the IEEE standard doesn't explicitly state this is required, the examples added in the SystemVerilog standard show that this is expected. Also add a preprocessor lexical rule to recognise `` inside a macro definition when it is not immediately followed by an identifier. --- ivlpp/lexor.lex | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index 5a95e4f6a..56022aa72 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -1,7 +1,7 @@ %option prefix="yy" %{ /* - * Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2015 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 @@ -532,6 +532,8 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif) } } +`` { if (istack->file != NULL) ECHO; } + \( { BEGIN(MA_ADD); macro_start_args(); } {W} {} @@ -568,8 +570,12 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif) "(" { macro_add_to_arg(0); ma_parenthesis_level++; } -"," { if (ma_parenthesis_level > 0) macro_add_to_arg(0); - else macro_finish_arg(); } +"," { + if (ma_parenthesis_level > 0) + macro_add_to_arg(0); + else + macro_finish_arg(); +} ")" { if (ma_parenthesis_level > 0) { @@ -1300,14 +1306,30 @@ static void macro_add_to_arg(int is_white_space) static void macro_finish_arg(void) { - char* tail = &def_buf[def_buf_size - def_buf_free]; + int offs; + char* head; + char* tail; check_for_max_args(); + offs = def_argo[def_argc-1] + def_argl[def_argc-1] + 1; + head = &def_buf[offs]; + tail = &def_buf[def_buf_size - def_buf_free]; + + /* Eat any leading and trailing white space. */ + if ((head < tail) && (*head == ' ')) { + offs++; + head++; + } + if ((tail > head) && (*(tail-1) == ' ')) { + def_buf_free++; + tail--; + } + *tail = 0; - def_argo[def_argc] = def_argo[def_argc-1] + def_argl[def_argc-1] + 1; - def_argl[def_argc] = tail - def_argv(def_argc); + def_argo[def_argc] = offs; + def_argl[def_argc] = tail - head; def_buf_free -= 1; def_argc++; From d5b41853fd95567fdea642772fd0bf351336c354 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Fri, 22 May 2015 18:44:25 +0100 Subject: [PATCH 042/595] Fix for br979 part 2 - handle blank lines in macro definition continuation. --- ivlpp/lexor.lex | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/ivlpp/lexor.lex b/ivlpp/lexor.lex index 56022aa72..fc382fd70 100644 --- a/ivlpp/lexor.lex +++ b/ivlpp/lexor.lex @@ -39,6 +39,7 @@ static void def_finish(void); static void def_undefine(void); static void do_define(void); static int def_is_done(void); +static void def_continue(void); static int is_defined(const char*name); static int macro_needs_args(const char*name); @@ -358,6 +359,8 @@ keywords (include|define|undef|ifdef|ifndef|else|elseif|endif) if (def_is_done()) { def_finish(); yy_pop_state(); + } else { + def_continue(); } istack->lineno += 1; @@ -1130,6 +1133,14 @@ static int def_is_done(void) return !define_continue_flag; } +/* + * Reset the define_continue_flag. + */ +static void def_continue(void) +{ + define_continue_flag = 0; +} + /* * After some number of calls to do_define, this function is called to * assigned value to the parsed name. If there is no value, then From 33c651aa0094b7ba2593e89231d7ce5ddc4f0f52 Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Wed, 20 May 2015 15:46:04 -0700 Subject: [PATCH 043/595] Spelling fixes in .txt files --- ivlpp/ivlpp.txt | 2 +- tgt-vvp/README.txt | 4 ++-- vvp/README.txt | 12 ++++++------ vvp/opcodes.txt | 8 ++++---- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/ivlpp/ivlpp.txt b/ivlpp/ivlpp.txt index fe6071f53..a95d05126 100644 --- a/ivlpp/ivlpp.txt +++ b/ivlpp/ivlpp.txt @@ -95,7 +95,7 @@ keys, with their corresponding values, are: This is exactly the same as the "-Dname=" described above. I: - This is exctly the same as "-I". + This is exactly the same as "-I". relative include: The can be "true" or "false". This enables "relative diff --git a/tgt-vvp/README.txt b/tgt-vvp/README.txt index 4242b1b09..f07323021 100644 --- a/tgt-vvp/README.txt +++ b/tgt-vvp/README.txt @@ -3,7 +3,7 @@ THE VVP TARGET SYMBOL NAME CONVENTIONS -There are some naming conventions that the vp target uses for +There are some naming conventions that the vvp target uses for generating symbol names. * wires and regs @@ -30,4 +30,4 @@ the drivers are first fed into a resolver (or a tree of resolvers) to form a single output that is the nexus. The nexus, then, feeds its output to the inputs of other gates, or to -the .net objects in the design. \ No newline at end of file +the .net objects in the design. diff --git a/vvp/README.txt b/vvp/README.txt index 27827d9eb..b1a98768d 100644 --- a/vvp/README.txt +++ b/vvp/README.txt @@ -218,8 +218,8 @@ only. The function of a UDP is defined via a table. The rows of the table are strings which describe input states or edges, and the new output -state. Combinatorial UDPs require one character for each input, and -one character at the end for the output state. Sequential UDPs need +state. Combinatorial UDPs require one character for each input, and +one character at the end for the output state. Sequential UDPs need an additional char for the current state, which is the first char of the row. @@ -227,7 +227,7 @@ Any input transition or the new state must match at most one row (or all matches must provide the same output state). If no row matches, the output becomes 1'bx. -The output state can be specified as "0", "1", or "x". Sequential +The output state can be specified as "0", "1", or "x". Sequential UDPs may also have "-": no change. An input or current output state can be @@ -256,7 +256,7 @@ A combinatorial UDP is defined like this: .udp/comb "", , "", "", ... ; is a label that identifies the UDP. is the number of -inputs. "" is there for public identification. Sequential UDPs +inputs. "" is there for public identification. Sequential UDPs need an additional initialization value: .udp/sequ "", , , "", "", ... ; @@ -535,8 +535,8 @@ implicit from these numbers. The is then the input source. SUBSTITUTION STATEMENTS: -The substition statement doesn't have a direct analog in Verilog, it -only turns up in synthesis. It is a sorthand for forms like this: +The substitution statement doesn't have a direct analog in Verilog, it +only turns up in synthesis. It is a shorthand for forms like this: foo = ; foo[n] = ; diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index bef0c887b..97ae6100f 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -118,7 +118,7 @@ event control registers to determine when to perform the assign. %evctl is used to set the event control information. * %assign/v0 , , (XXXX Old description) -* %assign/v0/d , , (XXXX Old description +* %assign/v0/d , , (XXXX Old description) * %assign/v0/e , (XXXX Old description) The %assign/v0 instruction is a vector version of non-blocking @@ -142,8 +142,8 @@ assignments. For blocking assignments, see %set/v. * %assign/vec4/d , * %assign/vec4/e -The %assign/vec4 instruction if a vec4 version of non-blocking -assignment, The is the number lf clock ticks in the future +The %assign/vec4 instruction is a vec4 version of non-blocking +assignment. The is the number of clock ticks in the future where the assignment should schedule, and the value to assign is pulled from the vec4 stack. @@ -536,7 +536,7 @@ part comes from the width of the popped value, and the is an index register that contains the canonical offset where the value sets written. -The %foce/vec4/off instruction will test the value if flags[4], and if +The %force/vec4/off instruction will test the value of flags[4], and if it is 1, will suppress the actual assignment. This is intended to help with detection of invalid index expressions. From e6c6f6c81ebe5240418f8fc47da058b8416929fc Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 3 Jun 2015 10:00:35 -0700 Subject: [PATCH 044/595] Use fwrite to write $display output, instead of fprintf This change makes it safe to write non-ascii characters, which is an issue when the %u format is used. --- vpi/sys_display.c | 59 +++++++++++++++++++++-------------------------- vpi_user.h | 4 ++++ vvp/vpi_mcd.cc | 18 +++++++++++++++ vvp/vvp.def | 1 + 4 files changed, 49 insertions(+), 33 deletions(-) diff --git a/vpi/sys_display.c b/vpi/sys_display.c index ad36a1fbd..98446b8a1 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -65,6 +65,23 @@ static PLI_INT32 my_mcd_printf(PLI_UINT32 mcd, const char *fmt, ...) return r; } +static void my_mcd_rawwrite(PLI_UINT32 mcd, const char*buf, size_t count) +{ + if (IS_MCD(mcd)) { + vpip_mcd_rawwrite(mcd, buf, count); + } else { + FILE*fp = vpi_get_file(mcd); + if (fp) { + while (count > 0) { + size_t rc = fwrite(buf, 1, count, fp); + if (rc <= 0) break; + count -= rc; + buf += rc; + } + } + } +} + struct timeformat_info_s timeformat_info = { 0, 0, 0, 20 }; struct strobe_cb_info { @@ -1198,7 +1215,7 @@ static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) vpiHandle callh, argv, scope; struct strobe_cb_info info; char* result; - unsigned int size, location=0; + unsigned int size; PLI_UINT32 fd_mcd; callh = vpi_handle(vpiSysTfCall, 0); @@ -1247,17 +1264,9 @@ static PLI_INT32 sys_display_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) /* Because %u and %z may put embedded NULL characters into the * returned string strlen() may not match the real size! */ result = get_display(&size, &info); - while (location < size) { - if (result[location] == '\0') { - my_mcd_printf(fd_mcd, "%c", '\0'); - location += 1; - } else { - my_mcd_printf(fd_mcd, "%s", &result[location]); - location += strlen(&result[location]); - } - } + my_mcd_rawwrite(fd_mcd, result, size); if ((strncmp(name,"$display",8) == 0) || - (strncmp(name,"$fdisplay",9) == 0)) my_mcd_printf(fd_mcd, "\n"); + (strncmp(name,"$fdisplay",9) == 0)) my_mcd_rawwrite(fd_mcd, "\n", 1); free(info.filename); free(info.items); @@ -1282,20 +1291,12 @@ static PLI_INT32 strobe_cb(p_cb_data cb) if ((! IS_MCD(info->fd_mcd) && vpi_get_file(info->fd_mcd) != NULL) || ( IS_MCD(info->fd_mcd) && my_mcd_printf(info->fd_mcd, "") != EOF)) { char* result; - unsigned int size, location=0; + unsigned int size; /* Because %u and %z may put embedded NULL characters into the * returned string strlen() may not match the real size! */ result = get_display(&size, info); - while (location < size) { - if (result[location] == '\0') { - my_mcd_printf(info->fd_mcd, "%c", '\0'); - location += 1; - } else { - my_mcd_printf(info->fd_mcd, "%s", &result[location]); - location += strlen(&result[location]); - } - } - my_mcd_printf(info->fd_mcd, "\n"); + my_mcd_rawwrite(info->fd_mcd, result, size); + my_mcd_rawwrite(info->fd_mcd, "\n", 1); free(result); } @@ -1397,23 +1398,15 @@ static int monitor_enabled = 1; static PLI_INT32 monitor_cb_2(p_cb_data cb) { char* result; - unsigned int size, location=0; + unsigned int size; (void)cb; /* Parameter is not used. */ /* Because %u and %z may put embedded NULL characters into the * returned string strlen() may not match the real size! */ result = get_display(&size, &monitor_info); - while (location < size) { - if (result[location] == '\0') { - my_mcd_printf(monitor_info.fd_mcd, "%c", '\0'); - location += 1; - } else { - my_mcd_printf(monitor_info.fd_mcd, "%s", &result[location]); - location += strlen(&result[location]); - } - } - my_mcd_printf(monitor_info.fd_mcd, "\n"); + my_mcd_rawwrite(monitor_info.fd_mcd, result, size); + my_mcd_rawwrite(monitor_info.fd_mcd, "\n", 1); monitor_scheduled = 0; free(result); return 0; diff --git a/vpi_user.h b/vpi_user.h index 52f9a5f78..8fb8b12d8 100644 --- a/vpi_user.h +++ b/vpi_user.h @@ -632,6 +632,10 @@ extern void vpip_set_return_value(int value); extern s_vpi_vecval vpip_calc_clog2(vpiHandle arg); extern void vpip_make_systf_system_defined(vpiHandle ref); + /* Perform fwrite to mcd files. This is used to write raw data, + which may include nulls. */ +extern void vpip_mcd_rawwrite(PLI_UINT32 mcd, const char*buf, size_t count); + /* Return driver information for a net bit. The information is returned in the 'counts' array as follows: counts[0] - number of drivers driving '0' onto the net diff --git a/vvp/vpi_mcd.cc b/vvp/vpi_mcd.cc index 7a092c3c7..b64e5ce35 100644 --- a/vvp/vpi_mcd.cc +++ b/vvp/vpi_mcd.cc @@ -230,6 +230,24 @@ extern "C" PLI_INT32 vpi_mcd_printf(PLI_UINT32 mcd, const char *fmt, ...) return r; } +extern "C" void vpip_mcd_rawwrite(PLI_UINT32 mcd, const char*buf, size_t cnt) +{ + if (!IS_MCD(mcd)) return; + + for(int idx = 0; idx < 31; idx += 1) { + if (((mcd>>idx) & 1) == 0) + continue; + + if (mcd_table[idx].fp == 0) + continue; + + fwrite(buf, 1, cnt, mcd_table[idx].fp); + if (idx == 0 && logfile) + fwrite(buf, 1, cnt, mcd_table[idx].fp); + + } +} + extern "C" PLI_INT32 vpi_mcd_flush(PLI_UINT32 mcd) { int rc = 0; diff --git a/vvp/vvp.def b/vvp/vvp.def index 20434df84..c49f79400 100644 --- a/vvp/vvp.def +++ b/vvp/vvp.def @@ -41,4 +41,5 @@ vpip_calc_clog2 vpip_count_drivers vpip_format_strength vpip_make_systf_system_defined +vpip_mcd_rawwrite vpip_set_return_value From fbedf4ae222a682db44e519c8069c8af39012637 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 3 Jun 2015 11:16:07 -0700 Subject: [PATCH 045/595] Snapshot 2015-06-03 --- verilog.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/verilog.spec b/verilog.spec index aae298568..1bfebea82 100644 --- a/verilog.spec +++ b/verilog.spec @@ -1,6 +1,6 @@ #norootforbuild # -%define rev_date 20150513 +%define rev_date 20150603 # Normally, the suff-ix is %nil, meaning the suffix is to not be used. # But if the builder wants to make a suffixed package, he may set this # to a value (i.e. -test) to cause suffixes to be put in all the right From 05d591ccd6627e607f295bf00804ec41e91a5608 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 3 Jun 2015 14:32:04 -0700 Subject: [PATCH 046/595] Fix broken write to log files. --- vvp/vpi_mcd.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vvp/vpi_mcd.cc b/vvp/vpi_mcd.cc index b64e5ce35..df2505aee 100644 --- a/vvp/vpi_mcd.cc +++ b/vvp/vpi_mcd.cc @@ -243,7 +243,7 @@ extern "C" void vpip_mcd_rawwrite(PLI_UINT32 mcd, const char*buf, size_t cnt) fwrite(buf, 1, cnt, mcd_table[idx].fp); if (idx == 0 && logfile) - fwrite(buf, 1, cnt, mcd_table[idx].fp); + fwrite(buf, 1, cnt, logfile); } } From 7af3280215e5c6912eff4e4bf383d114f388a81c Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 4 Jun 2015 09:49:12 -0700 Subject: [PATCH 047/595] Update cppcheck suppression file in VPI --- vpi/cppcheck.sup | 154 +++++++++++++++++++++++------------------------ 1 file changed, 77 insertions(+), 77 deletions(-) diff --git a/vpi/cppcheck.sup b/vpi/cppcheck.sup index fc7332cff..94f478505 100644 --- a/vpi/cppcheck.sup +++ b/vpi/cppcheck.sup @@ -4,7 +4,7 @@ // fstapi.c from GTKWave obsoleteFunctionsasctime:fstapi.c:929 -obsoleteFunctionsalloca:fstapi.c:2303 +obsoleteFunctionsalloca:fstapi.c:2304 unreadVariable:fstapi.c:1647 variableScope:fstapi.c:665 variableScope:fstapi.c:1337 @@ -12,134 +12,134 @@ variableScope:fstapi.c:1338 variableScope:fstapi.c:1395 variableScope:fstapi.c:1978 variableScope:fstapi.c:2107 -variableScope:fstapi.c:2538 -variableScope:fstapi.c:2539 -variableScope:fstapi.c:2730 -variableScope:fstapi.c:2731 -variableScope:fstapi.c:2735 -variableScope:fstapi.c:2851 -variableScope:fstapi.c:2890 -variableScope:fstapi.c:2891 -variableScope:fstapi.c:3609 -variableScope:fstapi.c:3783 +variableScope:fstapi.c:2540 +variableScope:fstapi.c:2541 +variableScope:fstapi.c:2732 +variableScope:fstapi.c:2733 +variableScope:fstapi.c:2737 +variableScope:fstapi.c:2853 +variableScope:fstapi.c:2892 +variableScope:fstapi.c:2893 +variableScope:fstapi.c:3611 variableScope:fstapi.c:3785 -variableScope:fstapi.c:4227 -variableScope:fstapi.c:4228 -variableScope:fstapi.c:4237 -variableScope:fstapi.c:4500 -variableScope:fstapi.c:4771 -variableScope:fstapi.c:4774 -variableScope:fstapi.c:5268 -variableScope:fstapi.c:5272 -variableScope:fstapi.c:5273 -variableScope:fstapi.c:5429 -variableScope:fstapi.c:5487 -variableScope:fstapi.c:5800 -variableScope:fstapi.c:5803 -variableScope:fstapi.c:6039 -variableScope:fstapi.c:6144 -variableScope:fstapi.c:6145 -variableScope:fstapi.c:6176 -variableScope:fstapi.c:6404 +variableScope:fstapi.c:3787 +variableScope:fstapi.c:4229 +variableScope:fstapi.c:4230 +variableScope:fstapi.c:4239 +variableScope:fstapi.c:4502 +variableScope:fstapi.c:4773 +variableScope:fstapi.c:4776 +variableScope:fstapi.c:5270 +variableScope:fstapi.c:5274 +variableScope:fstapi.c:5275 +variableScope:fstapi.c:5431 +variableScope:fstapi.c:5489 +variableScope:fstapi.c:5802 +variableScope:fstapi.c:5805 +variableScope:fstapi.c:6041 +variableScope:fstapi.c:6146 +variableScope:fstapi.c:6147 +variableScope:fstapi.c:6178 +variableScope:fstapi.c:6406 // These functions are not used by Icarus // fstReaderClrFacProcessMask() -unusedFunction:fstapi.c:3341 +unusedFunction:fstapi.c:3343 // fstReaderClrFacProcessMaskAll() -unusedFunction:fstapi.c:3370 +unusedFunction:fstapi.c:3372 // fstReaderGetAliasCount() -unusedFunction:fstapi.c:3433 +unusedFunction:fstapi.c:3435 // fstReaderGetCurrentFlatScope() -unusedFunction:fstapi.c:3179 +unusedFunction:fstapi.c:3181 // fstReaderGetAliasCount() -unusedFunction:fstapi.c:3276 +unusedFunction:fstapi.c:3278 // fstReaderGetCurrentScopeUserInfo() -unusedFunction:fstapi.c:3193 +unusedFunction:fstapi.c:3195 // fstReaderGetDateString() -unusedFunction:fstapi.c:3461 +unusedFunction:fstapi.c:3463 // fstReaderGetDoubleEndianMatchState() -unusedFunction:fstapi.c:3447 +unusedFunction:fstapi.c:3449 // fstReaderGetDumpActivityChangeTime() -unusedFunction:fstapi.c:3489 +unusedFunction:fstapi.c:3491 // fstReaderGetDumpActivityChangeValue() -unusedFunction:fstapi.c:3504 +unusedFunction:fstapi.c:3506 // fstReaderGetEndTime() -unusedFunction:fstapi.c:3398 +unusedFunction:fstapi.c:3400 // fstReaderGetFacProcessMask() -unusedFunction:fstapi.c:3304 +unusedFunction:fstapi.c:3306 // fstReaderGetFileType() -unusedFunction:fstapi.c:3468 +unusedFunction:fstapi.c:3470 // fstReaderGetFseekFailed() -unusedFunction:fstapi.c:3289 +unusedFunction:fstapi.c:3291 // fstReaderGetMaxHandle() -unusedFunction:fstapi.c:3426 +unusedFunction:fstapi.c:3428 // fstReaderGetMemoryUsedByWriter() -unusedFunction:fstapi.c:3405 +unusedFunction:fstapi.c:3407 // fstReaderGetNumberDumpActivityChanges() -unusedFunction:fstapi.c:3482 +unusedFunction:fstapi.c:3484 // fstReaderGetScopeCount() -unusedFunction:fstapi.c:3412 +unusedFunction:fstapi.c:3414 // fstReaderGetStartTime() -unusedFunction:fstapi.c:3391 +unusedFunction:fstapi.c:3393 // fstReaderGetTimescale() -unusedFunction:fstapi.c:3384 +unusedFunction:fstapi.c:3386 // fstReaderGetTimezero() -unusedFunction:fstapi.c:3475 +unusedFunction:fstapi.c:3477 // fstReaderGetValueChangeSectionCount() -unusedFunction:fstapi.c:3440 +unusedFunction:fstapi.c:3442 // fstReaderGetValueFromHandleAtTime() -unusedFunction:fstapi.c:5682 +unusedFunction:fstapi.c:5684 // fstReaderGetVarCount() -unusedFunction:fstapi.c:3419 +unusedFunction:fstapi.c:3421 // fstReaderGetVersionString() -unusedFunction:fstapi.c:3454 +unusedFunction:fstapi.c:3456 // fstReaderIterBlocks() -unusedFunction:fstapi.c:4649 +unusedFunction:fstapi.c:4651 // fstReaderIterBlocksSetNativeDoublesOnCallback() -unusedFunction:fstapi.c:3554 +unusedFunction:fstapi.c:3556 // fstReaderIterateHier() -unusedFunction:fstapi.c:3779 +unusedFunction:fstapi.c:3781 // fstReaderIterateHierRewind() -unusedFunction:fstapi.c:3759 +unusedFunction:fstapi.c:3761 // fstReaderOpen() -unusedFunction:fstapi.c:4547 +unusedFunction:fstapi.c:4549 // fstReaderOpenForUtilitiesOnly() -unusedFunction:fstapi.c:4539 +unusedFunction:fstapi.c:4541 // fstReaderPushScope() -unusedFunction:fstapi.c:3241 +unusedFunction:fstapi.c:3243 // fstReaderResetScope() -unusedFunction:fstapi.c:3230 +unusedFunction:fstapi.c:3232 // fstReaderSetFacProcessMask() -unusedFunction:fstapi.c:3323 +unusedFunction:fstapi.c:3325 // fstReaderSetFacProcessMaskAll() -unusedFunction:fstapi.c:3359 +unusedFunction:fstapi.c:3361 // fstReaderSetLimitTimeRange() -unusedFunction:fstapi.c:3519 +unusedFunction:fstapi.c:3521 // fstReaderSetUnlimitedTimeRange() -unusedFunction:fstapi.c:3532 +unusedFunction:fstapi.c:3534 // fstReaderSetVcdExtensions() -unusedFunction:fstapi.c:3543 +unusedFunction:fstapi.c:3545 // fstUtilityEscToBin() -unusedFunction:fstapi.c:6482 +unusedFunction:fstapi.c:6484 // fstWriterCreateVar2() -unusedFunction:fstapi.c:2525 +unusedFunction:fstapi.c:2527 // fstWriterEmitVariableLengthValueChange() -unusedFunction:fstapi.c:2844 +unusedFunction:fstapi.c:2846 // fstWriterGetFseekFailed() -unusedFunction:fstapi.c:2508 +unusedFunction:fstapi.c:2510 // fstWriterSetAttrEnd() -unusedFunction:fstapi.c:2711 +unusedFunction:fstapi.c:2713 // fstWriterSetComment() -unusedFunction:fstapi.c:2357 +unusedFunction:fstapi.c:2359 // fstWriterSetEnvVar() -unusedFunction:fstapi.c:2369 +unusedFunction:fstapi.c:2371 // fstWriterSetFileType() unusedFunction:fstapi.c:2234 // fstWriterSetParallelMode() -unusedFunction:fstapi.c:2468 +unusedFunction:fstapi.c:2470 // fstWriterSetTimezero() -unusedFunction:fstapi.c:2433 +unusedFunction:fstapi.c:2435 // fstWriterSetValueList() -unusedFunction:fstapi.c:2363 +unusedFunction:fstapi.c:2365 // These functions are not used by Icarus //unusedFunction:fstapi.c:226 From 2739f83702dd8063def059af31e2a2b7b7867db7 Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Tue, 2 Jun 2015 10:40:24 -0700 Subject: [PATCH 048/595] Spelling fixes in C and C++ comments --- PTask.cc | 2 +- elab_expr.cc | 4 ++-- elaborate.cc | 2 +- ivl_target.h | 6 +++--- libveriuser/getsimtime.c | 2 +- netlist.h | 6 +++--- netmisc.cc | 2 +- nettypes.cc | 2 +- pform_types.h | 2 +- synth2.cc | 4 ++-- tgt-vlog95/vlog95.c | 2 +- tgt-vvp/eval_vec4.c | 6 +++--- tgt-vvp/vvp_priv.h | 4 ++-- tgt-vvp/vvp_process.c | 6 +++--- vhdlpp/parse.y | 2 +- vpi/sys_darray.c | 2 +- vpi/table_mod.c | 2 +- vvp/compile.cc | 2 +- vvp/compile.h | 2 +- vvp/dff.cc | 2 +- vvp/resolv.cc | 2 +- vvp/vpi_signal.cc | 2 +- vvp/vthread.cc | 8 ++++---- 23 files changed, 37 insertions(+), 37 deletions(-) diff --git a/PTask.cc b/PTask.cc index 75e68bc22..034f38da6 100644 --- a/PTask.cc +++ b/PTask.cc @@ -41,7 +41,7 @@ void PTaskFunc::set_this(class_type_t*type, PWire*this_wire) assert(this_type_ == 0); this_type_ = type; - // Push a synthethis argument that is the "this" value. + // Push a synthesis argument that is the "this" value. if (ports_==0) ports_ = new vector; diff --git a/elab_expr.cc b/elab_expr.cc index 8c53b6066..308e41606 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1335,7 +1335,7 @@ unsigned PECallFunction::test_width_method_(Design*des, NetScope*scope, if (net == 0) return 0; - // Look fonr built in string attributes. + // Look for built in string attributes. if (net->data_type()==IVL_VT_STRING) { if (method_name == "len") { @@ -3843,7 +3843,7 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, } // Maybe this is a method attached to an enumeration name? If - // this is system verilog, then test to see if the name is + // this is SystemVerilog, then test to see if the name is // really a method attached to an object. if (gn_system_verilog() && found_in==0 && path_.size() >= 2) { pform_name_t use_path = path_; diff --git a/elaborate.cc b/elaborate.cc index 1693b3215..974312c9e 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -1581,7 +1581,7 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const // Special case: If the output port is an unpacked // array, then there should be no sub-ports and - // the passed pexxpression is processed + // the passed port expression is processed // differently. Note that we are calling it the // "r-value" expression, but since this is an // output port, we assign to it from the internal object. diff --git a/ivl_target.h b/ivl_target.h index 0198eec09..4cb84d786 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -300,7 +300,7 @@ typedef enum ivl_lpm_type_e { IVL_LPM_CONCAT = 16, IVL_LPM_CONCATZ = 36, /* Transparent concat */ IVL_LPM_CMP_EEQ= 18, /* Case EQ (===) */ - IVL_LPM_CMP_EQX= 37, /* Windcard EQ (==?) */ + IVL_LPM_CMP_EQX= 37, /* Wildcard EQ (==?) */ IVL_LPM_CMP_EQZ= 38, /* casez EQ */ IVL_LPM_CMP_EQ = 10, IVL_LPM_CMP_GE = 1, @@ -1285,8 +1285,8 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net); * magnitude compare, the signedness does matter. In any case, the * result of the compare is always unsigned. * - * The EQX and EQZ nodes are windcard compares, where xz bits (EQX) or - * z bits (EQZ) in the data(1) operand are treated as windcards. no + * The EQX and EQZ nodes are wildcard compares, where xz bits (EQX) or + * z bits (EQZ) in the data(1) operand are treated as wildcards. no * bits in the data(0) operand are wild. This matches the * SystemVerilog convention for the ==? operator. * diff --git a/libveriuser/getsimtime.c b/libveriuser/getsimtime.c index 0a7ad914f..a8812bd0c 100644 --- a/libveriuser/getsimtime.c +++ b/libveriuser/getsimtime.c @@ -115,7 +115,7 @@ PLI_INT32 tf_getlongtime(PLI_INT32 *high) } /* - * This function is not defined in the IEE standard, but is provided for + * This function is not defined in the IEEE standard, but is provided for * compatibility with other simulators. On platforms that support this, * make it a weak symbol just in case the user has defined their own * function for this. diff --git a/netlist.h b/netlist.h index 28dc78667..c0ccecbc8 100644 --- a/netlist.h +++ b/netlist.h @@ -765,7 +765,7 @@ class NetNet : public NetObj, public PortType { unsigned peek_eref() const; // Assignment statements count their lrefs here. And by - // asignment statements, we mean BEHAVIORAL assignments. + // assignment statements, we mean BEHAVIORAL assignments. void incr_lref(); void decr_lref(); unsigned peek_lref() const { return lref_count_; } @@ -2216,7 +2216,7 @@ class NetPartSelect : public NetNode { * * wire [7:0] foo = NetSubstitute(bar, bat, off); * - * meaus that bar is a vector the same width as foo, bat is a narrower + * means that bar is a vector the same width as foo, bat is a narrower * vector. The off is a constant offset into the bar vector. This * looks something like this: * @@ -2287,7 +2287,7 @@ class NetBUFZ : public NetNode { * * 0 -- Output (always returns 0 or 1) * 1 -- Input - * 2 -- Input (windcard input for EQX and EQZ variants) + * 2 -- Input (wildcard input for EQX and EQZ variants) */ class NetCaseCmp : public NetNode { diff --git a/netmisc.cc b/netmisc.cc index e345cb977..26d523d3c 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -893,7 +893,7 @@ static NetExpr* do_elab_and_eval(Design*des, NetScope*scope, PExpr*pe, } } - // If the context_width sent is is actually the minimim width, + // If the context_width sent is is actually the minimum width, // then raise the context_width to be big enough for the // lossless expression. if (force_expand && context_width > 0) { diff --git a/nettypes.cc b/nettypes.cc index 4a01d4d8a..2f2e3988f 100644 --- a/nettypes.cc +++ b/nettypes.cc @@ -141,7 +141,7 @@ bool prefix_to_slice(const std::vector&dims, // Now similarly go through the prefix numbers, working // through the dimensions until we run out. Accumulate a - // growing slice width (acc_wid) that is used to caculate the + // growing slice width (acc_wid) that is used to calculate the // growing offset (acc_off). list::const_iterator icur = prefix.end(); do { diff --git a/pform_types.h b/pform_types.h index de616f1d9..149ae9f27 100644 --- a/pform_types.h +++ b/pform_types.h @@ -50,7 +50,7 @@ typedef named named_number_t; typedef named named_pexpr_t; /* - * The pform_range_t holds variable diimensions for type + * The pform_range_t holds variable dimensions for type * declarations. The two expressions are interpreted as the first and * last values of the range. For example: * diff --git a/synth2.cc b/synth2.cc index e0a964f04..2f8bf7fb2 100644 --- a/synth2.cc +++ b/synth2.cc @@ -808,8 +808,8 @@ bool NetCase::synth_async_casez_(Design*des, NetScope*scope, sel_width, case_kind); des->add_node(condit_dev); condit_dev->set_line(*this); - // Note that the expression that may have windcards must - // go in the pin(2) input. This is the definiton of the + // Note that the expression that may have wildcards must + // go in the pin(2) input. This is the definition of the // NetCaseCmp statement. connect(condit_dev->pin(1), esig->pin(0)); connect(condit_dev->pin(2), guard->pin(0)); diff --git a/tgt-vlog95/vlog95.c b/tgt-vlog95/vlog95.c index 1765b9468..861cff554 100644 --- a/tgt-vlog95/vlog95.c +++ b/tgt-vlog95/vlog95.c @@ -208,7 +208,7 @@ int target_design(ivl_design_t des) assert(indent == 0); fprintf(vlog_out, "endmodule /* ivl_root_scope */\n"); } - /* Emit the rest of the scope objets. */ + /* Emit the rest of the scope objects. */ for (idx = 0; idx < nroots; idx += 1) emit_scope(roots[idx], 0); free_emitted_scope_list(); diff --git a/tgt-vvp/eval_vec4.c b/tgt-vvp/eval_vec4.c index e38f7238a..9030cc06c 100644 --- a/tgt-vvp/eval_vec4.c +++ b/tgt-vvp/eval_vec4.c @@ -415,7 +415,7 @@ static void draw_binary_vec4_land(ivl_expr_t expr) fprintf(vvp_out, " %%or/r;\n"); /* Now push the right expression. Again, reduce to a single - bit if necessasry. */ + bit if necessary. */ draw_eval_vec4(re); if (ivl_expr_width(re) > 1) fprintf(vvp_out, " %%or/r;\n"); @@ -615,7 +615,7 @@ static void draw_binary_vec4_lor(ivl_expr_t expr) fprintf(vvp_out, " %%or/r;\n"); /* Now push the right expression. Again, reduce to a single - bit if necessasry. */ + bit if necessary. */ draw_eval_vec4(re); if (ivl_expr_width(re) > 1) fprintf(vvp_out, " %%or/r;\n"); @@ -952,7 +952,7 @@ static void draw_select_pad_vec4(ivl_expr_t expr) } /* - * This function handles the speical case of a call to the internal + * This function handles the special case of a call to the internal * functions $ivl_darray_method$pop_back et al. The first (and only) * argument is the signal that represents a dynamic queue. Generate a * %qpop instruction to pop a value and push it to the vec4 stack. diff --git a/tgt-vvp/vvp_priv.h b/tgt-vvp/vvp_priv.h index e23916e03..5255058cc 100644 --- a/tgt-vvp/vvp_priv.h +++ b/tgt-vvp/vvp_priv.h @@ -237,13 +237,13 @@ extern void draw_eval_real(ivl_expr_t ex); extern int draw_eval_bool64(ivl_expr_t ex); /* - * The draw_eval_string functio evaluates the expression as a string, + * The draw_eval_string function evaluates the expression as a string, * and pushes the string onto the string stack. */ extern void draw_eval_string(ivl_expr_t ex); /* - * The draw_eval_string functio evaluates the expression as an object, + * The draw_eval_string function evaluates the expression as an object, * and pushes the object onto the object stack. */ extern int draw_eval_object(ivl_expr_t ex); diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 3980b9575..571c8b100 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -671,7 +671,7 @@ static int show_stmt_case(ivl_statement_t net, ivl_scope_t sscope) /* Duplicate the case expression so that the cmp instructions below do not completely erase the - value. Do this in fromt of each compare. */ + value. Do this in front of each compare. */ fprintf(vvp_out, " %%dup/vec4;\n"); draw_eval_vec4(cex); @@ -767,7 +767,7 @@ static int show_stmt_case_r(ivl_statement_t net, ivl_scope_t sscope) continue; } - /* The referene value... */ + /* The reference value... */ fprintf(vvp_out, " %%dup/real;\n"); /* The guard value... */ draw_eval_real(cex); @@ -2321,7 +2321,7 @@ int draw_process(ivl_process_t net, void*x) fprintf(vvp_out, " .scope S_%p;\n", scope); /* Generate the entry label. Just give the thread a number so - that we ar certain the label is unique. */ + that we are certain the label is unique. */ fprintf(vvp_out, "T_%u ;\n", thread_count); /* Draw the contents of the thread. */ diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 0927022be..c3a4e2ab9 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -753,7 +753,7 @@ composite_type_definition /* 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 + create Expression objects for it, but the parser will only recognize it it in specific situations. */ concurrent_conditional_signal_assignment /* IEEE 1076-2008 P11.6 */ : name LEQ waveform K_when expression else_when_waveforms ';' diff --git a/vpi/sys_darray.c b/vpi/sys_darray.c index 507bb974a..7fe90f4f4 100644 --- a/vpi/sys_darray.c +++ b/vpi/sys_darray.c @@ -263,7 +263,7 @@ static PLI_INT32 to_vec_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) offset)); vec_ptr->bval |= (bval >> (darr_word_size - offset)); - /* Start at the begining of the next vector part. */ + /* Start at the beginning of the next vector part. */ } else { offset = 0; } diff --git a/vpi/table_mod.c b/vpi/table_mod.c index 43609989b..c8157fdda 100644 --- a/vpi/table_mod.c +++ b/vpi/table_mod.c @@ -629,7 +629,7 @@ static unsigned initialize_table_model(vpiHandle callh, const char *name, } /* - * Routine to evalute the table model using the current input values. + * Routine to evaluate the table model using the current input values. */ static double eval_table_model(vpiHandle callh, p_table_mod table) { diff --git a/vvp/compile.cc b/vvp/compile.cc index eb74b8be4..3bf1d7474 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -1962,7 +1962,7 @@ void compile_param_string(char*label, char*name, char*value, bool local_flag, long file_idx, long lineno) { - // name and value become owned bi vpip_make_string_param + // name and value become owned by vpip_make_string_param vpiHandle obj = vpip_make_string_param(name, value, local_flag, file_idx, lineno); compile_vpi_symbol(label, obj); vpip_attach_to_current_scope(obj); diff --git a/vvp/compile.h b/vvp/compile.h index 60e094cb8..bfe20cd52 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -512,7 +512,7 @@ extern void compile_port_info( unsigned index, int vpi_port_type, unsigned width * given name. * * The vpi_type_code argument of compile_net() is one of the vpi - * object codes for the equivelent variable types. The supported codes + * object codes for the equivalent variable types. The supported codes * are: * vpiLogic -- 4-value logic * vpiIntVar -- 2-value logic diff --git a/vvp/dff.cc b/vvp/dff.cc index ed177373f..0070c5fcc 100644 --- a/vvp/dff.cc +++ b/vvp/dff.cc @@ -71,7 +71,7 @@ void vvp_dff::recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, } /* - * The recv_clear and recv_set function respond to asynchronout + * The recv_clear and recv_set function respond to asynchronous * clear/set input by propagating the desired output. * * NOTE: Don't touch the d_ value, because that tracks the D input, diff --git a/vvp/resolv.cc b/vvp/resolv.cc index 4aef59ef5..cd6bfa9e6 100644 --- a/vvp/resolv.cc +++ b/vvp/resolv.cc @@ -29,7 +29,7 @@ /* * The core functor for a resolver node stores all the input values * received by that node. This provides the necessary information - * for implementing the $countdrivers system call. For efficency, + * for implementing the $countdrivers system call. For efficiency, * the resolver is implemented using a balanced quaternary tree, so * the core functor also stores the current value for each branch * of the tree, to eliminate the need to re-evaluate branches whose diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index 8750c3a65..552fb499f 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -136,7 +136,7 @@ static vpiHandle fill_in_net4(struct __vpiSignal*obj, bool signed_flag, vvp_net_t*node); /* - * The standard formating/conversion routines. + * The standard formatting/conversion routines. * They work with full or partial signals. */ diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 21eef0b28..39c463fc5 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -949,7 +949,7 @@ bool of_ASSIGN_VEC4_A_D(vthread_t thr, vvp_code_t cp) unsigned wid = val.size(); const unsigned array_wid = cp->array->get_word_size(); - // Abort if flags[4] is set. This can happen if the calulation + // Abort if flags[4] is set. This can happen if the calculation // into an index register failed. if (thr->flags[4] == BIT4_1) return true; @@ -992,7 +992,7 @@ bool of_ASSIGN_VEC4_A_E(vthread_t thr, vvp_code_t cp) unsigned wid = val.size(); const unsigned array_wid = cp->array->get_word_size(); - // Abort if flags[4] is set. This can happen if the calulation + // Abort if flags[4] is set. This can happen if the calculation // into an index register failed. if (thr->flags[4] == BIT4_1) return true; @@ -1038,7 +1038,7 @@ bool of_ASSIGN_VEC4_OFF_D(vthread_t thr, vvp_code_t cp) int off = thr->words[off_index].w_int; vvp_time64_t del = thr->words[del_index].w_uint; - // Abort if flags[4] is set. This can happen if the calulation + // Abort if flags[4] is set. This can happen if the calculation // into an index register failed. if (thr->flags[4] == BIT4_1) return true; @@ -1080,7 +1080,7 @@ bool of_ASSIGN_VEC4_OFF_E(vthread_t thr, vvp_code_t cp) int off = thr->words[off_index].w_int; - // Abort if flags[4] is set. This can happen if the calulation + // Abort if flags[4] is set. This can happen if the calculation // into an index register failed. if (thr->flags[4] == BIT4_1) return true; From 4068c172f4ba4f3cdadb5c31ce762e1454e0e86d Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 7 Jun 2015 08:48:33 +0100 Subject: [PATCH 049/595] Fix overzealous detection of duplicate net/variable declarations. As reported by Larry Doolittle on iverilog-devel. --- pform.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/pform.cc b/pform.cc index 61965ef70..79d295c74 100644 --- a/pform.cc +++ b/pform.cc @@ -2425,7 +2425,8 @@ static PWire* pform_get_or_make_wire(const vlltype&li, perm_string name, // If the wire already exists but isn't yet fully defined, // carry on adding details. - if (cur && cur->get_data_type() == IVL_VT_NO_TYPE) { + if (cur && (cur->get_data_type() == IVL_VT_NO_TYPE || + cur->get_wire_type() == NetNet::IMPLICIT) ) { // If this is not implicit ("implicit" meaning we don't // know what the type is yet) then set the type now. if (type != NetNet::IMPLICIT) { From d6ff1946f978e4871884555030a3b1020cdb77e4 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 20 May 2015 18:53:29 +0200 Subject: [PATCH 050/595] vhdlpp: Support for time expressions. --- vhdlpp/expression.cc | 22 ++++++++++++++++++++++ vhdlpp/expression.h | 22 ++++++++++++++++++++++ vhdlpp/expression_debug.cc | 5 +++++ vhdlpp/expression_elaborate.cc | 7 +++++++ vhdlpp/expression_emit.cc | 16 ++++++++++++++++ vhdlpp/expression_evaluate.cc | 20 ++++++++++++++++++++ vhdlpp/expression_stream.cc | 14 ++++++++++++++ vhdlpp/lexor.lex | 1 + vhdlpp/library.cc | 3 +++ vhdlpp/parse.y | 26 ++++++++++++++++++++++++++ vhdlpp/vtype.cc | 3 +++ vhdlpp/vtype.h | 3 ++- vhdlpp/vtype_emit.cc | 3 +++ vhdlpp/vtype_stream.cc | 3 +++ 14 files changed, 147 insertions(+), 1 deletion(-) diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 949d568ae..7886618ee 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -564,3 +564,25 @@ ExpNew::~ExpNew() { delete size_; } + +ExpTime::ExpTime(uint64_t amount, timeunit_t unit) +: amount_(amount), unit_(unit) +{ +} + +double ExpTime::to_fs() const +{ + double val = amount_; + + switch(unit_) { + case FS: break; + case PS: val *= 1e3; break; + case NS: val *= 1e6; break; + case US: val *= 1e9; break; + case MS: val *= 1e12; break; + case S: val *= 1e15; break; + default: ivl_assert(*this, false); break; + } + + return val; +} diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 7d5f47ee6..717b1e116 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -838,4 +838,26 @@ class ExpNew : public Expression { Expression*size_; }; +class ExpTime : public Expression { + public: + typedef enum { FS, PS, NS, US, MS, S } timeunit_t; + + ExpTime(uint64_t amount, timeunit_t unit); + + Expression*clone() const { return new ExpTime(amount_, unit_); } + + int elaborate_expr(Entity*ent, ScopeBase*scope, const VType*ltype); + void write_to_stream(std::ostream&) const; + int emit(ostream&out, Entity*ent, ScopeBase*scope); + bool evaluate(ScopeBase*scope, int64_t&val) const; + bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const; + void dump(ostream&out, int indent = 0) const; + + private: + // Returns the time value expressed in femtoseconds + double to_fs() const; + uint64_t amount_; + timeunit_t unit_; +}; + #endif /* IVL_expression_H */ diff --git a/vhdlpp/expression_debug.cc b/vhdlpp/expression_debug.cc index 1a7b44e8c..fd52b6875 100644 --- a/vhdlpp/expression_debug.cc +++ b/vhdlpp/expression_debug.cc @@ -112,3 +112,8 @@ void ExpShift::dump(ostream&out, int indent) const dump_operands(out, indent+4); } +void ExpTime::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "Time "; + write_to_stream(out); +} diff --git a/vhdlpp/expression_elaborate.cc b/vhdlpp/expression_elaborate.cc index 30985fa53..71cda7c97 100644 --- a/vhdlpp/expression_elaborate.cc +++ b/vhdlpp/expression_elaborate.cc @@ -1133,3 +1133,10 @@ int ExpUNot::elaborate_expr(Entity*, ScopeBase*, const VType*ltype) set_type(ltype); return 0; } + + +int ExpTime::elaborate_expr(Entity*, ScopeBase*, const VType*) +{ + set_type(&primitive_INTEGER); + return 0; +} diff --git a/vhdlpp/expression_emit.cc b/vhdlpp/expression_emit.cc index b0ccefc5e..e7263e406 100644 --- a/vhdlpp/expression_emit.cc +++ b/vhdlpp/expression_emit.cc @@ -1068,3 +1068,19 @@ int ExpNew::emit(ostream&out, Entity*ent, ScopeBase*scope) out << "]"; return errors; } + +int ExpTime::emit(ostream&out, Entity*, ScopeBase*) +{ + out << amount_; + + switch(unit_) { + case FS: out << "fs"; break; + case PS: out << "ps"; break; + case NS: out << "ns"; break; + case US: out << "us"; break; + case MS: out << "ms"; break; + case S: out << "s"; break; + } + + return 0; +} diff --git a/vhdlpp/expression_evaluate.cc b/vhdlpp/expression_evaluate.cc index 54bf704b4..2e26ba502 100644 --- a/vhdlpp/expression_evaluate.cc +++ b/vhdlpp/expression_evaluate.cc @@ -22,6 +22,7 @@ # include "expression.h" # include "architec.h" # include +# include bool Expression::evaluate(ScopeBase*, int64_t&) const { @@ -245,3 +246,22 @@ bool ExpShift::evaluate(ScopeBase*scope, int64_t&val) const return true; } + +bool ExpTime::evaluate(ScopeBase*, int64_t&val) const +{ + double v = to_fs(); + + if(v > std::numeric_limits::max()) { + val = std::numeric_limits::max(); + cerr << get_fileline() << ": sorry: Time value is higher than the " + << "handled limit, reduced to " << val << " fs." << endl; + } + + val = v; + return true; +} + +bool ExpTime::evaluate(Entity*, ScopeBase*, int64_t&val) const +{ + return evaluate(NULL, NULL, val); +} diff --git a/vhdlpp/expression_stream.cc b/vhdlpp/expression_stream.cc index c379795bf..1321a3740 100644 --- a/vhdlpp/expression_stream.cc +++ b/vhdlpp/expression_stream.cc @@ -297,3 +297,17 @@ void ExpCast::write_to_stream(ostream&fd) const // SystemVerilog, so no need to use it here base_->write_to_stream(fd); } + +void ExpTime::write_to_stream(ostream&fd) const +{ + fd << amount_; + + switch(unit_) { + case FS: fd << " fs"; break; + case PS: fd << " ps"; break; + case NS: fd << " ns"; break; + case US: fd << " us"; break; + case MS: fd << " ms"; break; + case S: fd << " s"; break; + } +} diff --git a/vhdlpp/lexor.lex b/vhdlpp/lexor.lex index c9dae5c51..1cbda23c9 100644 --- a/vhdlpp/lexor.lex +++ b/vhdlpp/lexor.lex @@ -84,6 +84,7 @@ exponent [eE][-+]?{integer} based_literal {integer}#{based_integer}(\.{based_integer})?#{exponent}? based_integer [0-9a-fA-F](_?[0-9a-fA-F])* +time {integer}{W}*([fFpPnNuUmM]?[sS]) %% [ \t\b\f\r] { ; } diff --git a/vhdlpp/library.cc b/vhdlpp/library.cc index fda670a34..b0594c38d 100644 --- a/vhdlpp/library.cc +++ b/vhdlpp/library.cc @@ -391,6 +391,7 @@ 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 VTypePrimitive primitive_TIME(VTypePrimitive::TIME); static const VTypeArray primitive_BIT_VECTOR(&primitive_BIT, vector (1)); static const VTypeArray primitive_BOOL_VECTOR(&primitive_BOOLEAN, vector (1)); @@ -407,6 +408,7 @@ void generate_global_types(ActiveScope*res) res->use_name(perm_string::literal("bit_vector"),&primitive_BIT_VECTOR); res->use_name(perm_string::literal("string"), &primitive_STRING); res->use_name(perm_string::literal("natural"), &primitive_NATURAL); + res->use_name(perm_string::literal("time"), &primitive_TIME); } void emit_std_types(ostream&out) @@ -431,6 +433,7 @@ bool is_global_type(perm_string name) if (name == "natural") return true; if (name == "signed") return true; if (name == "unsigned") return true; + if (name == "time") return true; return false; } diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index c3a4e2ab9..7b3b4212b 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -1835,6 +1835,32 @@ primary delete[]$1; $$ = tmp; } + | INT_LITERAL IDENTIFIER + { ExpTime::timeunit_t unit = ExpTime::FS; + + if(!strcasecmp($2, "us")) + unit = ExpTime::US; + else if(!strcasecmp($2, "ms")) + unit = ExpTime::MS; + else if(!strcasecmp($2, "ns")) + unit = ExpTime::NS; + else if(!strcasecmp($2, "s")) + unit = ExpTime::S; + else if(!strcasecmp($2, "ps")) + unit = ExpTime::PS; + else if(!strcasecmp($2, "fs")) + unit = ExpTime::FS; + else + errormsg(@2, "Invalid time unit (accepted are fs, ps, ns, us, ms, s)."); + + if($1 < 0) + errormsg(@1, "Time cannot be negative."); + + ExpTime*tmp = new ExpTime($1, unit); + FILE_NAME(tmp, @1); + delete[] $2; + $$ = tmp; + } /*XXXX Caught up in element_association_list? | '(' expression ')' diff --git a/vhdlpp/vtype.cc b/vhdlpp/vtype.cc index ee43570e7..4dc97199a 100644 --- a/vhdlpp/vtype.cc +++ b/vhdlpp/vtype.cc @@ -76,6 +76,9 @@ void VTypePrimitive::show(ostream&out) const case STDLOGIC: out << "STD_LOGIC"; break; + case TIME: + out << "TIME"; + break; } } diff --git a/vhdlpp/vtype.h b/vhdlpp/vtype.h index 62b528240..0756ff68b 100644 --- a/vhdlpp/vtype.h +++ b/vhdlpp/vtype.h @@ -156,7 +156,7 @@ class VTypeERROR : public VType { class VTypePrimitive : public VType { public: - enum type_t { BOOLEAN, BIT, INTEGER, NATURAL, REAL, STDLOGIC, CHARACTER }; + enum type_t { BOOLEAN, BIT, INTEGER, NATURAL, REAL, STDLOGIC, CHARACTER, TIME }; public: VTypePrimitive(type_t tt, bool packed = false); @@ -187,6 +187,7 @@ extern const VTypePrimitive primitive_NATURAL; extern const VTypePrimitive primitive_REAL; extern const VTypePrimitive primitive_STDLOGIC; extern const VTypePrimitive primitive_CHARACTER; +extern const VTypePrimitive primitive_TIME; /* * An array is a compound N-dimensional array of element type. The diff --git a/vhdlpp/vtype_emit.cc b/vhdlpp/vtype_emit.cc index b97d00d7e..cfb8f6390 100644 --- a/vhdlpp/vtype_emit.cc +++ b/vhdlpp/vtype_emit.cc @@ -169,6 +169,9 @@ int VTypePrimitive::emit_primitive_type(ostream&out) const case CHARACTER: out << "char"; break; + case TIME: + out << "time"; + break; default: assert(0); break; diff --git a/vhdlpp/vtype_stream.cc b/vhdlpp/vtype_stream.cc index 2cf159db8..9f8b6c689 100644 --- a/vhdlpp/vtype_stream.cc +++ b/vhdlpp/vtype_stream.cc @@ -168,6 +168,9 @@ void VTypePrimitive::write_to_stream(ostream&fd) const case BOOLEAN: fd << "boolean"; break; + case TIME: + fd << "time"; + break; default: assert(0); fd << "/* PRIMITIVE: " << type_ << " */"; From 68f8007fc4f60cc24ff5bd9add77fff79ae6bf48 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 22 May 2015 18:07:31 +0200 Subject: [PATCH 051/595] vhdlpp: 'wait for' statement. --- vhdlpp/parse.y | 11 ++++++++++- vhdlpp/sequential.cc | 5 +++++ vhdlpp/sequential.h | 13 +++++++++++++ vhdlpp/sequential_debug.cc | 7 +++++++ vhdlpp/sequential_elaborate.cc | 5 +++++ vhdlpp/sequential_emit.cc | 17 +++++++++++++++++ 6 files changed, 57 insertions(+), 1 deletion(-) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index 7b3b4212b..b6a877438 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -359,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 assertion_statement report_statement return_statement +%type assertion_statement report_statement return_statement wait_for_statement %type range %type range_list index_constraint @@ -2201,6 +2201,7 @@ sequential_statement | return_statement { $$ = $1; } | report_statement { $$ = $1; } | assertion_statement { $$ = $1; } + | wait_for_statement { $$ = $1; } | K_null ';' { $$ = 0; } | error ';' { errormsg(@1, "Syntax error in sequential statement.\n"); @@ -2631,6 +2632,14 @@ variable_declaration /* IEEE 1076-2008 P6.4.2.4 */ } ; +wait_for_statement + : K_wait K_for expression ';' + { WaitForStmt*tmp = new WaitForStmt($3); + FILE_NAME(tmp, @1); + $$ = tmp; + } + ; + waveform : waveform_elements { $$ = $1; } diff --git a/vhdlpp/sequential.cc b/vhdlpp/sequential.cc index 95497a987..b6a4c1079 100644 --- a/vhdlpp/sequential.cc +++ b/vhdlpp/sequential.cc @@ -284,3 +284,8 @@ AssertStmt::AssertStmt(Expression*condition, const char*msg, ReportStmt::severit } const std::string AssertStmt::default_msg_ = std::string("Assertion violation."); + +WaitForStmt::WaitForStmt(Expression*delay) +: delay_(delay) +{ +} diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index d561b0559..ed7bb17a8 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -308,4 +308,17 @@ class AssertStmt : public ReportStmt { static const std::string default_msg_; }; +class WaitForStmt : public SequentialStmt { + public: + WaitForStmt(Expression*delay); + + 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*delay_; +}; + #endif /* IVL_sequential_H */ diff --git a/vhdlpp/sequential_debug.cc b/vhdlpp/sequential_debug.cc index 786fa5cc6..5c40b5012 100644 --- a/vhdlpp/sequential_debug.cc +++ b/vhdlpp/sequential_debug.cc @@ -180,3 +180,10 @@ void AssertStmt::dump(ostream&out, int indent) const cond_->dump(out, indent+3); ReportStmt::dump(out, indent+3); } + +void WaitForStmt::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "WaitForStmt at file=" << get_fileline() << endl; + out << setw(indent+3) << "" << "delay: "; + delay_->dump(out, indent+3); +} diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index 2c342030b..a0cfafe6d 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -197,3 +197,8 @@ int AssertStmt::elaborate(Entity*ent, ScopeBase*scope) { return cond_->elaborate_expr(ent, scope, 0); } + +int WaitForStmt::elaborate(Entity*ent, ScopeBase*scope) +{ + return delay_->elaborate_expr(ent, scope, 0); +} diff --git a/vhdlpp/sequential_emit.cc b/vhdlpp/sequential_emit.cc index 29f488b80..f0e6f0b5c 100644 --- a/vhdlpp/sequential_emit.cc +++ b/vhdlpp/sequential_emit.cc @@ -512,3 +512,20 @@ void AssertStmt::write_to_stream(std::ostream&fd) fd << std::endl; ReportStmt::write_to_stream(fd); } + +int WaitForStmt::emit(ostream&out, Entity*ent, ScopeBase*scope) +{ + int errors = 0; + + out << "#("; + errors += delay_->emit(out, ent, scope); + out << ")"; + + return errors; +} + +void WaitForStmt::write_to_stream(std::ostream&fd) +{ + fd << "wait for "; + delay_->write_to_stream(fd); +} From cd3180d1c29115c94b1306a23e8af9fd862b79fe Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Wed, 27 May 2015 13:48:30 +0200 Subject: [PATCH 052/595] ivl: TIME_LITERAL added as a primary expression. --- parse.y | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/parse.y b/parse.y index 787f409cb..f362d6505 100644 --- a/parse.y +++ b/parse.y @@ -3339,6 +3339,22 @@ expr_primary FILE_NAME(tmp, @1); $$ = tmp; } + | TIME_LITERAL + { int unit; + + based_size = 0; + $$ = 0; + if ($1 == 0 || !get_time_unit($1, unit)) + yyerror(@1, "internal error: delay."); + else { + double p = pow(10.0, (double)(unit - pform_get_timeunit())); + double time = atof($1) * p; + + verireal *v = new verireal(time); + $$ = new PEFNumber(v); + FILE_NAME($$, @1); + } + } | SYSTEM_IDENTIFIER { perm_string tn = lex_strings.make($1); PECallFunction*tmp = new PECallFunction(tn); From 80403d2ade171979f0edeebd9e39017a854ace9c Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Mon, 8 Jun 2015 18:42:17 +0200 Subject: [PATCH 053/595] ivl: Disabled reg_flag for time type in SV. --- parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parse.y b/parse.y index f362d6505..fe3eef5c3 100644 --- a/parse.y +++ b/parse.y @@ -1066,7 +1066,7 @@ data_type /* IEEE1800-2005: A.2.2.1 */ | K_time { list*pd = make_range_from_width(64); vector_type_t*tmp = new vector_type_t(IVL_VT_LOGIC, false, pd); - tmp->reg_flag = true; + tmp->reg_flag = !gn_system_verilog(); $$ = tmp; } | TYPE_IDENTIFIER dimensions_opt From 1f1d47887ed541fe89c90bb9c22c3b98a45c08d3 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Thu, 28 May 2015 17:51:18 +0200 Subject: [PATCH 054/595] vhdlpp: Visitor for Expression class. --- vhdlpp/expression.cc | 104 +++++++++++++++++++++++++++++++++++++++++++ vhdlpp/expression.h | 20 ++++++++- 2 files changed, 123 insertions(+), 1 deletion(-) diff --git a/vhdlpp/expression.cc b/vhdlpp/expression.cc index 7886618ee..0e3a0b493 100644 --- a/vhdlpp/expression.cc +++ b/vhdlpp/expression.cc @@ -69,6 +69,12 @@ Expression*ExpAttribute::clone() const return new ExpAttribute(static_cast(base_->clone()), name_); } +void ExpAttribute::visit(ExprVisitor& func) +{ + base_->visit(func); + func(this); +} + ExpBinary::ExpBinary(Expression*op1, Expression*op2) : operand1_(op1), operand2_(op2) { @@ -90,6 +96,13 @@ bool ExpBinary::eval_operand2(ScopeBase*scope, int64_t&val) const return operand2_->evaluate(scope, val); } +void ExpBinary::visit(ExprVisitor& func) +{ + operand1_->visit(func); + operand2_->visit(func); + func(this); +} + ExpUnary::ExpUnary(Expression*op1) : operand1_(op1) { @@ -100,6 +113,12 @@ ExpUnary::~ExpUnary() delete operand1_; } +void ExpUnary::visit(ExprVisitor& func) +{ + operand1_->visit(func); + func(this); +} + ExpAggregate::ExpAggregate(std::list*el) : elements_(el? el->size() : 0) { @@ -135,6 +154,24 @@ Expression* ExpAggregate::clone() const return new ExpAggregate(new_elements); } +void ExpAggregate::visit(ExprVisitor& func) +{ + for(std::vector::iterator it = elements_.begin(); + it != elements_.end(); ++it) { + (*it)->extract_expression()->visit(func); + } + + for(std::vector::iterator it = aggregate_.begin(); + it != aggregate_.end(); ++it) { + if(Expression*choice_expr = it->choice->simple_expression(false)) + choice_expr->visit(func); + + it->expr->visit(func); + } + + func(this); +} + ExpAggregate::choice_t::choice_t(Expression*exp) : expr_(exp) { @@ -256,6 +293,13 @@ ExpConcat::~ExpConcat() delete operand2_; } +void ExpConcat::visit(ExprVisitor& func) +{ + operand1_->visit(func); + operand2_->visit(func); + func(this); +} + ExpConditional::ExpConditional(Expression*co, list*tru, list*fal) : cond_(co) @@ -304,6 +348,30 @@ Expression*ExpConditional::clone() const return new ExpConditional(cond_->clone(), new_true_clause, new_else_clause); } +void ExpConditional::visit(ExprVisitor& func) +{ + if(!true_clause_.empty()) { + for(std::list::iterator it = true_clause_.begin(); + it != true_clause_.end(); ++it) { + (*it)->visit(func); + } + } + + if(!else_clause_.empty()) { + for(std::list::iterator it = else_clause_.begin(); + it != else_clause_.end(); ++it) { + std::list& else_clause = (*it)->extract_true_clause(); + + for(std::list::iterator jt = else_clause.begin(); + jt != else_clause.end(); ++jt) { + (*jt)->visit(func); + } + } + } + + func(this); +} + ExpConditional::else_t::else_t(Expression*cond, std::list*tru) : cond_(cond) { @@ -378,6 +446,16 @@ Expression*ExpFunc::clone() const { return f; } +void ExpFunc::visit(ExprVisitor& func) { + if(!argv_.empty()) { + for(std::vector::iterator it = argv_.begin(); + it != argv_.end(); ++it) + (*it)->visit(func); + } + + func(this); +} + const VType* ExpFunc::func_ret_type() const { return def_ ? def_->peek_return_type() : NULL; @@ -481,6 +559,20 @@ void ExpName::set_range(Expression*msb, Expression*lsb) lsb_ = lsb; } +void ExpName::visit(ExprVisitor& func) +{ + if(prefix_.get()) + prefix_.get()->visit(func); + + if(index_) + index_->visit(func); + + if(lsb_) + lsb_->visit(func); + + func(this); +} + int ExpName::index_t::emit(ostream&out, Entity*ent, ScopeBase*scope) { int errors = 0; @@ -555,6 +647,12 @@ ExpCast::~ExpCast() { } +void ExpCast::visit(ExprVisitor& func) +{ + base_->visit(func); + func(this); +} + ExpNew::ExpNew(Expression*size) : size_(size) { @@ -565,6 +663,12 @@ ExpNew::~ExpNew() delete size_; } +void ExpNew::visit(ExprVisitor& func) +{ + size_->visit(func); + func(this); +} + ExpTime::ExpTime(uint64_t amount, timeunit_t unit) : amount_(amount), unit_(unit) { diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 717b1e116..479d207d5 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -38,6 +38,11 @@ class VTypeArray; class VTypePrimitive; class ExpName; +struct ExprVisitor { + virtual ~ExprVisitor() {}; + virtual void operator() (Expression*s) = 0; +}; + /* * The Expression class represents parsed expressions from the parsed * VHDL input. The Expression class is a virtual class that holds more @@ -120,6 +125,9 @@ class Expression : public LineInfo { virtual void dump(ostream&out, int indent = 0) const =0; virtual ostream& dump_inline(ostream&out) const; + // Recursively visits a tree of expressions (useful of complex expressions). + virtual void visit(ExprVisitor& func) { func(this); } + protected: // This function is called by the derived class during // elaboration to set the type of the current expression that @@ -160,6 +168,7 @@ class ExpUnary : public Expression { inline const Expression*peek_operand() const { return operand1_; } const VType*fit_type(Entity*ent, ScopeBase*scope, const VTypeArray*atype) const; + void visit(ExprVisitor& func); protected: inline void write_to_stream_operand1(std::ostream&fd) const @@ -186,6 +195,7 @@ class ExpBinary : public Expression { inline const Expression* peek_operand2(void) const { return operand2_; } const VType*probe_type(Entity*ent, ScopeBase*scope) const; + void visit(ExprVisitor& func); protected: @@ -299,6 +309,7 @@ class ExpAggregate : public Expression { void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: int elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype); @@ -360,6 +371,7 @@ class ExpAttribute : public Expression { bool evaluate(ScopeBase*scope, int64_t&val) const; bool evaluate(Entity*ent, ScopeBase*scope, int64_t&val) const; void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: ExpName*base_; @@ -430,6 +442,7 @@ class ExpConcat : public Expression { virtual bool evaluate(ScopeBase*scope, int64_t&val) const; bool is_primary(void) const; void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: int elaborate_expr_array_(Entity*ent, ScopeBase*scope, const VTypeArray*ltype); @@ -457,6 +470,7 @@ class ExpConditional : public Expression { int emit_when_else(ostream&out, Entity*ent, ScopeBase*scope); int emit_else(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + std::list& extract_true_clause() { return true_clause_; } private: Expression*cond_; @@ -475,6 +489,7 @@ class ExpConditional : public Expression { void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: Expression*cond_; @@ -528,6 +543,7 @@ class ExpFunc : public Expression { void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); // NOTE: does not handle expressions in subprogram private: perm_string name_; @@ -638,8 +654,8 @@ class ExpName : public Expression { void dump(ostream&out, int indent = 0) const; inline const char* name() const { return name_; } inline const perm_string& peek_name() const { return name_; } - void set_range(Expression*msb, Expression*lsb); + void visit(ExprVisitor& func); private: class index_t { @@ -811,6 +827,7 @@ class ExpCast : public Expression { void write_to_stream(std::ostream&fd) const; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: Expression*base_; @@ -833,6 +850,7 @@ class ExpNew : public Expression { void write_to_stream(std::ostream&) const {}; int emit(ostream&out, Entity*ent, ScopeBase*scope); void dump(ostream&out, int indent = 0) const; + void visit(ExprVisitor& func); private: Expression*size_; From 4a31f36646c695f18689004da0efd406810e91f1 Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 29 May 2015 10:51:17 +0200 Subject: [PATCH 055/595] vhdlpp: Minor code cleaning. --- vhdlpp/architec_elaborate.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/vhdlpp/architec_elaborate.cc b/vhdlpp/architec_elaborate.cc index 9ab09bfa8..327457ef1 100644 --- a/vhdlpp/architec_elaborate.cc +++ b/vhdlpp/architec_elaborate.cc @@ -338,10 +338,7 @@ int ProcessStatement::elaborate(Entity*ent, Architecture*arc) int errors = 0; if (rewrite_as_always_edge_(ent, arc) >= 0) { - - } else if (extract_anyedge_(ent, arc) >= 0) { - - } else { + extract_anyedge_(ent, arc); } for (list::iterator cur = statements_list_.begin() From 29ddd5208fce6a113e05173cfb838293f4216e0a Mon Sep 17 00:00:00 2001 From: Maciej Suminski Date: Fri, 29 May 2015 10:54:29 +0200 Subject: [PATCH 056/595] vhdlpp: 'wait on' and 'wait until' statements. --- vhdlpp/parse.y | 16 +++++++++--- vhdlpp/sequential.cc | 5 ++++ vhdlpp/sequential.h | 20 ++++++++++++-- vhdlpp/sequential_debug.cc | 7 +++++ vhdlpp/sequential_elaborate.cc | 24 +++++++++++++++++ vhdlpp/sequential_emit.cc | 48 ++++++++++++++++++++++++++++++++++ 6 files changed, 115 insertions(+), 5 deletions(-) diff --git a/vhdlpp/parse.y b/vhdlpp/parse.y index b6a877438..f75cd19e2 100644 --- a/vhdlpp/parse.y +++ b/vhdlpp/parse.y @@ -359,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 assertion_statement report_statement return_statement wait_for_statement +%type assertion_statement report_statement return_statement wait_statement %type range %type range_list index_constraint @@ -2201,7 +2201,7 @@ sequential_statement | return_statement { $$ = $1; } | report_statement { $$ = $1; } | assertion_statement { $$ = $1; } - | wait_for_statement { $$ = $1; } + | wait_statement { $$ = $1; } | K_null ';' { $$ = 0; } | error ';' { errormsg(@1, "Syntax error in sequential statement.\n"); @@ -2632,12 +2632,22 @@ variable_declaration /* IEEE 1076-2008 P6.4.2.4 */ } ; -wait_for_statement +wait_statement : K_wait K_for expression ';' { WaitForStmt*tmp = new WaitForStmt($3); FILE_NAME(tmp, @1); $$ = tmp; } + | K_wait K_on expression ';' + { WaitStmt*tmp = new WaitStmt(WaitStmt::ON, $3); + FILE_NAME(tmp, @1); + $$ = tmp; + } + | K_wait K_until expression ';' + { WaitStmt*tmp = new WaitStmt(WaitStmt::UNTIL, $3); + FILE_NAME(tmp, @1); + $$ = tmp; + } ; waveform diff --git a/vhdlpp/sequential.cc b/vhdlpp/sequential.cc index b6a4c1079..0f793b713 100644 --- a/vhdlpp/sequential.cc +++ b/vhdlpp/sequential.cc @@ -289,3 +289,8 @@ WaitForStmt::WaitForStmt(Expression*delay) : delay_(delay) { } + +WaitStmt::WaitStmt(wait_type_t type, Expression*expr) +: type_(type), expr_(expr) +{ +} diff --git a/vhdlpp/sequential.h b/vhdlpp/sequential.h index ed7bb17a8..eba398cef 100644 --- a/vhdlpp/sequential.h +++ b/vhdlpp/sequential.h @@ -22,8 +22,7 @@ # include "LineInfo.h" # include "parse_types.h" -# include -# include +# include class ScopeBase; class Entity; @@ -321,4 +320,21 @@ class WaitForStmt : public SequentialStmt { Expression*delay_; }; +class WaitStmt : public SequentialStmt { + public: + typedef enum { ON, UNTIL } wait_type_t; + WaitStmt(wait_type_t type, Expression*expression); + + 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: + wait_type_t type_; + Expression*expr_; + // Sensitivity list for 'wait until' statement + std::set sens_list_; +}; + #endif /* IVL_sequential_H */ diff --git a/vhdlpp/sequential_debug.cc b/vhdlpp/sequential_debug.cc index 5c40b5012..149021440 100644 --- a/vhdlpp/sequential_debug.cc +++ b/vhdlpp/sequential_debug.cc @@ -187,3 +187,10 @@ void WaitForStmt::dump(ostream&out, int indent) const out << setw(indent+3) << "" << "delay: "; delay_->dump(out, indent+3); } + +void WaitStmt::dump(ostream&out, int indent) const +{ + out << setw(indent) << "" << "WaitStmt at file=" << get_fileline() << endl; + out << setw(indent+3) << "" << "expression: "; + expr_->dump(out, indent+3); +} diff --git a/vhdlpp/sequential_elaborate.cc b/vhdlpp/sequential_elaborate.cc index a0cfafe6d..80e7b2584 100644 --- a/vhdlpp/sequential_elaborate.cc +++ b/vhdlpp/sequential_elaborate.cc @@ -19,6 +19,7 @@ # include "sequential.h" # include "expression.h" +# include "scope.h" int SequentialStmt::elaborate(Entity*, ScopeBase*) { @@ -202,3 +203,26 @@ int WaitForStmt::elaborate(Entity*ent, ScopeBase*scope) { return delay_->elaborate_expr(ent, scope, 0); } + +int WaitStmt::elaborate(Entity*ent, ScopeBase*scope) +{ + if(type_ == UNTIL) { + struct fill_sens_list_t : public ExprVisitor { + fill_sens_list_t(set& sig_list) + : sig_list_(sig_list) {}; + + void operator() (Expression*s) { + if(ExpName*name = dynamic_cast(s)) + sig_list_.insert(name); + } + + private: + set& sig_list_; + } fill_sens_list(sens_list_); + + // Fill the sensitivity list + expr_->visit(fill_sens_list); + } + + return expr_->elaborate_expr(ent, scope, 0); +} diff --git a/vhdlpp/sequential_emit.cc b/vhdlpp/sequential_emit.cc index f0e6f0b5c..619c0f5e5 100644 --- a/vhdlpp/sequential_emit.cc +++ b/vhdlpp/sequential_emit.cc @@ -529,3 +529,51 @@ void WaitForStmt::write_to_stream(std::ostream&fd) fd << "wait for "; delay_->write_to_stream(fd); } + +int WaitStmt::emit(ostream&out, Entity*ent, ScopeBase*scope) +{ + int errors = 0; + + switch(type_) { + case ON: + out << "@("; + break; + + case UNTIL: + if(!sens_list_.empty()) { + out << "@("; + for(std::set::iterator it = sens_list_.begin(); + it != sens_list_.end(); ++it) { + if(it != sens_list_.begin()) + out << ","; + + (*it)->emit(out, ent, scope); + } + + out << ");"; + } + + out << "wait("; + break; + } + + errors += expr_->emit(out, ent, scope); + out << ");" << endl; + + return errors; +} + +void WaitStmt::write_to_stream(std::ostream&fd) +{ + switch(type_) { + case ON: + fd << "wait on "; + break; + + case UNTIL: + fd << "wait until "; + break; + } + + expr_->write_to_stream(fd); +} From 3080f5730d581afb6b6b3df25ff1f9f481c454f3 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 8 Jun 2015 20:27:38 +0100 Subject: [PATCH 057/595] Better implementation of assignment lval concatenation synthesis. --- synth2.cc | 55 +++++++++++++++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/synth2.cc b/synth2.cc index 2f8bf7fb2..f877a2215 100644 --- a/synth2.cc +++ b/synth2.cc @@ -70,6 +70,33 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, NexusSet&nex_map, NetBus&nex_out, NetBus&accumulated_nex_out) { + /* If the lval is a concatenation, synthesise each part + separately. */ + if (lval_->more ) { + /* Temporarily set the lval_ and rval_ fields for each + part in turn and recurse. Restore them when done. */ + NetAssign_*full_lval = lval_; + NetExpr*full_rval = rval_; + unsigned offset = 0; + while (lval_) { + unsigned width = lval_->lwidth(); + NetEConst*base = new NetEConst(verinum(offset)); + base->set_line(*this); + rval_ = new NetESelect(full_rval->dup_expr(), base, width); + rval_->set_line(*this); + eval_expr(rval_, width); + NetAssign_*more = lval_->more; + lval_->more = 0; + synth_async(des, scope, nex_map, nex_out, + accumulated_nex_out); + lval_ = lval_->more = more; + offset += width; + } + lval_ = full_lval; + rval_ = full_rval; + return true; + } + NetNet*rsig = rval_->synthesize(des, scope, rval_); assert(rsig); @@ -100,34 +127,6 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, << ", nex_out.pin_count()==" << nex_out.pin_count() << endl; } - if (lval_->more ) { - unsigned base = 0, width = 1; - unsigned i = 0; - NetAssign_ *lval = lval_; - while (lval) { - NetNet *llsig = lval->sig(); - width = lval->lwidth(); - ivl_variable_type_t tmp_data_type = llsig->data_type(); - netvector_t *tmp_type = new netvector_t(tmp_data_type, llsig->vector_width()-1, 0); - - NetNet *tmp = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, NetNet::not_an_array, tmp_type); - tmp->local_flag(true); - NetPartSelect *ps = new NetPartSelect(rsig, base, width, NetPartSelect::VP); - ps->set_line(*this); - des->add_node(ps); - - connect(tmp->pin(0), ps->pin(0)); - connect(nex_out.pin(i), tmp->pin(0)); - - base += width; - i++; - lval->turn_sig_to_wire_on_release(); - lval = lval->more; - } - return true; - } - // Here we note if the l-value is actually a bit/part // select. If so, generate a NetPartSelect to perform the select. if ((lval_->lwidth()!=lsig->vector_width()) && !scope->loop_index_tmp.empty()) { From 3fb65eb51a059cfc4ea64e9b437777f16bd330f3 Mon Sep 17 00:00:00 2001 From: Johann Klammer Date: Wed, 22 Apr 2015 08:00:27 +0200 Subject: [PATCH 058/595] single bit reset --- synth2.cc | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/synth2.cc b/synth2.cc index f877a2215..eee722b47 100644 --- a/synth2.cc +++ b/synth2.cc @@ -1533,21 +1533,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, verinum zero (verinum::V0, rst_drv.len()); verinum ones (verinum::V1, rst_drv.len()); - if (rst_drv==zero) { - // Don't yet support multiple asynchronous reset inputs. - ivl_assert(*this, ! ff_aclr.pin(pin).is_linked()); - - ivl_assert(*this, rst->pin_count()==1); - connect(ff_aclr.pin(pin), rst->pin(0)); - - } else if (rst_drv==ones) { - // Don't yet support multiple asynchronous set inputs. - ivl_assert(*this, ! ff_aset.pin(pin).is_linked()); - - ivl_assert(*this, rst->pin_count()==1); - connect(ff_aset.pin(pin), rst->pin(0)); - - } else { + if(rst_drv.len() != 1) { NetConcat *set_cc = new NetConcat(scope, scope->local_symbol(), rst_nex->vector_width(), @@ -1585,6 +1571,12 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, connect(set_cc->pin(i+1), rst->pin(0)); connect(rst_cc->pin(i+1), nc->pin(0)); } else { + if(rst_drv[i] != verinum::V0) + { + cerr << get_fileline() << ": error: Async initialisation not constant" + << " for FlipFlop reset: " << i << rst_drv << endl; + des->errors += 1; + } connect(set_cc->pin(i+1), nc->pin(0)); connect(rst_cc->pin(i+1), rst->pin(0)); } @@ -1592,6 +1584,22 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, connect(ff_aset.pin(pin), set_cc->pin(0)); connect(ff_aclr.pin(pin), rst_cc->pin(0)); } + else { + if (rst_drv==zero) { + // Don't yet support multiple asynchronous reset inputs. + ivl_assert(*this, ! ff_aclr.pin(pin).is_linked()); + + ivl_assert(*this, rst->pin_count()==1); + connect(ff_aclr.pin(pin), rst->pin(0)); + + } else if (rst_drv==ones) { + // Don't yet support multiple asynchronous set inputs. + ivl_assert(*this, ! ff_aset.pin(pin).is_linked()); + + ivl_assert(*this, rst->pin_count()==1); + connect(ff_aset.pin(pin), rst->pin(0)); + } + } } return else_->synth_sync(des, scope, ff_clk, ff_ce, From 81e1735959611a75e3dfedcd5ae01d6c44d81bf7 Mon Sep 17 00:00:00 2001 From: Johann Klammer Date: Thu, 23 Apr 2015 03:20:20 +0200 Subject: [PATCH 059/595] establish support for aset_value and reorder clauses so vlog95 doesn't fail anymore. --- netlist.h | 4 +++ synth2.cc | 97 +++++++++++++++++-------------------------------------- 2 files changed, 33 insertions(+), 68 deletions(-) diff --git a/netlist.h b/netlist.h index c0ccecbc8..a9cea0ecc 100644 --- a/netlist.h +++ b/netlist.h @@ -2620,6 +2620,7 @@ class NetProc : public virtual LineInfo { virtual bool synth_sync(Design*des, NetScope*scope, NetNet*ff_clock, NetBus&ff_ce, NetBus&ff_aclr, NetBus&ff_aset, + vector&aset_value, NexusSet&nex_map, NetBus&nex_out, const std::vector&events); @@ -2901,6 +2902,7 @@ class NetBlock : public NetProc { bool synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetBus&ff_ce, NetBus&ff_aclr,NetBus&ff_aset, + vector&aset_value, NexusSet&nex_map, NetBus&nex_out, const std::vector&events); @@ -3042,6 +3044,7 @@ class NetCondit : public NetProc { bool synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetBus&ff_ce, NetBus&ff_aclr,NetBus&ff_aset, + vector&aset_value, NexusSet&nex_map, NetBus&nex_out, const std::vector&events); @@ -3319,6 +3322,7 @@ class NetEvWait : public NetProc { virtual bool synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetBus&ff_ce, NetBus&ff_aclr,NetBus&ff_aset, + vector&aset_value, NexusSet&nex_map, NetBus&nex_out, const std::vector&events); diff --git a/synth2.cc b/synth2.cc index eee722b47..d838dfdbe 100644 --- a/synth2.cc +++ b/synth2.cc @@ -36,6 +36,7 @@ bool NetProc::synth_async(Design*, NetScope*, NexusSet&, NetBus&, NetBus&) bool NetProc::synth_sync(Design*des, NetScope*scope, NetNet* /* ff_clk */, NetBus& /* ff_ce */, NetBus& /* ff_aclr*/, NetBus& /* ff_aset*/, + vector &aset_value, NexusSet&nex_map, NetBus&nex_out, const vector&events) { @@ -1383,6 +1384,7 @@ bool NetProcTop::synth_async(Design*des) bool NetBlock::synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetBus&ff_ce, NetBus&ff_aclr,NetBus&ff_aset, + vector &aset_value, NexusSet&nex_map, NetBus&nex_out, const vector&events_in) { @@ -1426,7 +1428,7 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, nexa that we expect, and the tmp_out is where we want those outputs connected. */ bool ok_flag = cur->synth_sync(des, scope, ff_clk, tmp_ce, - ff_aclr, ff_aset, + ff_aclr, ff_aset, aset_value, tmp_set, tmp_out, events_in); flag = flag && ok_flag; @@ -1464,6 +1466,7 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, bool NetCondit::synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetBus&ff_ce, NetBus&ff_aclr,NetBus&ff_aset, + vector &aset_value, NexusSet&nex_map, NetBus&nex_out, const vector&events_in) { @@ -1533,77 +1536,31 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, verinum zero (verinum::V0, rst_drv.len()); verinum ones (verinum::V1, rst_drv.len()); - if(rst_drv.len() != 1) { - NetConcat *set_cc = new NetConcat(scope, - scope->local_symbol(), - rst_nex->vector_width(), - rst_drv.len(), true); - NetConcat *rst_cc = new NetConcat(scope, - scope->local_symbol(), - rst_nex->vector_width(), - rst_drv.len(), true); - ivl_variable_type_t oosig_data_type = IVL_VT_LOGIC; - netvector_t *oosig_vec = new netvector_t(oosig_data_type, 0, 0); - NetNet *oosig[2] = {new NetNet(scope, - scope->local_symbol(), - NetNet::TRI, oosig_vec), - new NetNet(scope, - scope->local_symbol(), - NetNet::TRI, oosig_vec)}; - set_cc->set_line(*this); - des->add_node(set_cc); - connect(set_cc->pin(0), oosig[0]->pin(0)); - rst_cc->set_line(*this); - des->add_node(rst_cc); - connect(rst_cc->pin(0), oosig[1]->pin(0)); - for (int i = 0; i < (int)rst_drv.len(); i += 1) { - // This is the output signal f const, osig. - ivl_variable_type_t osig_data_type = IVL_VT_LOGIC; - netvector_t*osig_vec = new netvector_t(osig_data_type, 0, 0); - NetNet *osig = new NetNet(scope, scope->local_symbol(), - NetNet::TRI, osig_vec); - NetConst *nc = new NetConst(scope, scope->local_symbol(), - verinum(verinum::V0, 1)); - connect(nc->pin(0), osig->pin(0)); - nc->set_line(*this); - des->add_node(nc); - if (rst_drv[i] == verinum::V1) { - connect(set_cc->pin(i+1), rst->pin(0)); - connect(rst_cc->pin(i+1), nc->pin(0)); - } else { - if(rst_drv[i] != verinum::V0) - { - cerr << get_fileline() << ": error: Async initialisation not constant" - << " for FlipFlop reset: " << i << rst_drv << endl; - des->errors += 1; - } - connect(set_cc->pin(i+1), nc->pin(0)); - connect(rst_cc->pin(i+1), rst->pin(0)); - } - } - connect(ff_aset.pin(pin), set_cc->pin(0)); - connect(ff_aclr.pin(pin), rst_cc->pin(0)); - } - else { - if (rst_drv==zero) { - // Don't yet support multiple asynchronous reset inputs. - ivl_assert(*this, ! ff_aclr.pin(pin).is_linked()); + if (rst_drv==zero) { + // Don't yet support multiple asynchronous reset inputs. + ivl_assert(*this, ! ff_aclr.pin(pin).is_linked()); - ivl_assert(*this, rst->pin_count()==1); - connect(ff_aclr.pin(pin), rst->pin(0)); + ivl_assert(*this, rst->pin_count()==1); + connect(ff_aclr.pin(pin), rst->pin(0)); + aset_value[pin] = rst_drv; - } else if (rst_drv==ones) { - // Don't yet support multiple asynchronous set inputs. - ivl_assert(*this, ! ff_aset.pin(pin).is_linked()); + } else if (rst_drv==ones) { + // Don't yet support multiple asynchronous set inputs. + ivl_assert(*this, ! ff_aset.pin(pin).is_linked()); - ivl_assert(*this, rst->pin_count()==1); - connect(ff_aset.pin(pin), rst->pin(0)); - } + ivl_assert(*this, rst->pin_count()==1); + connect(ff_aset.pin(pin), rst->pin(0)); + aset_value[pin] = rst_drv; + } else { + ivl_assert(*this, ! ff_aset.pin(pin).is_linked()); + ivl_assert(*this, rst->pin_count()==1); + connect(ff_aset.pin(pin), rst->pin(0)); + aset_value[pin] = rst_drv; } } return else_->synth_sync(des, scope, ff_clk, ff_ce, - ff_aclr, ff_aset, + ff_aclr, ff_aset, aset_value, nex_map, nex_out, vector(0)); } @@ -1758,7 +1715,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, } } - bool flag = if_->synth_sync(des, scope, ff_clk, ff_ce, ff_aclr, ff_aset, nex_map, nex_out, events_in); + bool flag = if_->synth_sync(des, scope, ff_clk, ff_ce, ff_aclr, ff_aset, aset_value, nex_map, nex_out, events_in); return flag; } @@ -1766,6 +1723,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetBus&ff_ce, NetBus&ff_aclr,NetBus&ff_aset, + vector &aset_value, NexusSet&nex_map, NetBus&nex_out, const vector&events_in) { @@ -1847,7 +1805,7 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, /* Synthesize the input to the DFF. */ bool flag = statement_->synth_sync(des, scope, ff_clk, ff_ce, - ff_aclr, ff_aset, + ff_aclr, ff_aset, aset_value, nex_map, nex_out, events); return flag; @@ -1867,7 +1825,9 @@ bool NetProcTop::synth_sync(Design*des) } NexusSet nex_set; + statement_->nex_output(nex_set); + vector aset_value(nex_set.size()); /* Make a model FF that will connect to the first item in the set, and will also take the initial connection of clocks @@ -1902,7 +1862,7 @@ bool NetProcTop::synth_sync(Design*des) // Connect the input later. /* Synthesize the input to the DFF. */ - bool flag = statement_->synth_sync(des, scope(), clock, ce, aclr, aset, + bool flag = statement_->synth_sync(des, scope(), clock, ce, aclr, aset, aset_value, nex_set, nex_d, vector()); if (! flag) { @@ -1924,6 +1884,7 @@ bool NetProcTop::synth_sync(Design*des) nex_set[idx].wid); des->add_node(ff2); ff2->set_line(*this); + ff2->aset_value(aset_value[idx]); NetNet*tmp = nex_d.pin(idx).nexus()->pick_any_net(); tmp->set_line(*this); From e0cdd71984f03f34f7f6e5c984ce1383123c7600 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 8 Jun 2015 21:20:49 +0100 Subject: [PATCH 060/595] Minor cleanup and simplification of aset_value changes. --- synth2.cc | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) diff --git a/synth2.cc b/synth2.cc index d838dfdbe..d94548298 100644 --- a/synth2.cc +++ b/synth2.cc @@ -36,7 +36,7 @@ bool NetProc::synth_async(Design*, NetScope*, NexusSet&, NetBus&, NetBus&) bool NetProc::synth_sync(Design*des, NetScope*scope, NetNet* /* ff_clk */, NetBus& /* ff_ce */, NetBus& /* ff_aclr*/, NetBus& /* ff_aset*/, - vector &aset_value, + vector& /*aset_value*/, NexusSet&nex_map, NetBus&nex_out, const vector&events) { @@ -1384,7 +1384,7 @@ bool NetProcTop::synth_async(Design*des) bool NetBlock::synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetBus&ff_ce, NetBus&ff_aclr,NetBus&ff_aset, - vector &aset_value, + vector&aset_value, NexusSet&nex_map, NetBus&nex_out, const vector&events_in) { @@ -1466,7 +1466,7 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, bool NetCondit::synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetBus&ff_ce, NetBus&ff_aclr,NetBus&ff_aset, - vector &aset_value, + vector&aset_value, NexusSet&nex_map, NetBus&nex_out, const vector&events_in) { @@ -1537,25 +1537,20 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, verinum ones (verinum::V1, rst_drv.len()); if (rst_drv==zero) { - // Don't yet support multiple asynchronous reset inputs. + // Don't yet support multiple asynchronous reset inputs. ivl_assert(*this, ! ff_aclr.pin(pin).is_linked()); ivl_assert(*this, rst->pin_count()==1); connect(ff_aclr.pin(pin), rst->pin(0)); - aset_value[pin] = rst_drv; - } else if (rst_drv==ones) { - // Don't yet support multiple asynchronous set inputs. - ivl_assert(*this, ! ff_aset.pin(pin).is_linked()); - - ivl_assert(*this, rst->pin_count()==1); - connect(ff_aset.pin(pin), rst->pin(0)); - aset_value[pin] = rst_drv; } else { + // Don't yet support multiple asynchronous set inputs. ivl_assert(*this, ! ff_aset.pin(pin).is_linked()); + ivl_assert(*this, rst->pin_count()==1); connect(ff_aset.pin(pin), rst->pin(0)); - aset_value[pin] = rst_drv; + if (rst_drv!=ones) + aset_value[pin] = rst_drv; } } @@ -1723,7 +1718,7 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetBus&ff_ce, NetBus&ff_aclr,NetBus&ff_aset, - vector &aset_value, + vector&aset_value, NexusSet&nex_map, NetBus&nex_out, const vector&events_in) { @@ -1825,7 +1820,6 @@ bool NetProcTop::synth_sync(Design*des) } NexusSet nex_set; - statement_->nex_output(nex_set); vector aset_value(nex_set.size()); From d39c284055f5782e22740ff831a5b9bc135fde55 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 9 Jun 2015 08:59:28 +0100 Subject: [PATCH 061/595] Observe and propagate failures when synthesising lval concatenations. --- synth2.cc | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/synth2.cc b/synth2.cc index d94548298..86d1a9d43 100644 --- a/synth2.cc +++ b/synth2.cc @@ -79,6 +79,7 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, NetAssign_*full_lval = lval_; NetExpr*full_rval = rval_; unsigned offset = 0; + bool flag = true; while (lval_) { unsigned width = lval_->lwidth(); NetEConst*base = new NetEConst(verinum(offset)); @@ -88,14 +89,14 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, eval_expr(rval_, width); NetAssign_*more = lval_->more; lval_->more = 0; - synth_async(des, scope, nex_map, nex_out, - accumulated_nex_out); + if (!synth_async(des, scope, nex_map, nex_out, accumulated_nex_out)) + flag = false; lval_ = lval_->more = more; offset += width; } lval_ = full_lval; rval_ = full_rval; - return true; + return flag; } NetNet*rsig = rval_->synthesize(des, scope, rval_); From b242663cae4500b4c68edffb34b1dff5762b2b62 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 13 Jun 2015 15:56:12 +0100 Subject: [PATCH 062/595] Support negedge flip-flops in synthesis and in vvp. Also extend the support for FF asynchronous set values to vvp and fix the dff functor in vvp to correctly model asynchronous set/clr behaviour. --- design_dump.cc | 10 ++- ivl.def | 1 + ivl_target.h | 3 +- netlist.cc | 11 ++- netlist.h | 18 +++-- syn-rules.y | 10 +-- synth2.cc | 64 ++++++++--------- t-dll-api.cc | 14 +++- t-dll.cc | 13 +++- t-dll.h | 3 +- tgt-stub/stub.c | 7 +- tgt-vlog95/logic_lpm.c | 64 ++++++++++++++--- tgt-vvp/vvp_scope.c | 48 ++++++++----- vvp/README.txt | 30 ++++---- vvp/compile.h | 9 +-- vvp/dff.cc | 152 +++++++++++++++++++++-------------------- vvp/dff.h | 72 ++++++++++++------- vvp/lexor.lex | 9 ++- vvp/parse.y | 32 ++++++--- 19 files changed, 356 insertions(+), 214 deletions(-) diff --git a/design_dump.cc b/design_dump.cc index 123917d16..b92bd2c4e 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2015 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 @@ -677,8 +677,12 @@ void NetConst::dump_node(ostream&o, unsigned ind) const void NetFF::dump_node(ostream&o, unsigned ind) const { o << setw(ind) << "" << "LPM_FF: " << name() - << " scope=" << scope_path(scope()) - << " aset_value=" << aset_value_ << endl; + << " scope=" << scope_path(scope()); + if (negedge_) + o << " negedge"; + else + o << " posedge"; + o << " aset_value=" << aset_value_ << endl; dump_node_pins(o, ind+4); dump_obj_attr(o, ind+4); diff --git a/ivl.def b/ivl.def index a49849ba7..562211831 100644 --- a/ivl.def +++ b/ivl.def @@ -125,6 +125,7 @@ ivl_lpm_enable ivl_lpm_file ivl_lpm_lineno ivl_lpm_name +ivl_lpm_negedge ivl_lpm_q ivl_lpm_scope ivl_lpm_select diff --git a/ivl_target.h b/ivl_target.h index 4cb84d786..959a6fb65 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -1,7 +1,7 @@ #ifndef IVL_ivl_target_H #define IVL_ivl_target_H /* - * Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2015 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 @@ -1418,6 +1418,7 @@ extern ivl_signal_t ivl_lpm_array(ivl_lpm_t net); /* IVL_LPM_PART IVL_LPM_SUBSTITUTE */ extern unsigned ivl_lpm_base(ivl_lpm_t net); /* IVL_LPM_FF */ +extern unsigned ivl_lpm_negedge(ivl_lpm_t net); extern ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net); /* IVL_LPM_UFUNC */ extern ivl_scope_t ivl_lpm_define(ivl_lpm_t net); diff --git a/netlist.cc b/netlist.cc index 44f142246..ae4f95349 100644 --- a/netlist.cc +++ b/netlist.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2015 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 @@ -1153,8 +1153,8 @@ unsigned NetReplicate::repeat() const * ... */ -NetFF::NetFF(NetScope*s, perm_string n, unsigned width__) -: NetNode(s, n, 8), width_(width__) +NetFF::NetFF(NetScope*s, perm_string n, bool negedge__, unsigned width__) +: NetNode(s, n, 8), negedge_(negedge__), width_(width__) { pin_Clock().set_dir(Link::INPUT); pin_Enable().set_dir(Link::INPUT); @@ -1170,6 +1170,11 @@ NetFF::~NetFF() { } +bool NetFF::is_negedge() const +{ + return negedge_; +} + unsigned NetFF::width() const { return width_; diff --git a/netlist.h b/netlist.h index a9cea0ecc..8a3e3f98f 100644 --- a/netlist.h +++ b/netlist.h @@ -1,7 +1,7 @@ #ifndef IVL_netlist_H #define IVL_netlist_H /* - * Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2015 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -1622,9 +1622,10 @@ class NetModulo : public NetNode { class NetFF : public NetNode { public: - NetFF(NetScope*s, perm_string n, unsigned vector_width); + NetFF(NetScope*s, perm_string n, bool negedge, unsigned vector_width); ~NetFF(); + bool is_negedge() const; unsigned width() const; Link& pin_Clock(); @@ -1656,6 +1657,7 @@ class NetFF : public NetNode { virtual void functor_node(Design*des, functor_t*fun); private: + bool negedge_; unsigned width_; verinum aset_value_; verinum sset_value_; @@ -2618,9 +2620,10 @@ class NetProc : public virtual LineInfo { // picked off by e.g. condit statements as set/reset inputs to // the flipflop being generated. virtual bool synth_sync(Design*des, NetScope*scope, + bool&ff_negedge, NetNet*ff_clock, NetBus&ff_ce, NetBus&ff_aclr, NetBus&ff_aset, - vector&aset_value, + vector&ff_aset_value, NexusSet&nex_map, NetBus&nex_out, const std::vector&events); @@ -2900,9 +2903,10 @@ class NetBlock : public NetProc { NetBus&accumulated_nex_out); bool synth_sync(Design*des, NetScope*scope, + bool&ff_negedge, NetNet*ff_clk, NetBus&ff_ce, NetBus&ff_aclr,NetBus&ff_aset, - vector&aset_value, + vector&ff_aset_value, NexusSet&nex_map, NetBus&nex_out, const std::vector&events); @@ -3042,9 +3046,10 @@ class NetCondit : public NetProc { NetBus&accumulated_nex_out); bool synth_sync(Design*des, NetScope*scope, + bool&ff_negedge, NetNet*ff_clk, NetBus&ff_ce, NetBus&ff_aclr,NetBus&ff_aset, - vector&aset_value, + vector&ff_aset_value, NexusSet&nex_map, NetBus&nex_out, const std::vector&events); @@ -3320,9 +3325,10 @@ class NetEvWait : public NetProc { NetBus&accumulated_nex_out); virtual bool synth_sync(Design*des, NetScope*scope, + bool&ff_negedge, NetNet*ff_clk, NetBus&ff_ce, NetBus&ff_aclr,NetBus&ff_aset, - vector&aset_value, + vector&ff_aset_value, NexusSet&nex_map, NetBus&nex_out, const std::vector&events); diff --git a/syn-rules.y b/syn-rules.y index 8a86fe6e5..ac90c186a 100644 --- a/syn-rules.y +++ b/syn-rules.y @@ -1,7 +1,7 @@ %{ /* - * Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2015 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 @@ -121,11 +121,6 @@ static void hookup_DFF_CE(NetFF*ff, NetESignal*d, NetEvProbe*pclk, connect(ff->pin_Clock(), pclk->pin(0)); if (ce) connect(ff->pin_Enable(), ce->pin(0)); - ff->attribute(perm_string::literal("LPM_FFType"), verinum("DFF")); - if (pclk->edge() == NetEvProbe::NEGEDGE) - ff->attribute(perm_string::literal("Clock:LPM_Polarity"), verinum("INVERT")); - - /* This lval_ represents a reg that is a WIRE in the synthesized results. This function signals the destructor to change the REG that this l-value refers to into a @@ -165,7 +160,8 @@ static void make_DFF_CE(Design*des, NetProcTop*top, if (a->sig()) { // cerr << "new NetFF named " << a->name() << endl; - NetFF*ff = new NetFF(top->scope(), a->name(), + bool negedge = pclk->edge() == NetEvProbe::NEGEDGE; + NetFF*ff = new NetFF(top->scope(), a->name(), negedge, a->sig()->vector_width()); hookup_DFF_CE(ff, d, pclk, ce, a, rval_pinoffset); des->add_node(ff); diff --git a/synth2.cc b/synth2.cc index 86d1a9d43..44f7e07f6 100644 --- a/synth2.cc +++ b/synth2.cc @@ -34,9 +34,10 @@ bool NetProc::synth_async(Design*, NetScope*, NexusSet&, NetBus&, NetBus&) } bool NetProc::synth_sync(Design*des, NetScope*scope, + bool& /* ff_negedge */, NetNet* /* ff_clk */, NetBus& /* ff_ce */, NetBus& /* ff_aclr*/, NetBus& /* ff_aset*/, - vector& /*aset_value*/, + vector& /*ff_aset_value*/, NexusSet&nex_map, NetBus&nex_out, const vector&events) { @@ -1383,9 +1384,10 @@ bool NetProcTop::synth_async(Design*des) * the statements may each infer different reset and enable signals. */ bool NetBlock::synth_sync(Design*des, NetScope*scope, + bool&ff_negedge, NetNet*ff_clk, NetBus&ff_ce, NetBus&ff_aclr,NetBus&ff_aset, - vector&aset_value, + vector&ff_aset_value, NexusSet&nex_map, NetBus&nex_out, const vector&events_in) { @@ -1428,8 +1430,9 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, subset of the statement. The tmp_map is the output nexa that we expect, and the tmp_out is where we want those outputs connected. */ - bool ok_flag = cur->synth_sync(des, scope, ff_clk, tmp_ce, - ff_aclr, ff_aset, aset_value, + bool ok_flag = cur->synth_sync(des, scope, + ff_negedge, ff_clk, tmp_ce, + ff_aclr, ff_aset, ff_aset_value, tmp_set, tmp_out, events_in); flag = flag && ok_flag; @@ -1465,9 +1468,10 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, * expression is connected to an event, or not. */ bool NetCondit::synth_sync(Design*des, NetScope*scope, + bool&ff_negedge, NetNet*ff_clk, NetBus&ff_ce, NetBus&ff_aclr,NetBus&ff_aset, - vector&aset_value, + vector&ff_aset_value, NexusSet&nex_map, NetBus&nex_out, const vector&events_in) { @@ -1514,25 +1518,13 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, for (unsigned pin = 0 ; pin < tmp_out.pin_count() ; pin += 1) { Nexus*rst_nex = tmp_out.pin(pin).nexus(); - vector rst_mask = rst_nex->driven_mask(); - if (debug_synth2) { - cerr << get_fileline() << ": NetCondit::synth_sync: " - << "nex_out pin=" << pin - << ", rst_mask.size()==" << rst_mask.size() - << ", rst_nex->vector_width()=" << rst_nex->vector_width() - << endl; - } - - for (size_t bit = 0 ; bit < rst_mask.size() ; bit += 1) { - if (rst_mask[bit]==false) { - cerr << get_fileline() << ": sorry: " - << "Asynchronous LOAD not implemented." << endl; - return false; - } + if (! rst_nex->drivers_constant()) { + cerr << get_fileline() << ": sorry: " + << "Asynchronous LOAD not implemented." << endl; + return false; } verinum rst_drv = rst_nex->driven_vector(); - ivl_assert(*this, rst_drv.len()==rst_mask.size()); verinum zero (verinum::V0, rst_drv.len()); verinum ones (verinum::V1, rst_drv.len()); @@ -1551,12 +1543,13 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, ivl_assert(*this, rst->pin_count()==1); connect(ff_aset.pin(pin), rst->pin(0)); if (rst_drv!=ones) - aset_value[pin] = rst_drv; + ff_aset_value[pin] = rst_drv; } } - return else_->synth_sync(des, scope, ff_clk, ff_ce, - ff_aclr, ff_aset, aset_value, + return else_->synth_sync(des, scope, + ff_negedge, ff_clk, ff_ce, + ff_aclr, ff_aset, ff_aset_value, nex_map, nex_out, vector(0)); } @@ -1711,15 +1704,19 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, } } - bool flag = if_->synth_sync(des, scope, ff_clk, ff_ce, ff_aclr, ff_aset, aset_value, nex_map, nex_out, events_in); + bool flag = if_->synth_sync(des, scope, + ff_negedge, ff_clk, ff_ce, + ff_aclr, ff_aset, ff_aset_value, + nex_map, nex_out, events_in); return flag; } bool NetEvWait::synth_sync(Design*des, NetScope*scope, + bool&ff_negedge, NetNet*ff_clk, NetBus&ff_ce, NetBus&ff_aclr,NetBus&ff_aset, - vector&aset_value, + vector&ff_aset_value, NexusSet&nex_map, NetBus&nex_out, const vector&events_in) { @@ -1789,8 +1786,7 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, connect(ff_clk->pin(0), pclk->pin(0)); if (pclk->edge() == NetEvProbe::NEGEDGE) { - perm_string polarity = perm_string::literal("Clock:LPM_Polarity"); - ff_clk->attribute(polarity, verinum("INVERT")); + ff_negedge = true; if (debug_synth2) { cerr << get_fileline() << ": debug: " @@ -1800,8 +1796,9 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, } /* Synthesize the input to the DFF. */ - bool flag = statement_->synth_sync(des, scope, ff_clk, ff_ce, - ff_aclr, ff_aset, aset_value, + bool flag = statement_->synth_sync(des, scope, + ff_negedge, ff_clk, ff_ce, + ff_aclr, ff_aset, ff_aset_value, nex_map, nex_out, events); return flag; @@ -1857,7 +1854,10 @@ bool NetProcTop::synth_sync(Design*des) // Connect the input later. /* Synthesize the input to the DFF. */ - bool flag = statement_->synth_sync(des, scope(), clock, ce, aclr, aset, aset_value, + bool negedge = false; + bool flag = statement_->synth_sync(des, scope(), + negedge, clock, ce, + aclr, aset, aset_value, nex_set, nex_d, vector()); if (! flag) { @@ -1876,7 +1876,7 @@ bool NetProcTop::synth_sync(Design*des) } NetFF*ff2 = new NetFF(scope(), scope()->local_symbol(), - nex_set[idx].wid); + negedge, nex_set[idx].wid); des->add_node(ff2); ff2->set_line(*this); ff2->aset_value(aset_value[idx]); diff --git a/t-dll-api.cc b/t-dll-api.cc index 5a77f26eb..a4e33852e 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -1090,6 +1090,18 @@ extern "C" unsigned ivl_lpm_base(ivl_lpm_t net) } } +extern "C" unsigned ivl_lpm_negedge(ivl_lpm_t net) +{ + assert(net); + switch (net->type) { + case IVL_LPM_FF: + return net->u_.ff.negedge_flag; + default: + assert(0); + return 0; + } +} + extern "C" ivl_nexus_t ivl_lpm_clk(ivl_lpm_t net) { assert(net); diff --git a/t-dll.cc b/t-dll.cc index 3c0b9fa2d..23be1f7ce 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -1938,6 +1938,9 @@ void dll_target::lpm_ff(const NetFF*net) const Nexus*nex; + /* Set the clock polarity. */ + obj->u_.ff.negedge_flag = net->is_negedge(); + /* Set the clk signal to point to the nexus, and the nexus to point back to this device. */ nex = net->pin_Clock().nexus(); @@ -1976,7 +1979,10 @@ void dll_target::lpm_ff(const NetFF*net) nexus_lpm_add(obj->u_.ff.aset, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ); verinum tmp = net->aset_value(); - obj->u_.ff.aset_value = expr_from_value_(tmp); + if (tmp.len() > 0) + obj->u_.ff.aset_value = expr_from_value_(tmp); + else + obj->u_.ff.aset_value = 0; } else { obj->u_.ff.aset = 0; @@ -2001,7 +2007,10 @@ void dll_target::lpm_ff(const NetFF*net) nexus_lpm_add(obj->u_.ff.sset, obj, 0, IVL_DR_HiZ, IVL_DR_HiZ); verinum tmp = net->sset_value(); - obj->u_.ff.sset_value = expr_from_value_(tmp); + if (tmp.len() > 0) + obj->u_.ff.sset_value = expr_from_value_(tmp); + else + obj->u_.ff.sset_value = 0; } else { obj->u_.ff.sset = 0; diff --git a/t-dll.h b/t-dll.h index 918a95bde..97ed7607f 100644 --- a/t-dll.h +++ b/t-dll.h @@ -1,7 +1,7 @@ #ifndef IVL_t_dll_H #define IVL_t_dll_H /* - * Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2015 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 @@ -370,6 +370,7 @@ struct ivl_lpm_s { union { struct ivl_lpm_ff_s { + unsigned negedge_flag :1; ivl_nexus_t clk; ivl_nexus_t we; ivl_nexus_t aclr; diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index 451da0441..f71b70d0a 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2015 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 @@ -497,10 +497,11 @@ static void show_lpm_concat(ivl_lpm_t net) static void show_lpm_ff(ivl_lpm_t net) { ivl_nexus_t nex; + char*edge = ivl_lpm_negedge(net) ? "negedge" : "posedge"; unsigned width = ivl_lpm_width(net); - fprintf(out, " LPM_FF %s: \n", - ivl_lpm_basename(net), width); + fprintf(out, " LPM_FF %s: \n", + ivl_lpm_basename(net), edge, width); nex = ivl_lpm_clk(net); fprintf(out, " clk: %p\n", nex); diff --git a/tgt-vlog95/logic_lpm.c b/tgt-vlog95/logic_lpm.c index 1cffbd1e0..5a7bfcdd6 100644 --- a/tgt-vlog95/logic_lpm.c +++ b/tgt-vlog95/logic_lpm.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2014 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2011-2015 Cary R. (cygcary@yahoo.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1245,7 +1245,43 @@ static void emit_posedge_dff_prim(void) fprintf(vlog_out, "endprimitive\n"); } +static void emit_negedge_dff_prim(void) +{ + fprintf(vlog_out, "\n"); + fprintf(vlog_out, "/* Icarus generated UDP to represent a synthesized " + "negative edge D-FF. */\n"); + fprintf(vlog_out, "primitive IVL_negedge_DFF " + "(q, clk, en, d, clr, set);\n"); + fprintf(vlog_out, "%*coutput q;\n", indent_incr, ' '); + fprintf(vlog_out, "%*cinput clk, en, d, clr, set;\n", indent_incr, ' '); + fprintf(vlog_out, "%*creg q;\n", indent_incr, ' '); + fprintf(vlog_out, "%*ctable\n", indent_incr, ' '); + fprintf(vlog_out, "%*cf 1 0 0 0 : ? : 0 ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*cf 1 1 0 0 : ? : 1 ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*cn 1 0 0 0 : 0 : - ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*cn 1 1 0 0 : 1 : - ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*cn x 0 0 0 : 0 : - ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*cn x 1 0 0 : 1 : - ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*cp ? ? 0 0 : ? : - ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*c* 0 ? 0 0 : ? : - ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*c? * ? ? ? : ? : - ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*c? ? * ? ? : ? : - ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*c? ? ? * ? : ? : - ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*c? ? ? ? * : ? : - ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*c? ? ? 0 1 : ? : 1 ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*c? ? ? 0 x : 1 : - ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*c? ? ? 0 x : 0 : x ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*c? ? ? 1 ? : ? : 0 ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*c? ? ? x 0 : 0 : - ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*c? ? ? x 0 : 1 : x ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*c? ? ? x x : ? : x ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*c? ? ? x 1 : ? : x ;\n", 2*indent_incr, ' '); + fprintf(vlog_out, "%*cendtable\n", indent_incr, ' '); + fprintf(vlog_out, "endprimitive\n"); +} + static unsigned need_posedge_dff_prim = 0; +static unsigned need_negedge_dff_prim = 0; /* * Synthesis creates a D-FF LPM object. To allow this to be simulated as @@ -1263,14 +1299,14 @@ void emit_icarus_generated_udps() { /* Emit the copyright information and LGPL note and then emit any * needed primitives. */ - if (need_posedge_dff_prim) { + if (need_posedge_dff_prim || need_negedge_dff_prim) { fprintf(vlog_out, "\n" "/*\n" " * This is the copyright information for the following primitive(s)\n" " * (library elements).\n" " *\n" -" * Copyright (C) 2011 Cary R. (cygcary@yahoo.com)\n" +" * Copyright (C) 2011-2015 Cary R. (cygcary@yahoo.com)\n" " *\n" " * This library is free software; you can redistribute it and/or\n" " * modify it under the terms of the GNU Lesser General Public\n" @@ -1290,13 +1326,12 @@ void emit_icarus_generated_udps() "NOTE: vlog95: Adding LGPL 2.1 primitive(s) at the end of the output file.\n"); } if (need_posedge_dff_prim) emit_posedge_dff_prim(); + if (need_negedge_dff_prim) emit_negedge_dff_prim(); } static void emit_lpm_ff(ivl_scope_t scope, ivl_lpm_t lpm) { -// HERE: No support for lpm attributes and hence polarity information. -// ivl_attribute_t clock_pol = find_lpm_attr(lpm, "Clock:LPM_Polarity"); - ivl_attribute_t clock_pol = 0; + unsigned negedge = ivl_lpm_negedge(lpm); ivl_expr_t aset_expr = ivl_lpm_aset_value(lpm); ivl_expr_t sset_expr = ivl_lpm_sset_value(lpm); ivl_nexus_t nex; @@ -1305,7 +1340,13 @@ static void emit_lpm_ff(ivl_scope_t scope, ivl_lpm_t lpm) const char *sset_bits = 0; /* For now we only support a width of 1 for these bits. */ if (aset_expr) { - assert(ivl_expr_width(aset_expr) == 1); + if (ivl_expr_width(aset_expr) != 1) { + fprintf(stderr, "%s:%u: vlog95 sorry: FF LPMs with " + "multi-bit asynchronous set values are not " + "currently translated.\n", + ivl_lpm_file(lpm), ivl_lpm_lineno(lpm)); + vlog_errors += 1; + } aset_bits = ivl_expr_bits(aset_expr); } if (sset_expr) { @@ -1314,9 +1355,7 @@ static void emit_lpm_ff(ivl_scope_t scope, ivl_lpm_t lpm) } fprintf(vlog_out, "%*c", indent, ' '); - /* If there is a clock polarity attribute then we have a negative - * edge D-FF. */ - if (clock_pol) { + if (negedge) { fprintf(vlog_out, "IVL_negedge_DFF"); } else { fprintf(vlog_out, "IVL_posedge_DFF"); @@ -1404,7 +1443,10 @@ static void emit_lpm_ff(ivl_scope_t scope, ivl_lpm_t lpm) else fprintf(vlog_out, "1'b0"); fprintf(vlog_out, ");\n"); /* We need to emit a primitive for this instance. */ - need_posedge_dff_prim = 1; + if (negedge) + need_negedge_dff_prim = 1; + else + need_posedge_dff_prim = 1; } static ivl_signal_t get_output_from_nexus(ivl_scope_t scope, ivl_nexus_t nex, diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 44d5b1e53..6a333d926 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -1716,44 +1716,45 @@ static void draw_lpm_concat(ivl_lpm_t net) /* * Emit a DFF primitive. This uses the following syntax: * - * .dff , , , ; - * - * The async pin currently sets the stored data value and propagates it - * to the output (not very useful). This routine always sets the async - * value to high-Z which is ignored in the VVP code. This is all OK - * since synthesis is not currently functional. + * .dff , , [, [, ]]; */ static void draw_lpm_ff(ivl_lpm_t net) { ivl_nexus_t nex; - /* Sync/Async set/clear control is currently only supported in V0.8 - * which has working synthesis. If/when this is added see that code - * for clues about how this should be implemented. The dff primitive - * used here (from vvp) needs to be improved to support both an - * async set and clear. See the UDP generated by the tgt-vlog95 code - * generator in V0.10 and later for how this might be done. */ + /* Sync set/clear control is not currently supported. This is not + * a problem, as synthesis can incorporate this in the D input + * expression. All modern synthesis tools do this as a matter of + * course, as most cell libraries don't contain flip-flops with + * sync set/clear. + */ assert(ivl_lpm_sync_clr(net) == 0); assert(ivl_lpm_sync_set(net) == 0); + unsigned width = ivl_lpm_width(net); + char*edge = ivl_lpm_negedge(net) ? "n" : "p"; if (ivl_lpm_async_clr(net)) { + /* Synthesis doesn't currently support both set and clear. + If it ever does, it might be better to implement the + flip-flop as a UDP. See tgt-vlog95 for an example of + how to do this. */ if (ivl_lpm_async_set(net)) { - fprintf(stderr, "%s:%u:vvp.tgt: sorry: No support for a D-ff " + fprintf(stderr, "%s:%u:vvp.tgt: sorry: No support for a DFF " "with both an async. set and clear.\n", ivl_lpm_file(net), ivl_lpm_lineno(net)); vvp_errors += 1; } - fprintf(vvp_out, "L_%p .dff/aclr ", net); + fprintf(vvp_out, "L_%p .dff/%s/aclr %u ", net, edge, width); } else if (ivl_lpm_async_set(net)) { - fprintf(vvp_out, "L_%p .dff/aset ", net); + fprintf(vvp_out, "L_%p .dff/%s/aset %u ", net, edge, width); } else { - fprintf(vvp_out, "L_%p .dff ", net); + fprintf(vvp_out, "L_%p .dff/%s %u ", net, edge, width); } nex = ivl_lpm_data(net,0); assert(nex); fprintf(vvp_out, "%s", draw_net_input(nex)); - assert(width_of_nexus(nex) == ivl_lpm_width(net));; + assert(width_of_nexus(nex) == width);; nex = ivl_lpm_clk(net); assert(nex); @@ -1769,11 +1770,24 @@ static void draw_lpm_ff(ivl_lpm_t net) } if ( (nex = ivl_lpm_async_clr(net)) ) { + assert(width_of_nexus(nex) == 1);; fprintf(vvp_out, ", %s", draw_net_input(nex)); } if ( (nex = ivl_lpm_async_set(net)) ) { + ivl_expr_t val = ivl_lpm_aset_value(net); + assert(width_of_nexus(nex) == 1);; fprintf(vvp_out, ", %s", draw_net_input(nex)); + if (val) { + unsigned nbits = ivl_expr_width(val); + const char*bits = ivl_expr_bits(val); + unsigned bb; + assert(nbits == width); + fprintf(vvp_out, ", C4<"); + for (bb = 0 ; bb < nbits; bb += 1) + fprintf(vvp_out, "%c", bits[nbits-bb-1]); + fprintf(vvp_out, ">"); + } } fprintf(vvp_out, ";\n"); diff --git a/vvp/README.txt b/vvp/README.txt index b1a98768d..e151543b8 100644 --- a/vvp/README.txt +++ b/vvp/README.txt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com) * */ @@ -192,18 +192,24 @@ The Verilog language itself does not have a DFF primitive, but post synthesis readily creates DFF devices that are best simulated with a common device. Thus, there is the DFF statement to create DFF devices: - , ; , ; , ; + , ; + , ; Whereas the arithmetic statements generate an output the width of , the comparisons produce a single bit vector result. The plain diff --git a/vvp/arith.cc b/vvp/arith.cc index b905c46aa..9348227a2 100644 --- a/vvp/arith.cc +++ b/vvp/arith.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 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 @@ -868,6 +868,76 @@ void vvp_cmp_gt::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, recv_vec4_base_(ptr, bit, BIT4_0); } +vvp_cmp_weq::vvp_cmp_weq(unsigned wid) +: vvp_arith_(wid) +{ +} + +void vvp_cmp_weq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, + vvp_context_t) +{ + dispatch_operand_(ptr, bit); + + vvp_vector4_t eeq (1); + eeq.set_bit(0, BIT4_1); + + assert(op_a_.size() == op_b_.size()); + for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) { + vvp_bit4_t a = op_a_.value(idx); + vvp_bit4_t b = op_b_.value(idx); + if (b == BIT4_X) + continue; + else if (b == BIT4_Z) + continue; + else if (a == BIT4_X) + eeq.set_bit(0, BIT4_X); + else if (a == BIT4_Z) + eeq.set_bit(0, BIT4_X); + else if (a != b) { + eeq.set_bit(0, BIT4_0); + break; + } + } + + vvp_net_t*net = ptr.ptr(); + net->send_vec4(eeq, 0); +} + +vvp_cmp_wne::vvp_cmp_wne(unsigned wid) +: vvp_arith_(wid) +{ +} + +void vvp_cmp_wne::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, + vvp_context_t) +{ + dispatch_operand_(ptr, bit); + + vvp_vector4_t eeq (1); + eeq.set_bit(0, BIT4_0); + + assert(op_a_.size() == op_b_.size()); + for (unsigned idx = 0 ; idx < op_a_.size() ; idx += 1) { + vvp_bit4_t a = op_a_.value(idx); + vvp_bit4_t b = op_b_.value(idx); + if (b == BIT4_X) + continue; + else if (b == BIT4_Z) + continue; + else if (a == BIT4_X) + eeq.set_bit(0, BIT4_X); + else if (a == BIT4_Z) + eeq.set_bit(0, BIT4_X); + else if (a != b) { + eeq.set_bit(0, BIT4_1); + break; + } + } + + vvp_net_t*net = ptr.ptr(); + net->send_vec4(eeq, 0); +} + vvp_shiftl::vvp_shiftl(unsigned wid) : vvp_arith_(wid) diff --git a/vvp/arith.h b/vvp/arith.h index 9caed5707..1cf6888d2 100644 --- a/vvp/arith.h +++ b/vvp/arith.h @@ -1,7 +1,7 @@ #ifndef IVL_arith_H #define IVL_arith_H /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 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 @@ -200,6 +200,24 @@ class vvp_cmp_ne : public vvp_arith_ { }; +class vvp_cmp_weq : public vvp_arith_ { + + public: + explicit vvp_cmp_weq(unsigned wid); + void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, + vvp_context_t); + +}; + +class vvp_cmp_wne : public vvp_arith_ { + + public: + explicit vvp_cmp_wne(unsigned wid); + void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, + vvp_context_t); + +}; + /* * This base class implements both GT and GE comparisons. The derived diff --git a/vvp/codes.h b/vvp/codes.h index 41509a97f..2b3e44cb2 100644 --- a/vvp/codes.h +++ b/vvp/codes.h @@ -1,7 +1,7 @@ #ifndef IVL_codes_H #define IVL_codes_H /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 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 @@ -75,6 +75,8 @@ extern bool of_CMPIS(vthread_t thr, vvp_code_t code); extern bool of_CMPSTR(vthread_t thr, vvp_code_t code); extern bool of_CMPU(vthread_t thr, vvp_code_t code); extern bool of_CMPIU(vthread_t thr, vvp_code_t code); +extern bool of_CMPWE(vthread_t thr, vvp_code_t code); +extern bool of_CMPWNE(vthread_t thr, vvp_code_t code); extern bool of_CMPWR(vthread_t thr, vvp_code_t code); extern bool of_CMPWS(vthread_t thr, vvp_code_t code); extern bool of_CMPWU(vthread_t thr, vvp_code_t code); diff --git a/vvp/compile.cc b/vvp/compile.cc index 39392c64e..7a13a67a7 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 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 @@ -117,21 +117,23 @@ static const struct opcode_table_s opcode_table[] = { { "%cassign/vec4", of_CASSIGN_VEC4, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, { "%cassign/vec4/off",of_CASSIGN_VEC4_OFF,2,{OA_FUNC_PTR,OA_BIT1, OA_NONE} }, { "%cassign/wr", of_CASSIGN_WR, 1,{OA_FUNC_PTR,OA_NONE, OA_NONE} }, - { "%cast2", of_CAST2, 0, {OA_NONE, OA_NONE, OA_NONE} }, - { "%cmp/e", of_CMPE, 0, {OA_NONE, OA_NONE, OA_NONE} }, - { "%cmp/ne", of_CMPNE, 0, {OA_NONE, OA_NONE, OA_NONE} }, - { "%cmp/s", of_CMPS, 0, {OA_NONE, OA_NONE, OA_NONE} }, - { "%cmp/str",of_CMPSTR, 0, {OA_NONE, OA_NONE, OA_NONE} }, - { "%cmp/u", of_CMPU, 0, {OA_NONE, OA_NONE, OA_NONE} }, - { "%cmp/wr", of_CMPWR, 0, {OA_NONE, OA_NONE, OA_NONE} }, - { "%cmp/ws", of_CMPWS, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, - { "%cmp/wu", of_CMPWU, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, - { "%cmp/x", of_CMPX, 0, {OA_NONE, OA_NONE, OA_NONE} }, - { "%cmp/z", of_CMPZ, 0, {OA_NONE, OA_NONE, OA_NONE} }, - { "%cmpi/e", of_CMPIE, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%cmpi/ne",of_CMPINE, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%cmpi/s", of_CMPIS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, - { "%cmpi/u", of_CMPIU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, + { "%cast2", of_CAST2, 0, {OA_NONE, OA_NONE, OA_NONE} }, + { "%cmp/e", of_CMPE, 0, {OA_NONE, OA_NONE, OA_NONE} }, + { "%cmp/ne", of_CMPNE, 0, {OA_NONE, OA_NONE, OA_NONE} }, + { "%cmp/s", of_CMPS, 0, {OA_NONE, OA_NONE, OA_NONE} }, + { "%cmp/str", of_CMPSTR, 0, {OA_NONE, OA_NONE, OA_NONE} }, + { "%cmp/u", of_CMPU, 0, {OA_NONE, OA_NONE, OA_NONE} }, + { "%cmp/we", of_CMPWE, 0, {OA_NONE, OA_NONE, OA_NONE} }, + { "%cmp/wne", of_CMPWNE, 0, {OA_NONE, OA_NONE, OA_NONE} }, + { "%cmp/wr", of_CMPWR, 0, {OA_NONE, OA_NONE, OA_NONE} }, + { "%cmp/ws", of_CMPWS, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, + { "%cmp/wu", of_CMPWU, 2, {OA_BIT1, OA_BIT2, OA_NONE} }, + { "%cmp/x", of_CMPX, 0, {OA_NONE, OA_NONE, OA_NONE} }, + { "%cmp/z", of_CMPZ, 0, {OA_NONE, OA_NONE, OA_NONE} }, + { "%cmpi/e", of_CMPIE, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, + { "%cmpi/ne", of_CMPINE, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, + { "%cmpi/s", of_CMPIS, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, + { "%cmpi/u", of_CMPIU, 3, {OA_BIT1, OA_BIT2, OA_NUMBER} }, { "%concat/str", of_CONCAT_STR, 0,{OA_NONE, OA_NONE, OA_NONE} }, { "%concat/vec4", of_CONCAT_VEC4, 0,{OA_NONE, OA_NONE, OA_NONE} }, { "%concati/str", of_CONCATI_STR, 1,{OA_STRING,OA_NONE, OA_NONE} }, @@ -1402,6 +1404,38 @@ void compile_cmp_gt_r(char*label, unsigned argc, struct symb_s*argv) make_arith(arith, label, argc, argv); } +void compile_cmp_weq(char*label, long wid, + unsigned argc, struct symb_s*argv) +{ + assert( wid > 0 ); + + if (argc != 2) { + fprintf(stderr, "%s .cmp/weq has wrong number of symbols\n",label); + compile_errors += 1; + return; + } + + vvp_arith_ *arith = new vvp_cmp_weq(wid); + + make_arith(arith, label, argc, argv); +} + +void compile_cmp_wne(char*label, long wid, + unsigned argc, struct symb_s*argv) +{ + assert( wid > 0 ); + + if (argc != 2) { + fprintf(stderr, "%s .cmp/wne has wrong number of symbols\n",label); + compile_errors += 1; + return; + } + + vvp_arith_ *arith = new vvp_cmp_wne(wid); + + make_arith(arith, label, argc, argv); +} + void compile_delay(char*label, unsigned width, vvp_delay_t*delay, struct symb_s arg) diff --git a/vvp/compile.h b/vvp/compile.h index 13e60ce23..b49a6dea4 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -1,7 +1,7 @@ #ifndef IVL_compile_H #define IVL_compile_H /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 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 @@ -195,6 +195,10 @@ extern void compile_cmp_ge(char*label, long width, bool signed_flag, unsigned argc, struct symb_s*argv); extern void compile_cmp_gt(char*label, long width, bool signed_flag, unsigned argc, struct symb_s*argv); +extern void compile_cmp_weq(char*label, long width, + unsigned argc, struct symb_s*argv); +extern void compile_cmp_wne(char*label, long width, + unsigned argc, struct symb_s*argv); extern void compile_arith_mult_r(char*label, unsigned argc, struct symb_s*argv); diff --git a/vvp/lexor.lex b/vvp/lexor.lex index 3969c296d..06313f4ef 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -146,6 +146,8 @@ static char* strdupnew(char const *str) ".cmp/gt" { return K_CMP_GT; } ".cmp/gt.r" { return K_CMP_GT_R; } ".cmp/gt.s" { return K_CMP_GT_S; } +".cmp/weq" { return K_CMP_WEQ; } +".cmp/wne" { return K_CMP_WNE; } ".concat" { return K_CONCAT; } ".concat8" { return K_CONCAT8; } ".delay" { return K_DELAY; } diff --git a/vvp/opcodes.txt b/vvp/opcodes.txt index 2e489e88e..fdc513c17 100644 --- a/vvp/opcodes.txt +++ b/vvp/opcodes.txt @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com) * */ @@ -302,6 +302,18 @@ The %cmp/ne and %cmpi/ne variants are the same as the %cmp/e and eliminate the need for a %flag_inv instruction to implement != and !== operations. +* %cmp/we +* %cmp/wne + +These instructions perform a wild comparison of two vectors of equal +size. Two values are pulled from the top of the stack, and not replaced. +The results are written into flag bit 4. The comparisons work like eq/ne +except an x/z bit in the r-value will match any l-value bit. + +The %cmp/wne variant is the same as %cmp/we, but the 4 flag is inverted +in order to eliminate the need for a %flag_inv instruction to implement +the !=? operator. + * %cmp/wr Compare real values for equality and less-then. This opcode pops to @@ -1299,7 +1311,7 @@ table for the xor is: /* - * Copyright (c) 2001-2009 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 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 diff --git a/vvp/parse.y b/vvp/parse.y index cbfc26335..3276a3c58 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -1,7 +1,7 @@ %{ /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 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 @@ -80,7 +80,7 @@ static struct __vpiModPath*modpath_dst = 0; %token K_ARRAY K_ARRAY_2U K_ARRAY_2S K_ARRAY_I K_ARRAY_OBJ K_ARRAY_R K_ARRAY_S K_ARRAY_STR K_ARRAY_PORT %token K_CAST_INT K_CAST_REAL K_CAST_REAL_S K_CAST_2 %token K_CLASS -%token K_CMP_EEQ K_CMP_EQ K_CMP_EQX K_CMP_EQZ +%token K_CMP_EEQ K_CMP_EQ K_CMP_EQX K_CMP_EQZ K_CMP_WEQ K_CMP_WNE %token K_CMP_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R %token K_CMP_GE K_CMP_GE_R K_CMP_GE_S K_CMP_GT K_CMP_GT_R K_CMP_GT_S %token K_CONCAT K_CONCAT8 K_DEBUG K_DELAY K_DFF_N K_DFF_N_ACLR @@ -475,6 +475,16 @@ statement compile_cmp_gt($1, $3, true, obj.cnt, obj.vect); } + | T_LABEL K_CMP_WEQ T_NUMBER ',' symbols ';' + { struct symbv_s obj = $5; + compile_cmp_weq($1, $3, obj.cnt, obj.vect); + } + + | T_LABEL K_CMP_WNE T_NUMBER ',' symbols ';' + { struct symbv_s obj = $5; + compile_cmp_wne($1, $3, obj.cnt, obj.vect); + } + /* Delay nodes take a set of numbers or a set of inputs. The delay node takes two form, one with an array of constants and a single input, and another with an array of inputs. */ diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 64fc3b6a0..46cd46869 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 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 @@ -1945,6 +1945,71 @@ bool of_CMPX(vthread_t thr, vvp_code_t) return true; } +static void do_CMPWE(vthread_t thr, const vvp_vector4_t&lval, const vvp_vector4_t&rval) +{ + assert(rval.size() == lval.size()); + + if (lval.has_xz() || rval.has_xz()) { + + unsigned wid = lval.size(); + vvp_bit4_t eq = BIT4_1; + + for (unsigned idx = 0 ; idx < wid ; idx += 1) { + vvp_bit4_t lv = lval.value(idx); + vvp_bit4_t rv = rval.value(idx); + + if (bit4_is_xz(rv)) + continue; + if ((eq == BIT4_1) && bit4_is_xz(lv)) + eq = BIT4_X; + if ((lv == BIT4_0) && (rv==BIT4_1)) + eq = BIT4_0; + if ((lv == BIT4_1) && (rv==BIT4_0)) + eq = BIT4_0; + + if (eq == BIT4_0) + break; + } + + thr->flags[4] = eq; + + } else { + // If there are no XZ bits anywhere, then the results of + // ==? match the === test. + thr->flags[4] = (lval.eeq(rval)? BIT4_1 : BIT4_0); + } +} + +bool of_CMPWE(vthread_t thr, vvp_code_t) +{ + // We are going to pop these and push nothing in their + // place, but for now it is more efficient to use a constant + // reference. When we finish, pop the stack without copies. + const vvp_vector4_t&rval = thr->peek_vec4(0); + const vvp_vector4_t&lval = thr->peek_vec4(1); + + do_CMPWE(thr, lval, rval); + + thr->pop_vec4(2); + return true; +} + +bool of_CMPWNE(vthread_t thr, vvp_code_t) +{ + // We are going to pop these and push nothing in their + // place, but for now it is more efficient to use a constant + // reference. When we finish, pop the stack without copies. + const vvp_vector4_t&rval = thr->peek_vec4(0); + const vvp_vector4_t&lval = thr->peek_vec4(1); + + do_CMPWE(thr, lval, rval); + + thr->flags[4] = ~thr->flags[4]; + + thr->pop_vec4(2); + return true; +} + bool of_CMPWR(vthread_t thr, vvp_code_t) { double r = thr->pop_real(); From c68a7fede3e51a728909106af8affef0c0f8de07 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 20 Nov 2017 07:30:12 -0800 Subject: [PATCH 530/595] Fix spacing --- elab_expr.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 6699823f6..8722039c1 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2278,8 +2278,8 @@ NetExpr* PECallFunction::elaborate_base_(Design*des, NetScope*scope, NetScope*ds } cerr << get_fileline() << ": internal error: Unable to locate " - "function return value for " << path_ - << " in " << dscope->basename() << "." << endl; + "function return value for " << path_ + << " in " << dscope->basename() << "." << endl; des->errors += 1; return 0; } From 585a0232cbd54e20d1dc41d2cb7712e18784bb8d Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 20 Nov 2017 07:48:35 -0800 Subject: [PATCH 531/595] Add preliminary support for always_comb, always_ff and always_latch --- Statement.cc | 10 +-- Statement.h | 8 +- design_dump.cc | 19 +++++ elaborate.cc | 19 +++-- ivl_target.h | 9 ++- net_nex_input.cc | 177 +++++++++++++++++++++++------------------- netlist.h | 76 +++++++++--------- parse.y | 14 +++- pform.cc | 16 +++- pform_dump.cc | 14 ++++ synth.cc | 5 +- t-dll.h | 4 +- tgt-stub/stub.c | 18 +++++ tgt-verilog/verilog.c | 5 +- tgt-vlog95/stmt.c | 5 +- tgt-vvp/vvp_process.c | 6 ++ 16 files changed, 262 insertions(+), 143 deletions(-) diff --git a/Statement.cc b/Statement.cc index 942558107..92a87a12d 100644 --- a/Statement.cc +++ b/Statement.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2017 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 @@ -294,20 +294,20 @@ PDoWhile::~PDoWhile() } PEventStatement::PEventStatement(const svector&ee) -: expr_(ee), statement_(0) +: expr_(ee), statement_(0), search_funcs_(false) { assert(expr_.count() > 0); } PEventStatement::PEventStatement(PEEvent*ee) -: expr_(1), statement_(0) +: expr_(1), statement_(0), search_funcs_(false) { expr_[0] = ee; } -PEventStatement::PEventStatement(void) -: statement_(0) +PEventStatement::PEventStatement(bool search_funcs) +: statement_(0), search_funcs_(search_funcs) { } diff --git a/Statement.h b/Statement.h index a6835b03e..30f3b8229 100644 --- a/Statement.h +++ b/Statement.h @@ -1,7 +1,7 @@ #ifndef IVL_Statement_H #define IVL_Statement_H /* - * Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2017 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 @@ -402,8 +402,9 @@ class PEventStatement : public Statement { explicit PEventStatement(const svector&ee); explicit PEventStatement(PEEvent*ee); - // Make an @* statement. - explicit PEventStatement(void); + // Make an @* statement or make a special @* version with the items + // from functions added and ouputs removed for always_comb/latch. + explicit PEventStatement(bool search_funcs = false); ~PEventStatement(); @@ -429,6 +430,7 @@ class PEventStatement : public Statement { private: svectorexpr_; Statement*statement_; + bool search_funcs_; }; ostream& operator << (ostream&o, const PEventStatement&obj); diff --git a/design_dump.cc b/design_dump.cc index 590ec1e07..b5f52cfad 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -990,6 +990,18 @@ void NetProcTop::dump(ostream&o, unsigned ind) const o << "always /* " << get_fileline() << " in " << scope_path(scope_) << " */" << endl; break; + case IVL_PR_ALWAYS_COMB: + o << "always_comb /* " << get_fileline() << " in " + << scope_path(scope_) << " */" << endl; + break; + case IVL_PR_ALWAYS_FF: + o << "always_ff /* " << get_fileline() << " in " + << scope_path(scope_) << " */" << endl; + break; + case IVL_PR_ALWAYS_LATCH: + o << "always_latch /* " << get_fileline() << " in " + << scope_path(scope_) << " */" << endl; + break; case IVL_PR_FINAL: o << "final /* " << get_fileline() << " in " << scope_path(scope_) << " */" << endl; @@ -1017,6 +1029,13 @@ void NetAnalogTop::dump(ostream&o, unsigned ind) const << scope_path(scope_) << " */" << endl; break; + // These are not used in an analog context. + case IVL_PR_ALWAYS_COMB: + case IVL_PR_ALWAYS_FF: + case IVL_PR_ALWAYS_LATCH: + assert(0); + break; + case IVL_PR_FINAL: o << "analog final /* " << get_fileline() << " in " << scope_path(scope_) << " */" << endl; diff --git a/elaborate.cc b/elaborate.cc index 7db362504..0fb01c6b4 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -4200,14 +4200,15 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope, if (expr_.count() == 0) { assert(enet); - /* For synthesis we want just the inputs, but for the rest we - * want inputs and outputs that may cause a value to change. */ + /* For synthesis or always_comb/latch we want just the inputs, + * but for the rest we want inputs and outputs that may cause + * a value to change. */ extern bool synthesis; /* Synthesis flag from main.cc */ bool rem_out = false; - if (synthesis) { + if (synthesis || search_funcs_) { rem_out = true; } - NexusSet*nset = enet->nex_input(rem_out); + NexusSet*nset = enet->nex_input(rem_out, search_funcs_); if (nset == 0) { cerr << get_fileline() << ": error: Unable to elaborate:" << endl; @@ -5356,7 +5357,10 @@ bool PProcess::elaborate(Design*des, NetScope*scope) const gets into its wait statement before non-combinational code is executed. */ do { - if (top->type() != IVL_PR_ALWAYS) + if ((top->type() != IVL_PR_ALWAYS) && + (top->type() != IVL_PR_ALWAYS_COMB) && + (top->type() != IVL_PR_ALWAYS_FF) && + (top->type() != IVL_PR_ALWAYS_LATCH)) break; NetEvWait*st = dynamic_cast(top->statement()); @@ -6110,7 +6114,10 @@ bool Design::check_proc_delay() const * a runtime infinite loop will happen. If we possible have some * delay then print a warning that an infinite loop is possible. */ - if (pr->type() == IVL_PR_ALWAYS) { + if ((pr->type() == IVL_PR_ALWAYS) || + (pr->type() == IVL_PR_ALWAYS_COMB) || + (pr->type() == IVL_PR_ALWAYS_FF) || + (pr->type() == IVL_PR_ALWAYS_LATCH)) { DelayType dly_type = pr->statement()->delay_type(); if (dly_type == NO_DELAY || dly_type == ZERO_DELAY) { diff --git a/ivl_target.h b/ivl_target.h index f23c3fb58..22342affb 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -355,9 +355,12 @@ typedef enum ivl_path_edge_e { /* Processes are initial, always, or final blocks with a statement. This is the type of the ivl_process_t object. */ typedef enum ivl_process_type_e ENUM_UNSIGNED_INT { - IVL_PR_INITIAL = 0, - IVL_PR_ALWAYS = 1, - IVL_PR_FINAL = 2 + IVL_PR_INITIAL = 0, + IVL_PR_ALWAYS = 1, + IVL_PR_ALWAYS_COMB = 3, + IVL_PR_ALWAYS_FF = 4, + IVL_PR_ALWAYS_LATCH = 5, + IVL_PR_FINAL = 2 } ivl_process_type_t; /* These are the sorts of reasons a scope may come to be. These types diff --git a/net_nex_input.cc b/net_nex_input.cc index 3e37b7b95..f11ffad7e 100644 --- a/net_nex_input.cc +++ b/net_nex_input.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2017 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 @@ -27,7 +27,7 @@ # include "netlist.h" # include "netmisc.h" -NexusSet* NetExpr::nex_input(bool) +NexusSet* NetExpr::nex_input(bool, bool) const { cerr << get_fileline() << ": internal error: nex_input not implemented: " @@ -35,7 +35,7 @@ NexusSet* NetExpr::nex_input(bool) return 0; } -NexusSet* NetProc::nex_input(bool) +NexusSet* NetProc::nex_input(bool, bool) const { cerr << get_fileline() << ": internal error: NetProc::nex_input not implemented" @@ -43,13 +43,13 @@ NexusSet* NetProc::nex_input(bool) return 0; } -NexusSet* NetEArrayPattern::nex_input(bool rem_out) +NexusSet* NetEArrayPattern::nex_input(bool rem_out, bool search_funcs) const { NexusSet*result = new NexusSet; for (size_t idx = 0 ; idx < items_.size() ; idx += 1) { if (items_[idx]==0) continue; - NexusSet*tmp = items_[idx]->nex_input(rem_out); + NexusSet*tmp = items_[idx]->nex_input(rem_out, search_funcs); if (tmp == 0) continue; result->add(*tmp); @@ -58,32 +58,32 @@ NexusSet* NetEArrayPattern::nex_input(bool rem_out) return result; } -NexusSet* NetEBinary::nex_input(bool rem_out) +NexusSet* NetEBinary::nex_input(bool rem_out, bool search_funcs) const { - NexusSet*result = left_->nex_input(rem_out); - NexusSet*tmp = right_->nex_input(rem_out); + NexusSet*result = left_->nex_input(rem_out, search_funcs); + NexusSet*tmp = right_->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; return result; } -NexusSet* NetEConcat::nex_input(bool rem_out) +NexusSet* NetEConcat::nex_input(bool rem_out, bool search_funcs) const { if (parms_[0] == NULL) return NULL; - NexusSet*result = parms_[0]->nex_input(rem_out); + NexusSet*result = parms_[0]->nex_input(rem_out, search_funcs); for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) { if (parms_[idx] == NULL) { delete result; return NULL; } - NexusSet*tmp = parms_[idx]->nex_input(rem_out); + NexusSet*tmp = parms_[idx]->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; } return result; } -NexusSet* NetEAccess::nex_input(bool) +NexusSet* NetEAccess::nex_input(bool, bool) const { return new NexusSet; } @@ -91,55 +91,55 @@ NexusSet* NetEAccess::nex_input(bool) /* * A constant has not inputs, so always return an empty set. */ -NexusSet* NetEConst::nex_input(bool) +NexusSet* NetEConst::nex_input(bool, bool) const { return new NexusSet; } -NexusSet* NetECReal::nex_input(bool) +NexusSet* NetECReal::nex_input(bool, bool) const { return new NexusSet; } -NexusSet* NetEEvent::nex_input(bool) +NexusSet* NetEEvent::nex_input(bool, bool) const { return new NexusSet; } -NexusSet* NetELast::nex_input(bool) +NexusSet* NetELast::nex_input(bool, bool) const { return new NexusSet; } -NexusSet* NetENetenum::nex_input(bool) +NexusSet* NetENetenum::nex_input(bool, bool) const { return new NexusSet; } -NexusSet* NetENew::nex_input(bool) +NexusSet* NetENew::nex_input(bool, bool) const { return new NexusSet; } -NexusSet* NetENull::nex_input(bool) +NexusSet* NetENull::nex_input(bool, bool) const { return new NexusSet; } -NexusSet* NetEProperty::nex_input(bool) +NexusSet* NetEProperty::nex_input(bool, bool) const { return new NexusSet; } -NexusSet* NetEScope::nex_input(bool) +NexusSet* NetEScope::nex_input(bool, bool) const { return new NexusSet; } -NexusSet* NetESelect::nex_input(bool rem_out) +NexusSet* NetESelect::nex_input(bool rem_out, bool search_funcs) const { - NexusSet*result = base_? base_->nex_input(rem_out) : new NexusSet(); - NexusSet*tmp = expr_->nex_input(rem_out); + NexusSet*result = base_? base_->nex_input(rem_out, search_funcs) : new NexusSet(); + NexusSet*tmp = expr_->nex_input(rem_out, search_funcs); if (tmp == NULL) { delete result; return NULL; @@ -157,17 +157,17 @@ NexusSet* NetESelect::nex_input(bool rem_out) /* * The $fread, etc. system functions can have NULL arguments. */ -NexusSet* NetESFunc::nex_input(bool rem_out) +NexusSet* NetESFunc::nex_input(bool rem_out, bool search_funcs) const { if (parms_.empty()) return new NexusSet; NexusSet*result; - if (parms_[0]) result = parms_[0]->nex_input(rem_out); + if (parms_[0]) result = parms_[0]->nex_input(rem_out, search_funcs); else result = new NexusSet; for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) { if (parms_[idx]) { - NexusSet*tmp = parms_[idx]->nex_input(rem_out); + NexusSet*tmp = parms_[idx]->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; } @@ -175,12 +175,12 @@ NexusSet* NetESFunc::nex_input(bool rem_out) return result; } -NexusSet* NetEShallowCopy::nex_input(bool) +NexusSet* NetEShallowCopy::nex_input(bool, bool) const { return new NexusSet; } -NexusSet* NetESignal::nex_input(bool rem_out) +NexusSet* NetESignal::nex_input(bool rem_out, bool search_funcs) const { /* * This is not what I would expect for the various selects (bit, @@ -194,7 +194,7 @@ NexusSet* NetESignal::nex_input(bool rem_out) /* If we have an array index add it to the sensitivity list. */ if (word_) { NexusSet*tmp; - tmp = word_->nex_input(rem_out); + tmp = word_->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; if (warn_sens_entire_arr) { @@ -209,27 +209,44 @@ NexusSet* NetESignal::nex_input(bool rem_out) return result; } -NexusSet* NetETernary::nex_input(bool rem_out) +NexusSet* NetETernary::nex_input(bool rem_out, bool search_funcs) const { NexusSet*tmp; - NexusSet*result = cond_->nex_input(rem_out); + NexusSet*result = cond_->nex_input(rem_out, search_funcs); - tmp = true_val_->nex_input(rem_out); + tmp = true_val_->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; - tmp = false_val_->nex_input(rem_out); + tmp = false_val_->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; return result; } -NexusSet* NetEUFunc::nex_input(bool rem_out) +NexusSet* NetEUFunc::nex_input(bool rem_out, bool search_funcs) const { NexusSet*result = new NexusSet; for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) { - NexusSet*tmp = parms_[idx]->nex_input(rem_out); + NexusSet*tmp = parms_[idx]->nex_input(rem_out, search_funcs); + result->add(*tmp); + delete tmp; + } + + if (search_funcs) { + NetFuncDef*func = func_->func_def(); + NexusSet*tmp = func->proc()->nex_input(rem_out, search_funcs); + // Remove the function inputs + NexusSet*in = new NexusSet; + for (unsigned idx = 0 ; idx < func->port_count() ; idx += 1) { + NetNet*net = func->port(idx); + assert(net->pin_count() == 1); + in->add(net->pin(0).nexus(), 0, net->vector_width()); + } + tmp->rem(*in); + delete in; + result->add(*tmp); delete tmp; } @@ -237,21 +254,21 @@ NexusSet* NetEUFunc::nex_input(bool rem_out) return result; } -NexusSet* NetEUnary::nex_input(bool rem_out) +NexusSet* NetEUnary::nex_input(bool rem_out, bool search_funcs) const { - return expr_->nex_input(rem_out); + return expr_->nex_input(rem_out, search_funcs); } -NexusSet* NetAssign_::nex_input(bool rem_out) +NexusSet* NetAssign_::nex_input(bool rem_out, bool search_funcs) const { NexusSet*result = new NexusSet; if (word_) { - NexusSet*tmp = word_->nex_input(rem_out); + NexusSet*tmp = word_->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; } if (base_) { - NexusSet*tmp = base_->nex_input(rem_out); + NexusSet*tmp = base_->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; } @@ -259,15 +276,15 @@ NexusSet* NetAssign_::nex_input(bool rem_out) return result; } -NexusSet* NetAssignBase::nex_input(bool rem_out) +NexusSet* NetAssignBase::nex_input(bool rem_out, bool search_funcs) const { - NexusSet*result = rval_->nex_input(rem_out); + NexusSet*result = rval_->nex_input(rem_out, search_funcs); /* It is possible that the lval_ can have nex_input values. In particular, index expressions are statement inputs as well, so should be addressed here. */ for (NetAssign_*cur = lval_ ; cur ; cur = cur->more) { - NexusSet*tmp = cur->nex_input(rem_out); + NexusSet*tmp = cur->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; } @@ -292,7 +309,7 @@ NexusSet* NetAssignBase::nex_input(bool rem_out) * In this example, "t" should not be in the input set because it is * used by the sequence as a temporary value. */ -NexusSet* NetBlock::nex_input(bool rem_out) +NexusSet* NetBlock::nex_input(bool rem_out, bool search_funcs) const { if (last_ == 0) return new NexusSet; @@ -312,7 +329,7 @@ NexusSet* NetBlock::nex_input(bool rem_out) do { /* Get the inputs for the current statement. */ - NexusSet*tmp = cur->nex_input(rem_out); + NexusSet*tmp = cur->nex_input(rem_out, search_funcs); /* Add the current input set to the accumulated input set. */ if (tmp != 0) result->add(*tmp); @@ -339,9 +356,9 @@ NexusSet* NetBlock::nex_input(bool rem_out) * the inputs to all the guards, and the inputs to all the guarded * statements. */ -NexusSet* NetCase::nex_input(bool rem_out) +NexusSet* NetCase::nex_input(bool rem_out, bool search_funcs) const { - NexusSet*result = expr_->nex_input(rem_out); + NexusSet*result = expr_->nex_input(rem_out, search_funcs); if (result == 0) return 0; @@ -351,7 +368,7 @@ NexusSet* NetCase::nex_input(bool rem_out) if (items_[idx].statement == 0) continue; - NexusSet*tmp = items_[idx].statement->nex_input(rem_out); + NexusSet*tmp = items_[idx].statement->nex_input(rem_out, search_funcs); assert(tmp); result->add(*tmp); delete tmp; @@ -360,7 +377,7 @@ NexusSet* NetCase::nex_input(bool rem_out) case is special and is identified by a null guard. The default guard obviously has no input. */ if (items_[idx].guard) { - tmp = items_[idx].guard->nex_input(rem_out); + tmp = items_[idx].guard->nex_input(rem_out, search_funcs); assert(tmp); result->add(*tmp); delete tmp; @@ -370,24 +387,24 @@ NexusSet* NetCase::nex_input(bool rem_out) return result; } -NexusSet* NetCAssign::nex_input(bool) +NexusSet* NetCAssign::nex_input(bool, bool) const { cerr << get_fileline() << ": internal warning: NetCAssign::nex_input()" << " not implemented." << endl; return new NexusSet; } -NexusSet* NetCondit::nex_input(bool rem_out) +NexusSet* NetCondit::nex_input(bool rem_out, bool search_funcs) const { - NexusSet*result = expr_->nex_input(rem_out); + NexusSet*result = expr_->nex_input(rem_out, search_funcs); if (if_ != 0) { - NexusSet*tmp = if_->nex_input(rem_out); + NexusSet*tmp = if_->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; } if (else_ != 0) { - NexusSet*tmp = else_->nex_input(rem_out); + NexusSet*tmp = else_->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; } @@ -395,46 +412,46 @@ NexusSet* NetCondit::nex_input(bool rem_out) return result; } -NexusSet* NetDoWhile::nex_input(bool rem_out) +NexusSet* NetDoWhile::nex_input(bool rem_out, bool search_funcs) const { - NexusSet*result = proc_->nex_input(rem_out); - NexusSet*tmp = cond_->nex_input(rem_out); + NexusSet*result = proc_->nex_input(rem_out, search_funcs); + NexusSet*tmp = cond_->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; return result; } -NexusSet* NetEvWait::nex_input(bool rem_out) +NexusSet* NetEvWait::nex_input(bool rem_out, bool search_funcs) const { NexusSet*result; if (statement_) - result = statement_->nex_input(rem_out); + result = statement_->nex_input(rem_out, search_funcs); else result = new NexusSet; return result; } -NexusSet* NetForce::nex_input(bool) +NexusSet* NetForce::nex_input(bool, bool) const { cerr << get_fileline() << ": internal warning: NetForce::nex_input()" << " not implemented." << endl; return new NexusSet; } -NexusSet* NetForLoop::nex_input(bool rem_out) +NexusSet* NetForLoop::nex_input(bool rem_out, bool search_funcs) const { - NexusSet*result = init_expr_->nex_input(rem_out); + NexusSet*result = init_expr_->nex_input(rem_out, search_funcs); - NexusSet*tmp = condition_->nex_input(rem_out); + NexusSet*tmp = condition_->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; - tmp = statement_->nex_input(rem_out); + tmp = statement_->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; - tmp = step_statement_->nex_input(rem_out); + tmp = step_statement_->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; @@ -450,9 +467,9 @@ NexusSet* NetForLoop::nex_input(bool rem_out) return result; } -NexusSet* NetForever::nex_input(bool rem_out) +NexusSet* NetForever::nex_input(bool rem_out, bool search_funcs) const { - NexusSet*result = statement_->nex_input(rem_out); + NexusSet*result = statement_->nex_input(rem_out, search_funcs); return result; } @@ -465,17 +482,17 @@ NexusSet* NetForever::nex_input(bool rem_out) * include the input set of the because it does not affect the * result. The statement can be omitted. */ -NexusSet* NetPDelay::nex_input(bool rem_out) +NexusSet* NetPDelay::nex_input(bool rem_out, bool search_funcs) const { if (statement_ == 0) return 0; - NexusSet*result = statement_->nex_input(rem_out); + NexusSet*result = statement_->nex_input(rem_out, search_funcs); return result; } -NexusSet* NetRepeat::nex_input(bool rem_out) +NexusSet* NetRepeat::nex_input(bool rem_out, bool search_funcs) const { - NexusSet*result = statement_->nex_input(rem_out); - NexusSet*tmp = expr_->nex_input(rem_out); + NexusSet*result = statement_->nex_input(rem_out, search_funcs); + NexusSet*tmp = expr_->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; return result; @@ -484,17 +501,17 @@ NexusSet* NetRepeat::nex_input(bool rem_out) /* * The $display, etc. system tasks can have NULL arguments. */ -NexusSet* NetSTask::nex_input(bool rem_out) +NexusSet* NetSTask::nex_input(bool rem_out, bool search_funcs) const { if (parms_.empty()) return new NexusSet; NexusSet*result; - if (parms_[0]) result = parms_[0]->nex_input(rem_out); + if (parms_[0]) result = parms_[0]->nex_input(rem_out, search_funcs); else result = new NexusSet; for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) { if (parms_[idx]) { - NexusSet*tmp = parms_[idx]->nex_input(rem_out); + NexusSet*tmp = parms_[idx]->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; } @@ -508,15 +525,15 @@ NexusSet* NetSTask::nex_input(bool rem_out) * parameters to consider, because the compiler already removed them * and converted them to blocking assignments. */ -NexusSet* NetUTask::nex_input(bool) +NexusSet* NetUTask::nex_input(bool, bool) const { return new NexusSet; } -NexusSet* NetWhile::nex_input(bool rem_out) +NexusSet* NetWhile::nex_input(bool rem_out, bool search_funcs) const { - NexusSet*result = proc_->nex_input(rem_out); - NexusSet*tmp = cond_->nex_input(rem_out); + NexusSet*result = proc_->nex_input(rem_out, search_funcs); + NexusSet*tmp = cond_->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; return result; diff --git a/netlist.h b/netlist.h index 4ba553407..18abc161b 100644 --- a/netlist.h +++ b/netlist.h @@ -2045,7 +2045,7 @@ class NetExpr : public LineInfo { // Get the Nexus that are the input to this // expression. Normally this descends down to the reference to // a signal that reads from its input. - virtual NexusSet* nex_input(bool rem_out = true) =0; + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const =0; // Return a version of myself that is structural. This is used // for converting expressions to gates. The arguments are: @@ -2088,7 +2088,7 @@ class NetEArrayPattern : public NetExpr { void dump(ostream&) const; NetEArrayPattern* dup_expr() const; - NexusSet* nex_input(bool rem_out =true); + NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; private: std::vector items_; @@ -2121,7 +2121,7 @@ class NetEConst : public NetExpr { virtual NetEConst* dup_expr() const; virtual NetNet*synthesize(Design*, NetScope*scope, NetExpr*); - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual NetExpr*evaluate_function(const LineInfo&loc, map&ctx) const; @@ -2193,7 +2193,7 @@ class NetECReal : public NetExpr { virtual NetECReal* dup_expr() const; virtual NetNet*synthesize(Design*, NetScope*scope, NetExpr*); - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual NetExpr*evaluate_function(const LineInfo&loc, map&ctx) const; @@ -2637,7 +2637,7 @@ class NetProc : public virtual LineInfo { // Find the nexa that are input by the statement. This is used // for example by @* to find the inputs to the process for the // sensitivity list. - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; // Find the nexa that are set by the statement. Add the output // values to the set passed as a parameter. @@ -2850,7 +2850,7 @@ class NetAssign_ { // being outputs. For example foo[idx] = ... is the l-value // (NetAssign_ object) with a foo l-value and the input // expression idx. - NexusSet* nex_input(bool rem_out = true); + NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; // Figuring out nex_output to process ultimately comes down to // this method. @@ -2898,7 +2898,7 @@ class NetAssignBase : public NetProc { void set_delay(NetExpr*); const NetExpr* get_delay() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void nex_output(NexusSet&o); @@ -3013,7 +3013,7 @@ class NetBlock : public NetProc { // for sequential blocks. void emit_recurse(struct target_t*) const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual int match_proc(struct proc_match_t*); @@ -3056,7 +3056,7 @@ class NetCase : public NetProc { inline const NetExpr*expr(unsigned idx) const { return items_[idx].guard;} inline const NetProc*stat(unsigned idx) const { return items_[idx].statement; } - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void nex_output(NexusSet&out); bool synth_async(Design*des, NetScope*scope, @@ -3102,7 +3102,7 @@ class NetCAssign : public NetAssignBase { explicit NetCAssign(NetAssign_*lv, NetExpr*rv); ~NetCAssign(); - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void dump(ostream&, unsigned ind) const; virtual bool emit_proc(struct target_t*) const; @@ -3135,7 +3135,7 @@ class NetCondit : public NetProc { bool emit_recurse_if(struct target_t*) const; bool emit_recurse_else(struct target_t*) const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void nex_output(NexusSet&o); bool is_asynchronous(); @@ -3252,7 +3252,7 @@ class NetDoWhile : public NetProc { void emit_proc_recurse(struct target_t*) const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -3417,7 +3417,7 @@ class NetEvWait : public NetProc { // process? This method checks. virtual bool is_synchronous(); - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void nex_output(NexusSet&out); virtual bool synth_async(Design*des, NetScope*scope, @@ -3484,7 +3484,7 @@ class NetForce : public NetAssignBase { explicit NetForce(NetAssign_*l, NetExpr*r); ~NetForce(); - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void dump(ostream&, unsigned ind) const; virtual bool emit_proc(struct target_t*) const; @@ -3502,7 +3502,7 @@ class NetForever : public NetProc { void emit_recurse(struct target_t*) const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; virtual DelayType delay_type() const; @@ -3524,7 +3524,7 @@ class NetForLoop : public NetProc { void emit_recurse(struct target_t*) const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -3624,7 +3624,7 @@ class NetPDelay : public NetProc { uint64_t delay() const; const NetExpr*expr() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; @@ -3651,7 +3651,7 @@ class NetRepeat : public NetProc { const NetExpr*expr() const; void emit_recurse(struct target_t*) const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; virtual DelayType delay_type() const; @@ -3702,7 +3702,7 @@ class NetSTask : public NetProc { const NetExpr* parm(unsigned idx) const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -3761,7 +3761,7 @@ class NetELast : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetELast*dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; private: NetNet*sig_; @@ -3790,7 +3790,7 @@ class NetEUFunc : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetEUFunc*dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual NetExpr* eval_tree(); virtual NetExpr*evaluate_function(const LineInfo&loc, map&ctx) const; @@ -3826,7 +3826,7 @@ class NetEAccess : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetEAccess*dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; private: NetBranch*branch_; @@ -3848,7 +3848,7 @@ class NetUTask : public NetProc { const NetScope* task() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -3873,7 +3873,7 @@ class NetWhile : public NetProc { void emit_proc_recurse(struct target_t*) const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -4016,7 +4016,7 @@ class NetEBinary : public NetExpr { virtual NetExpr* eval_tree(); virtual NetExpr* evaluate_function(const LineInfo&loc, map&ctx) const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; @@ -4270,7 +4270,7 @@ class NetEConcat : public NetExpr { NetExpr* parm(unsigned idx) const { return parms_[idx]; } virtual ivl_variable_type_t expr_type() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual bool has_width() const; virtual NetEConcat* dup_expr() const; virtual NetEConst* eval_tree(); @@ -4318,7 +4318,7 @@ class NetESelect : public NetExpr { // sub-expression. virtual ivl_variable_type_t expr_type() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual bool has_width() const; virtual void expr_scan(struct expr_scan_t*) const; virtual NetEConst* eval_tree(); @@ -4347,7 +4347,7 @@ class NetEEvent : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetEEvent* dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void dump(ostream&os) const; @@ -4370,7 +4370,7 @@ class NetENetenum : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetENetenum* dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void dump(ostream&os) const; @@ -4394,7 +4394,7 @@ class NetENew : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetENew* dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void dump(ostream&os) const; @@ -4416,7 +4416,7 @@ class NetENull : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetENull* dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void dump(ostream&os) const; }; @@ -4442,7 +4442,7 @@ class NetEProperty : public NetExpr { ivl_variable_type_t expr_type() const; virtual void expr_scan(struct expr_scan_t*) const; virtual NetEProperty* dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void dump(ostream&os) const; @@ -4467,7 +4467,7 @@ class NetEScope : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetEScope* dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void dump(ostream&os) const; @@ -4501,7 +4501,7 @@ class NetESFunc : public NetExpr { map&ctx) const; virtual ivl_variable_type_t expr_type() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual const netenum_t* enumeration() const; virtual void dump(ostream&) const; @@ -4636,7 +4636,7 @@ class NetEShallowCopy : public NetExpr { virtual void expr_scan(struct expr_scan_t*) const; virtual NetEShallowCopy* dup_expr() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void dump(ostream&os) const; @@ -4668,7 +4668,7 @@ class NetETernary : public NetExpr { virtual NetExpr*evaluate_function(const LineInfo&loc, map&ctx) const; virtual ivl_variable_type_t expr_type() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; virtual NetNet*synthesize(Design*, NetScope*scope, NetExpr*root); @@ -4723,7 +4723,7 @@ class NetEUnary : public NetExpr { virtual NetNet* synthesize(Design*, NetScope*scope, NetExpr*root); virtual ivl_variable_type_t expr_type() const; - virtual NexusSet* nex_input(bool rem_out = true); + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void expr_scan(struct expr_scan_t*) const; virtual void dump(ostream&) const; @@ -4799,7 +4799,7 @@ class NetESignal : public NetExpr { virtual NetESignal* dup_expr() const; NetNet* synthesize(Design*des, NetScope*scope, NetExpr*root); - NexusSet* nex_input(bool rem_out = true); + NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; const netenum_t*enumeration() const; virtual NetExpr*evaluate_function(const LineInfo&loc, diff --git a/parse.y b/parse.y index 206b6fbb9..48dbe2d9a 100644 --- a/parse.y +++ b/parse.y @@ -4852,6 +4852,18 @@ module_item { PProcess*tmp = pform_make_behavior(IVL_PR_ALWAYS, $3, $1); FILE_NAME(tmp, @2); } + | attribute_list_opt K_always_comb statement_item + { PProcess*tmp = pform_make_behavior(IVL_PR_ALWAYS_COMB, $3, $1); + FILE_NAME(tmp, @2); + } + | attribute_list_opt K_always_ff statement_item + { PProcess*tmp = pform_make_behavior(IVL_PR_ALWAYS_FF, $3, $1); + FILE_NAME(tmp, @2); + } + | attribute_list_opt K_always_latch statement_item + { PProcess*tmp = pform_make_behavior(IVL_PR_ALWAYS_LATCH, $3, $1); + FILE_NAME(tmp, @2); + } | attribute_list_opt K_initial statement_item { PProcess*tmp = pform_make_behavior(IVL_PR_INITIAL, $3, $1); FILE_NAME(tmp, @2); @@ -6401,7 +6413,7 @@ statement_item /* This is roughly statement_item in the LRM */ $$ = tmp; } | K_wait K_fork ';' - { PEventStatement*tmp = new PEventStatement(0); + { PEventStatement*tmp = new PEventStatement((PEEvent*)0); FILE_NAME(tmp,@1); $$ = tmp; } diff --git a/pform.cc b/pform.cc index c1a08a29a..189528985 100644 --- a/pform.cc +++ b/pform.cc @@ -3557,6 +3557,16 @@ vector* pform_make_udp_input_ports(list*names) PProcess* pform_make_behavior(ivl_process_type_t type, Statement*st, list*attr) { + // Add an implicit @* around the statement for the always_comb and + // always_latch statements. + if ((type == IVL_PR_ALWAYS_COMB) || (type == IVL_PR_ALWAYS_LATCH)) { + PEventStatement *tmp = new PEventStatement(true); + tmp->set_file(st->get_file()); + tmp->set_lineno(st->get_lineno()); + tmp->set_statement(st); + st = tmp; + } + PProcess*pp = new PProcess(type, st); // If we are in a part of the code where the meta-comment @@ -3576,8 +3586,10 @@ PProcess* pform_make_behavior(ivl_process_type_t type, Statement*st, pform_put_behavior_in_scope(pp); ivl_assert(*st, ! pform_cur_module.empty()); - if (pform_cur_module.front()->program_block && type == IVL_PR_ALWAYS) { - cerr << st->get_fileline() << ": error: Always statements not allowed" + if (pform_cur_module.front()->program_block && + ((type == IVL_PR_ALWAYS) || (type == IVL_PR_ALWAYS_COMB) || + (type == IVL_PR_ALWAYS_FF) || (type == IVL_PR_ALWAYS_LATCH))) { + cerr << st->get_fileline() << ": error: Always statements are not allowed" << " in program blocks." << endl; error_count += 1; } diff --git a/pform_dump.cc b/pform_dump.cc index 7d57b1704..b04f348a6 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -121,6 +121,15 @@ std::ostream& operator << (std::ostream&out, ivl_process_type_t pt) case IVL_PR_ALWAYS: out << "always"; break; + case IVL_PR_ALWAYS_COMB: + out << "always_comb"; + break; + case IVL_PR_ALWAYS_FF: + out << "always_ff"; + break; + case IVL_PR_ALWAYS_LATCH: + out << "always_latch"; + break; case IVL_PR_FINAL: out << "final"; break; @@ -1176,6 +1185,11 @@ void AProcess::dump(ostream&out, unsigned ind) const case IVL_PR_ALWAYS: out << setw(ind) << "" << "analog"; break; + case IVL_PR_ALWAYS_COMB: + case IVL_PR_ALWAYS_FF: + case IVL_PR_ALWAYS_LATCH: + assert(0); + break; case IVL_PR_FINAL: out << setw(ind) << "" << "analog final"; break; diff --git a/synth.cc b/synth.cc index 3e4c85a1d..cd7516d3d 100644 --- a/synth.cc +++ b/synth.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2012 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2017 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 @@ -134,6 +134,9 @@ void synth_f::process(Design*des, NetProcTop*top) top_ = top; switch (top->type()) { case IVL_PR_ALWAYS: + case IVL_PR_ALWAYS_COMB: + case IVL_PR_ALWAYS_FF: + case IVL_PR_ALWAYS_LATCH: proc_always_(des); break; case IVL_PR_INITIAL: diff --git a/t-dll.h b/t-dll.h index b85bb2d43..31b2106a1 100644 --- a/t-dll.h +++ b/t-dll.h @@ -1,7 +1,7 @@ #ifndef IVL_t_dll_H #define IVL_t_dll_H /* - * Copyright (c) 2000-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2017 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 @@ -645,7 +645,7 @@ struct ivl_parameter_s { * that generally only matters for VPI calls. */ struct ivl_process_s { - ivl_process_type_t type_ : 2; + ivl_process_type_t type_ : 3; unsigned int analog_flag : 1; ivl_scope_t scope_; ivl_statement_t stmt_; diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index 15767349a..800c87f82 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -1166,6 +1166,24 @@ static int show_process(ivl_process_t net, void*x) else fprintf(out, "always\n"); break; + case IVL_PR_ALWAYS_COMB: + if (ivl_process_analog(net)) + assert(0); + else + fprintf(out, "always_comb\n"); + break; + case IVL_PR_ALWAYS_FF: + if (ivl_process_analog(net)) + assert(0); + else + fprintf(out, "always_ff\n"); + break; + case IVL_PR_ALWAYS_LATCH: + if (ivl_process_analog(net)) + assert(0); + else + fprintf(out, "always_latch\n"); + break; case IVL_PR_FINAL: if (ivl_process_analog(net)) fprintf(out, "analog final\n"); diff --git a/tgt-verilog/verilog.c b/tgt-verilog/verilog.c index 333277a59..62616dba0 100644 --- a/tgt-verilog/verilog.c +++ b/tgt-verilog/verilog.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2017 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 @@ -393,6 +393,9 @@ static int show_process(ivl_process_t net, void*x) fprintf(out, " initial\n"); break; case IVL_PR_ALWAYS: + case IVL_PR_ALWAYS_COMB: + case IVL_PR_ALWAYS_FF: + case IVL_PR_ALWAYS_LATCH: fprintf(out, " always\n"); break; case IVL_PR_FINAL: diff --git a/tgt-vlog95/stmt.c b/tgt-vlog95/stmt.c index 4fc67135f..8d2a98d5b 100644 --- a/tgt-vlog95/stmt.c +++ b/tgt-vlog95/stmt.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2014 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2011-2017 Cary R. (cygcary@yahoo.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1606,6 +1606,9 @@ void emit_process(ivl_scope_t scope, ivl_process_t proc) fprintf(vlog_out, "initial"); break; case IVL_PR_ALWAYS: + case IVL_PR_ALWAYS_COMB: + case IVL_PR_ALWAYS_FF: + case IVL_PR_ALWAYS_LATCH: fprintf(vlog_out, "always"); break; case IVL_PR_FINAL: diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 4b41a4bdf..502c2a336 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -2358,6 +2358,9 @@ int draw_process(ivl_process_t net, void*x) break; case IVL_PR_ALWAYS: + case IVL_PR_ALWAYS_COMB: + case IVL_PR_ALWAYS_FF: + case IVL_PR_ALWAYS_LATCH: fprintf(vvp_out, " %%jmp T_%u;\n", thread_count); break; } @@ -2368,6 +2371,9 @@ int draw_process(ivl_process_t net, void*x) case IVL_PR_INITIAL: case IVL_PR_ALWAYS: + case IVL_PR_ALWAYS_COMB: + case IVL_PR_ALWAYS_FF: + case IVL_PR_ALWAYS_LATCH: if (init_flag) { fprintf(vvp_out, " .thread T_%u, $init;\n", thread_count); } else if (push_flag) { From 84d0df8a8acbcee5cd6efddf56d8700e8bfe9fbe Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 24 Nov 2017 12:35:02 -0800 Subject: [PATCH 532/595] Pass to the targets if an implicit T0 trigger event is needed. --- elaborate.cc | 5 ++++- ivl.def | 1 + ivl_target.h | 2 ++ netlist.h | 3 +++ t-dll-api.cc | 10 ++++++++++ t-dll-proc.cc | 5 ++++- t-dll.h | 1 + 7 files changed, 25 insertions(+), 2 deletions(-) diff --git a/elaborate.cc b/elaborate.cc index 0fb01c6b4..15f3d9602 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -4208,6 +4208,9 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope, if (synthesis || search_funcs_) { rem_out = true; } + // If this is an always_comp/latch then we need an implicit T0 + // trigger of the event expression. + if (search_funcs_) wa->set_t0_trigger(); NexusSet*nset = enet->nex_input(rem_out, search_funcs_); if (nset == 0) { cerr << get_fileline() << ": error: Unable to elaborate:" @@ -6111,7 +6114,7 @@ bool Design::check_proc_delay() const for (const NetProcTop*pr = procs_ ; pr ; pr = pr->next_) { /* If this is an always block and we have no or zero delay then - * a runtime infinite loop will happen. If we possible have some + * a runtime infinite loop will happen. If we possibly have some * delay then print a warning that an infinite loop is possible. */ if ((pr->type() == IVL_PR_ALWAYS) || diff --git a/ivl.def b/ivl.def index 5fee414ef..39682eaf5 100644 --- a/ivl.def +++ b/ivl.def @@ -294,6 +294,7 @@ ivl_stmt_lval ivl_stmt_lvals ivl_stmt_lwidth ivl_stmt_name +ivl_stmt_needs_t0_trigger ivl_stmt_nevent ivl_stmt_opcode ivl_stmt_parm diff --git a/ivl_target.h b/ivl_target.h index 22342affb..f3fed5669 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -2105,6 +2105,7 @@ extern unsigned ivl_stmt_lineno(ivl_statement_t net); * handle disable statements. * * ivl_stmt_events + * ivl_stmt_needs_t0_trigger * ivl_stmt_nevent * Statements that have event arguments (TRIGGER and WAIT) make * those event objects available through these methods. @@ -2232,6 +2233,7 @@ extern ivl_expr_t ivl_stmt_delay_expr(ivl_statement_t net); /* IVL_ST_DELAY */ extern uint64_t ivl_stmt_delay_val(ivl_statement_t net); /* IVL_ST_WAIT IVL_ST_TRIGGER */ +extern unsigned ivl_stmt_needs_t0_trigger(ivl_statement_t net); extern unsigned ivl_stmt_nevent(ivl_statement_t net); extern ivl_event_t ivl_stmt_events(ivl_statement_t net, unsigned idx); /* IVL_ST_CONTRIB */ diff --git a/netlist.h b/netlist.h index 18abc161b..ad8a78f9f 100644 --- a/netlist.h +++ b/netlist.h @@ -3398,10 +3398,12 @@ class NetEvWait : public NetProc { void add_event(NetEvent*tgt); void replace_event(NetEvent*orig, NetEvent*repl); + inline void set_t0_trigger() { has_t0_trigger_ = true; }; inline unsigned nevents() const { return events_.size(); } inline const NetEvent*event(unsigned idx) const { return events_[idx]; } inline NetEvent*event(unsigned idx) { return events_[idx]; } + inline bool has_t0_trigger() const { return has_t0_trigger_; }; NetProc*statement(); @@ -3442,6 +3444,7 @@ class NetEvWait : public NetProc { NetProc*statement_; // Events that I might wait for. std::vectorevents_; + bool has_t0_trigger_; }; ostream& operator << (ostream&out, const NetEvWait&obj); diff --git a/t-dll-api.cc b/t-dll-api.cc index 9c8283ab3..a32950437 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -2815,6 +2815,16 @@ extern "C" uint64_t ivl_stmt_delay_val(ivl_statement_t net) return net->u_.delay_.value; } +extern "C" unsigned ivl_stmt_needs_t0_trigger(ivl_statement_t net) +{ + assert(net); + if (net->type_ == IVL_ST_WAIT) { + return net->u_.wait_.needs_t0_trigger; + } else { + return 0; + } +} + extern "C" unsigned ivl_stmt_nevent(ivl_statement_t net) { assert(net); diff --git a/t-dll-proc.cc b/t-dll-proc.cc index e668919eb..ba0d4b1a0 100644 --- a/t-dll-proc.cc +++ b/t-dll-proc.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2017 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 @@ -847,12 +847,15 @@ bool dll_target::proc_wait(const NetEvWait*net) /* This is a wait fork statement. */ if ((net->nevents() == 1) && (net->event(0) == 0)) { + stmt_cur_->u_.wait_.needs_t0_trigger = 0; stmt_cur_->u_.wait_.event = 0; stmt_cur_->type_ = IVL_ST_WAIT; stmt_cur_->u_.wait_.stmt_->type_ = IVL_ST_NOOP; return true; } + stmt_cur_->u_.wait_.needs_t0_trigger = net->has_t0_trigger(); + // This event processing code is also in the NB assign above. if (net->nevents() > 1) { stmt_cur_->u_.wait_.events = (ivl_event_t*) diff --git a/t-dll.h b/t-dll.h index 31b2106a1..879a5c966 100644 --- a/t-dll.h +++ b/t-dll.h @@ -862,6 +862,7 @@ struct ivl_statement_s { } utask_; struct { /* IVL_ST_TRIGGER IVL_ST_WAIT */ + unsigned needs_t0_trigger; unsigned nevent; union { ivl_event_t event; From 575aa9b0fb9b658cc8878c54f987ecca5ee3b5fe Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 24 Nov 2017 12:37:43 -0800 Subject: [PATCH 533/595] Fix spelling in always_comb --- elaborate.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elaborate.cc b/elaborate.cc index 15f3d9602..85a2ceb4c 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -4208,7 +4208,7 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope, if (synthesis || search_funcs_) { rem_out = true; } - // If this is an always_comp/latch then we need an implicit T0 + // If this is an always_comb/latch then we need an implicit T0 // trigger of the event expression. if (search_funcs_) wa->set_t0_trigger(); NexusSet*nset = enet->nex_input(rem_out, search_funcs_); From e611e8acc08e147b4cb6bba7c2fb79873596c20e Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 24 Nov 2017 12:40:14 -0800 Subject: [PATCH 534/595] Add support to convert always_comb/latch to vlog95 --- tgt-vlog95/event.c | 28 +++++++++++++++++++++++++++- tgt-vlog95/vlog95.c | 9 ++++++--- tgt-vlog95/vlog95_priv.h | 6 ++++-- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/tgt-vlog95/event.c b/tgt-vlog95/event.c index f4b3d370d..0a1c0b881 100644 --- a/tgt-vlog95/event.c +++ b/tgt-vlog95/event.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2013 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2011-2017 Cary R. (cygcary@yahoo.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -21,6 +21,24 @@ # include "config.h" # include "vlog95_priv.h" +static unsigned need_ivl_top_module = 0; + +void emit_icarus_generated_top_module() +{ + if (need_ivl_top_module) { + fprintf(vlog_out, +"\n" +"/*\n" +" * This module is used to trigger any always_comb or always_latch processes\n" +" * at time zero to make sure all the outputs have the correct values.\n" +"*/\n" +"module IVL_top_priv_module;\n" +" event IVL_T0_trigger_event;\n" +" initial #0 -> IVL_T0_trigger_event;\n" +"endmodule /* IVL_top_priv_module */\n"); + } +} + void emit_event(ivl_scope_t scope, ivl_statement_t stmt) { unsigned eidx, nevents, first = 1; @@ -68,4 +86,12 @@ void emit_event(ivl_scope_t scope, ivl_statement_t stmt) emit_id(ivl_event_basename(event)); } } + + /* If this is an always_comb/latch then we need to add a trigger to + * get the correct functionality. */ + if (ivl_stmt_needs_t0_trigger(stmt)) { + assert(first == 0); + fprintf(vlog_out, " or IVL_top_priv_module.IVL_T0_trigger_event"); + need_ivl_top_module = 1; + }; } diff --git a/tgt-vlog95/vlog95.c b/tgt-vlog95/vlog95.c index 1890d76b6..8fe45fb10 100644 --- a/tgt-vlog95/vlog95.c +++ b/tgt-vlog95/vlog95.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2016 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2010-2017 Cary R. (cygcary@yahoo.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,7 +30,7 @@ static const char*version_string = "Icarus Verilog VLOG95 Code Generator " VERSION " (" VERSION_TAG ")\n\n" -"Copyright (C) 2010-2015 Cary R. (cygcary@yahoo.com)\n\n" +"Copyright (C) 2010-2017 Cary R. (cygcary@yahoo.com)\n\n" " This program is free software; you can redistribute it and/or modify\n" " it under the terms of the GNU General Public License as published by\n" " the Free Software Foundation; either version 2 of the License, or\n" @@ -219,9 +219,12 @@ int target_design(ivl_design_t des) /* Emit any UDP definitions that the design used. */ emit_udp_list(); - /* Emit any UDPs that are Icarus generated (D-FF). */ + /* Emit any UDPs that are Icarus generated (D-FF or latch). */ emit_icarus_generated_udps(); + /* Emit the Icarus top module used to trigger translated always_comb/latch processes at T0. */ + emit_icarus_generated_top_module(); + /* If there were errors then add this information to the output. */ if (vlog_errors) { fprintf(vlog_out, "\n"); diff --git a/tgt-vlog95/vlog95_priv.h b/tgt-vlog95/vlog95_priv.h index 913fd0424..36e3cf543 100644 --- a/tgt-vlog95/vlog95_priv.h +++ b/tgt-vlog95/vlog95_priv.h @@ -1,7 +1,7 @@ #ifndef IVL_vlog95_priv_H #define IVL_vlog95_priv_H /* - * Copyright (C) 2010-2016 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2010-2017 Cary R. (cygcary@yahoo.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -106,7 +106,6 @@ extern void emit_nexus_as_ca(ivl_scope_t scope, ivl_nexus_t nex, extern void emit_nexus_port_driver_as_ca(ivl_scope_t scope, ivl_nexus_t nex); extern void emit_const_nexus(ivl_scope_t scope, ivl_net_const_t const_net); extern void emit_signal_net_const_as_ca(ivl_scope_t scope, ivl_signal_t sig); -extern void emit_icarus_generated_udps(void); extern void add_udp_to_list(ivl_udp_t udp); extern void emit_udp_list(void); @@ -118,6 +117,9 @@ extern void emit_number(const char *bits, unsigned nbits, unsigned is_signed, const char *file, unsigned lineno); extern void emit_string(const char *string); +extern void emit_icarus_generated_udps(void); +extern void emit_icarus_generated_top_module(void); + /* * Find the enclosing module scope. */ From a5b945f8f577ec744d8d8e82ec1b19c781da94e8 Mon Sep 17 00:00:00 2001 From: Cary R Date: Sun, 26 Nov 2017 20:24:58 -0800 Subject: [PATCH 535/595] Initialize the t0 trigger value to false. --- net_event.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net_event.cc b/net_event.cc index 1aa967859..f384ffccf 100644 --- a/net_event.cc +++ b/net_event.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2017 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 @@ -345,7 +345,7 @@ void NetEvProbe::find_similar_probes(list&plist) } NetEvWait::NetEvWait(NetProc*pr) -: statement_(pr) +: statement_(pr), has_t0_trigger_(false) { } From db1ea05452123c833abe6c2a534318416bb00211 Mon Sep 17 00:00:00 2001 From: Cary R Date: Sun, 3 Dec 2017 20:13:24 -0800 Subject: [PATCH 536/595] Fix #0 to trigger in the inactive region and add a trigger for always_comb/latch --- tgt-vvp/vvp_process.c | 14 ++++++++--- vvp/compile.cc | 20 +++++++++++++++ vvp/schedule.cc | 58 ++++++++++++++++++++++++++++++++----------- vvp/schedule.h | 10 +++++++- vvp/vthread.cc | 10 ++++---- 5 files changed, 88 insertions(+), 24 deletions(-) diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index 502c2a336..a8d2f1dfa 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 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 @@ -1643,6 +1643,7 @@ static int show_stmt_utask(ivl_statement_t net) static int show_stmt_wait(ivl_statement_t net, ivl_scope_t sscope) { + static unsigned int cascade_counter = 0; /* Look to see if this is a SystemVerilog wait fork. */ if ((ivl_stmt_nevent(net) == 1) && (ivl_stmt_events(net, 0) == 0)) { assert(ivl_statement_type(ivl_stmt_sub_stmt(net)) == IVL_ST_NOOP); @@ -1655,11 +1656,17 @@ static int show_stmt_wait(ivl_statement_t net, ivl_scope_t sscope) if (ivl_stmt_nevent(net) == 1) { ivl_event_t ev = ivl_stmt_events(net, 0); - fprintf(vvp_out, " %%wait E_%p;\n", ev); + if (ivl_stmt_needs_t0_trigger(net)) { + fprintf(vvp_out, "Ewait_%u .event/or E_%p, E_0x0;\n", + cascade_counter, ev); + fprintf(vvp_out, " %%wait Ewait_%u;\n", cascade_counter); + cascade_counter += 1; + } else { + fprintf(vvp_out, " %%wait E_%p;\n", ev); + } } else { unsigned idx; - static unsigned int cascade_counter = 0; ivl_event_t ev = ivl_stmt_events(net, 0); fprintf(vvp_out, "Ewait_%u .event/or E_%p", cascade_counter, ev); @@ -1667,6 +1674,7 @@ static int show_stmt_wait(ivl_statement_t net, ivl_scope_t sscope) ev = ivl_stmt_events(net, idx); fprintf(vvp_out, ", E_%p", ev); } + assert(ivl_stmt_needs_t0_trigger(net) == 0); fprintf(vvp_out, ";\n %%wait Ewait_%u;\n", cascade_counter); cascade_counter += 1; } diff --git a/vvp/compile.cc b/vvp/compile.cc index 7a13a67a7..0714fe5eb 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -478,6 +478,7 @@ struct vvp_net_resolv_list_s: public resolv_list_s { bool vvp_net_resolv_list_s::resolve(bool mes) { + static bool t0_trigger_generated = false; vvp_net_t*tmp = vvp_net_lookup(label()); if (tmp) { @@ -486,6 +487,25 @@ bool vvp_net_resolv_list_s::resolve(bool mes) return true; } + // This is a special label used to create a T0 trigger for the + // always_comb/latch processes. + if (! t0_trigger_generated && (strcmp(label(), "E_0x0") == 0)) { + // This should never happen, but if it does then the E_0x0 + // event generation may need to be explictly generated in + // the compiler output instead of implicitly in this code. + assert(! vpip_peek_current_scope()->is_automatic()); + t0_trigger_generated = true; + // Create an event with no name for the T0 trigger + compile_named_event(strdup(label()), strcpy(new char [1],"")); + tmp = vvp_net_lookup(label()); + assert(tmp); + tmp->link(port); + // Create a trigger for the T0 event. + vvp_net_ptr_t ptr (tmp, 0); + schedule_t0_trigger(ptr); + return true; + } + if (mes) fprintf(stderr, "unresolved vvp_net reference: %s\n", label()); diff --git a/vvp/schedule.cc b/vvp/schedule.cc index 577c0f983..b2fc085a3 100644 --- a/vvp/schedule.cc +++ b/vvp/schedule.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 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 @@ -76,6 +76,7 @@ struct event_time_s { count_time_events += 1; start = 0; active = 0; + inactive = 0; nbassign = 0; rwsync = 0; rosync = 0; @@ -86,6 +87,7 @@ struct event_time_s { struct event_s*start; struct event_s*active; + struct event_s*inactive; struct event_s*nbassign; struct event_s*rwsync; struct event_s*rosync; @@ -661,14 +663,13 @@ static void schedule_final_event(struct event_s*cur) * itself, and the structure is placed in the right place in the * queue. */ -typedef enum event_queue_e { SEQ_START, SEQ_ACTIVE, SEQ_NBASSIGN, +typedef enum event_queue_e { SEQ_START, SEQ_ACTIVE, SEQ_INACTIVE, SEQ_NBASSIGN, SEQ_RWSYNC, SEQ_ROSYNC, DEL_THREAD } event_queue_t; static void schedule_event_(struct event_s*cur, vvp_time64_t delay, event_queue_t select_queue) { cur->next = cur; - struct event_time_s*ctim = sched_list; if (sched_list == 0) { @@ -736,6 +737,11 @@ static void schedule_event_(struct event_s*cur, vvp_time64_t delay, q = &ctim->active; break; + case SEQ_INACTIVE: + assert(delay == 0); + q = &ctim->inactive; + break; + case SEQ_NBASSIGN: q = &ctim->nbassign; break; @@ -801,6 +807,23 @@ void schedule_vthread(vthread_t thr, vvp_time64_t delay, bool push_flag) } } +void schedule_t0_trigger(vvp_net_ptr_t ptr) +{ + vvp_vector4_t bit (1, BIT4_X); + struct assign_vector4_event_s*cur = new struct assign_vector4_event_s(bit); + cur->ptr = ptr; + schedule_event_(cur, 0, SEQ_INACTIVE); +} + +void schedule_inactive(vthread_t thr) +{ + struct vthread_event_s*cur = new vthread_event_s; + + cur->thr = thr; + vthread_mark_scheduled(thr); + schedule_event_(cur, 0, SEQ_INACTIVE); +} + void schedule_init_vthread(vthread_t thr) { struct vthread_event_s*cur = new vthread_event_s; @@ -1044,7 +1067,7 @@ static void run_rosync(struct event_time_s*ctim) delete cur; } - if (ctim->active || ctim->nbassign || ctim->rwsync) { + if (ctim->active || ctim->inactive || ctim->nbassign || ctim->rwsync) { cerr << "SCHEDULER ERROR: read-only sync events " << "created RW events!" << endl; } @@ -1145,21 +1168,26 @@ void schedule_simulate(void) queues. If there are not events at all, then release the event_time object. */ if (ctim->active == 0) { - ctim->active = ctim->nbassign; - ctim->nbassign = 0; + ctim->active = ctim->inactive; + ctim->inactive = 0; if (ctim->active == 0) { - ctim->active = ctim->rwsync; - ctim->rwsync = 0; + ctim->active = ctim->nbassign; + ctim->nbassign = 0; - /* If out of rw events, then run the rosync - events and delete this time step. This also - deletes threads as needed. */ if (ctim->active == 0) { - run_rosync(ctim); - sched_list = ctim->next; - delete ctim; - continue; + ctim->active = ctim->rwsync; + ctim->rwsync = 0; + + /* If out of rw events, then run the rosync + events and delete this time step. This also + deletes threads as needed. */ + if (ctim->active == 0) { + run_rosync(ctim); + sched_list = ctim->next; + delete ctim; + continue; + } } } } diff --git a/vvp/schedule.h b/vvp/schedule.h index f47057060..d60748d04 100644 --- a/vvp/schedule.h +++ b/vvp/schedule.h @@ -1,7 +1,7 @@ #ifndef IVL_schedule_H #define IVL_schedule_H /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2017 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 @@ -35,6 +35,8 @@ extern void schedule_vthread(vthread_t thr, vvp_time64_t delay, bool push_flag =false); +extern void schedule_inactive(vthread_t thr); + extern void schedule_init_vthread(vthread_t thr); extern void schedule_final_vthread(vthread_t thr); @@ -86,6 +88,12 @@ extern void schedule_set_vector(vvp_net_ptr_t ptr, const vvp_vector4_t&val); extern void schedule_set_vector(vvp_net_ptr_t ptr, vvp_vector8_t val); extern void schedule_set_vector(vvp_net_ptr_t ptr, double val); +/* + * Create a T0 event for always_comb/latch processes. This is the first + * event in the first inactive region. + */ +extern void schedule_t0_trigger(vvp_net_ptr_t ptr); + /* * The schedule_init_vector function assigns an initial value to a * functor. The assignment is put into a pre-simulation queue that is diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 46cd46869..3bed3ed59 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -2328,11 +2328,10 @@ bool of_DELAY(vthread_t thr, vvp_code_t cp) vvp_time64_t low = cp->bit_idx[0]; vvp_time64_t hig = cp->bit_idx[1]; - vvp_time64_t res = 32; - res = hig << res; - res += low; + vvp_time64_t delay = (hig << 32) | low; - schedule_vthread(thr, res); + if (delay == 0) schedule_inactive(thr); + else schedule_vthread(thr, delay); return false; } @@ -2342,7 +2341,8 @@ bool of_DELAYX(vthread_t thr, vvp_code_t cp) assert(cp->number < vthread_s::WORDS_COUNT); delay = thr->words[cp->number].w_uint; - schedule_vthread(thr, delay); + if (delay == 0) schedule_inactive(thr); + else schedule_vthread(thr, delay); return false; } From c38ca2114bb3c28976c48941062e9dfc62dce1c0 Mon Sep 17 00:00:00 2001 From: Cary R Date: Sun, 3 Dec 2017 20:14:41 -0800 Subject: [PATCH 537/595] Note the always_comb/ff/latch have not been looked at for synthesis --- syn-rules.y | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/syn-rules.y b/syn-rules.y index ac90c186a..cb9bf50d4 100644 --- a/syn-rules.y +++ b/syn-rules.y @@ -1,7 +1,7 @@ %{ /* - * Copyright (c) 2000-2015 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2017 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 @@ -304,6 +304,15 @@ static void syn_start_process(NetProcTop*t) last_ = first_; ptr_ = first_; + // Can the following be converted into S_ALWAYS? + if ((t->type() == IVL_PR_ALWAYS_COMB) || + (t->type() == IVL_PR_ALWAYS_FF) || + (t->type() == IVL_PR_ALWAYS_LATCH)) { + cerr << t->get_fileline() << ": internal error: " + << " Need to check if this can be synthesized." << endl; + assert(0); + } + first_->token = (t->type() == IVL_PR_ALWAYS)? S_ALWAYS : S_INITIAL; first_->top = t; first_->next_ = 0; From 39c14edb76cf47783929b8c714b70128bdec49ec Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 5 Dec 2017 21:48:33 -0800 Subject: [PATCH 538/595] The delay for a join_any and join_none is different than join --- netlist.cc | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/netlist.cc b/netlist.cc index d611f2b03..b57bbd97a 100644 --- a/netlist.cc +++ b/netlist.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2017 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 @@ -2804,12 +2804,27 @@ DelayType NetProc::delay_type() const DelayType NetBlock::delay_type() const { - DelayType result = NO_DELAY; + // A join_none has no delay. + if (type() == PARA_JOIN_NONE) return NO_DELAY; - for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) { - DelayType dt = cur->delay_type(); - if (dt > result) result = dt; - if (dt == DEFINITE_DELAY) break; + DelayType result; + // A join_any has the minimum delay. + if (type() == PARA_JOIN_ANY) { + result = DEFINITE_DELAY; + for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) { + DelayType dt = cur->delay_type(); + if (dt < result) result = dt; + if (dt == NO_DELAY) break; + } + + // A begin or join has the maximum delay. + } else { + result = NO_DELAY; + for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) { + DelayType dt = cur->delay_type(); + if (dt > result) result = dt; + if (dt == DEFINITE_DELAY) break; + } } return result; @@ -2880,9 +2895,10 @@ DelayType NetPDelay::delay_type() const return DEFINITE_DELAY; } else { if (statement_) { - return statement_->delay_type(); + return combine_delays(ZERO_DELAY, + statement_->delay_type()); } else { - return NO_DELAY; + return ZERO_DELAY; } } } From cb0ffd734ef87f89f6b346e3a781aa02ca077163 Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 5 Dec 2017 22:09:05 -0800 Subject: [PATCH 539/595] Check to see that always_comb/ff/latch do not have delays/events --- elaborate.cc | 32 ++++++++++++++++++++++++++++++++ net_event.cc | 5 +++++ netlist.h | 1 + 3 files changed, 38 insertions(+) diff --git a/elaborate.cc b/elaborate.cc index 85a2ceb4c..1a99c7195 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -6136,6 +6136,38 @@ bool Design::check_proc_delay() const cerr << pr->get_fileline() << ": : A runtime" << " infinite loop may be possible." << endl; } + + // The always_comb/ff/latch blocks have special delay + // rules that need to be checked. + if ((pr->type() == IVL_PR_ALWAYS_COMB) || + (pr->type() == IVL_PR_ALWAYS_FF) || + (pr->type() == IVL_PR_ALWAYS_LATCH)) { + const NetEvWait *wait = dynamic_cast (pr->statement()); + if (! wait) { + // The always_comb/latch have an event wait + // added automatically by the compiler. + assert(pr->type() == IVL_PR_ALWAYS_FF); + cerr << pr->get_fileline() << ": error: the " + << "first statement of an always_ff must " + << "be an event control." << endl; + result_flag = false; + } else if (wait->statement()->delay_type() != NO_DELAY) { + cerr << pr->get_fileline() << ": error: there " + << "must "; + + if (pr->type() == IVL_PR_ALWAYS_FF) { + cerr << "only be a single event control " + << "and no blocking delays in an " + << "always_ff process."; + } else { + cerr << "be no event controls or blocking " + << "delays in an always_comb/latch " + << "process."; + } + cerr << endl; + result_flag = false; + } + } } /* If this is a final block it must not have a delay, diff --git a/net_event.cc b/net_event.cc index f384ffccf..8c66ff1bf 100644 --- a/net_event.cc +++ b/net_event.cc @@ -442,3 +442,8 @@ NetProc* NetEvWait::statement() { return statement_; } + +const NetProc* NetEvWait::statement() const +{ + return statement_; +} diff --git a/netlist.h b/netlist.h index ad8a78f9f..ab9aa78ba 100644 --- a/netlist.h +++ b/netlist.h @@ -3406,6 +3406,7 @@ class NetEvWait : public NetProc { inline bool has_t0_trigger() const { return has_t0_trigger_; }; NetProc*statement(); + const NetProc*statement() const; virtual bool emit_proc(struct target_t*) const; bool emit_recurse(struct target_t*) const; From f17992bcd00e7de9ec8fe00472b42fced298478c Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 6 Dec 2017 00:21:24 -0800 Subject: [PATCH 540/595] Report the lines that have delay or event control in an always_comb/ff/latch process --- elaborate.cc | 2 +- netlist.cc | 68 ++++++++++++++++++++++++++++++---------------------- netlist.h | 26 ++++++++++---------- 3 files changed, 53 insertions(+), 43 deletions(-) diff --git a/elaborate.cc b/elaborate.cc index 1a99c7195..e378e842a 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -6151,7 +6151,7 @@ bool Design::check_proc_delay() const << "first statement of an always_ff must " << "be an event control." << endl; result_flag = false; - } else if (wait->statement()->delay_type() != NO_DELAY) { + } else if (wait->statement()->delay_type(true) != NO_DELAY) { cerr << pr->get_fileline() << ": error: there " << "must "; diff --git a/netlist.cc b/netlist.cc index b57bbd97a..70d65031e 100644 --- a/netlist.cc +++ b/netlist.cc @@ -2768,7 +2768,7 @@ static DelayType delay_type_from_expr(const NetExpr*expr) * The looping structures can use the same basic code so put it here * instead of duplicating it for each one (repeat and while). */ -static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc) +static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc, bool print_delay) { DelayType result; @@ -2779,12 +2779,12 @@ static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc) break; /* We have a constant true expression so the body always runs. */ case DEFINITE_DELAY: - result = proc->delay_type(); + result = proc->delay_type(print_delay); break; /* We don't know if the body will run so reduce a DEFINITE_DELAY * to a POSSIBLE_DELAY. All other stay the same. */ case POSSIBLE_DELAY: - result = combine_delays(NO_DELAY, proc->delay_type()); + result = combine_delays(NO_DELAY, proc->delay_type(print_delay)); break; /* This should never happen since delay_type_from_expr() only * returns three different values. */ @@ -2797,12 +2797,12 @@ static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc) } /* The default object does not have any delay. */ -DelayType NetProc::delay_type() const +DelayType NetProc::delay_type(bool /* print_delay */ ) const { return NO_DELAY; } -DelayType NetBlock::delay_type() const +DelayType NetBlock::delay_type(bool print_delay) const { // A join_none has no delay. if (type() == PARA_JOIN_NONE) return NO_DELAY; @@ -2812,7 +2812,7 @@ DelayType NetBlock::delay_type() const if (type() == PARA_JOIN_ANY) { result = DEFINITE_DELAY; for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) { - DelayType dt = cur->delay_type(); + DelayType dt = cur->delay_type(print_delay); if (dt < result) result = dt; if (dt == NO_DELAY) break; } @@ -2821,7 +2821,7 @@ DelayType NetBlock::delay_type() const } else { result = NO_DELAY; for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) { - DelayType dt = cur->delay_type(); + DelayType dt = cur->delay_type(print_delay); if (dt > result) result = dt; if (dt == DEFINITE_DELAY) break; } @@ -2830,7 +2830,7 @@ DelayType NetBlock::delay_type() const return result; } -DelayType NetCase::delay_type() const +DelayType NetCase::delay_type(bool print_delay) const { DelayType result = NO_DELAY; bool def_stmt = false; @@ -2838,7 +2838,7 @@ DelayType NetCase::delay_type() const for (unsigned idx = 0; idx < nstmts; idx += 1) { if (!expr(idx)) def_stmt = true; - DelayType dt = stat(idx) ? stat(idx)->delay_type() : NO_DELAY; + DelayType dt = stat(idx) ? stat(idx)->delay_type(print_delay) : NO_DELAY; if (idx == 0) { result = dt; } else { @@ -2853,41 +2853,51 @@ DelayType NetCase::delay_type() const return result; } -DelayType NetCondit::delay_type() const +DelayType NetCondit::delay_type(bool print_delay) const { - DelayType if_type = if_ ? if_->delay_type() : NO_DELAY; - DelayType el_type = else_? else_->delay_type() : NO_DELAY; + DelayType if_type = if_ ? if_->delay_type(print_delay) : NO_DELAY; + DelayType el_type = else_? else_->delay_type(print_delay) : NO_DELAY; return combine_delays(if_type, el_type); } /* * A do/while will execute the body at least once. */ -DelayType NetDoWhile::delay_type() const +DelayType NetDoWhile::delay_type(bool print_delay) const { ivl_assert(*this, proc_); - return proc_->delay_type(); + return proc_->delay_type(print_delay); } -DelayType NetEvWait::delay_type() const +DelayType NetEvWait::delay_type(bool print_delay) const { + if (print_delay) { + cerr << get_fileline() << ": error: an event control is not allowed " + << "in an always_comb, always_ff or always_latch process." + << endl; + } return DEFINITE_DELAY; } -DelayType NetForever::delay_type() const +DelayType NetForever::delay_type(bool print_delay) const { ivl_assert(*this, statement_); - return statement_->delay_type(); + return statement_->delay_type(print_delay); } -DelayType NetForLoop::delay_type() const +DelayType NetForLoop::delay_type(bool print_delay) const { ivl_assert(*this, statement_); - return get_loop_delay_type(condition_, statement_); + return get_loop_delay_type(condition_, statement_, print_delay); } -DelayType NetPDelay::delay_type() const +DelayType NetPDelay::delay_type(bool print_delay) const { + if (print_delay) { + cerr << get_fileline() << ": error: a blocking delay is not allowed " + << "in an always_comb, always_ff or always_latch process." + << endl; + } if (expr_) { return delay_type_from_expr(expr_); } else { @@ -2896,7 +2906,7 @@ DelayType NetPDelay::delay_type() const } else { if (statement_) { return combine_delays(ZERO_DELAY, - statement_->delay_type()); + statement_->delay_type(print_delay)); } else { return ZERO_DELAY; } @@ -2904,24 +2914,24 @@ DelayType NetPDelay::delay_type() const } } -DelayType NetRepeat::delay_type() const +DelayType NetRepeat::delay_type(bool print_delay) const { ivl_assert(*this, statement_); - return get_loop_delay_type(expr_, statement_); + return get_loop_delay_type(expr_, statement_, print_delay); } -DelayType NetTaskDef::delay_type() const +DelayType NetTaskDef::delay_type(bool print_delay) const { - return proc_->delay_type(); + return proc_->delay_type(print_delay); } -DelayType NetUTask::delay_type() const +DelayType NetUTask::delay_type(bool print_delay) const { - return task()->task_def()->delay_type(); + return task()->task_def()->delay_type(print_delay); } -DelayType NetWhile::delay_type() const +DelayType NetWhile::delay_type(bool print_delay) const { ivl_assert(*this, proc_); - return get_loop_delay_type(cond_, proc_); + return get_loop_delay_type(cond_, proc_, print_delay); } diff --git a/netlist.h b/netlist.h index ab9aa78ba..2f431269e 100644 --- a/netlist.h +++ b/netlist.h @@ -2715,7 +2715,7 @@ class NetProc : public virtual LineInfo { virtual void dump(ostream&, unsigned ind) const; // Recursively checks to see if there is delay in this element. - virtual DelayType delay_type() const; + virtual DelayType delay_type(bool print_delay=false) const; protected: bool synth_async_block_substatement_(Design*des, NetScope*scope, @@ -3018,7 +3018,7 @@ class NetBlock : public NetProc { virtual bool emit_proc(struct target_t*) const; virtual int match_proc(struct proc_match_t*); virtual void dump(ostream&, unsigned ind) const; - virtual DelayType delay_type() const; + virtual DelayType delay_type(bool print_delay=false) const; private: const Type type_; @@ -3065,7 +3065,7 @@ class NetCase : public NetProc { virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; - virtual DelayType delay_type() const; + virtual DelayType delay_type(bool print_delay=false) const; virtual bool evaluate_function(const LineInfo&loc, map&ctx) const; @@ -3155,7 +3155,7 @@ class NetCondit : public NetProc { virtual bool emit_proc(struct target_t*) const; virtual int match_proc(struct proc_match_t*); virtual void dump(ostream&, unsigned ind) const; - virtual DelayType delay_type() const; + virtual DelayType delay_type(bool print_delay=false) const; virtual bool evaluate_function(const LineInfo&loc, map&ctx) const; @@ -3256,7 +3256,7 @@ class NetDoWhile : public NetProc { virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; - virtual DelayType delay_type() const; + virtual DelayType delay_type(bool print_delay=false) const; virtual bool evaluate_function(const LineInfo&loc, map&ctx) const; @@ -3439,7 +3439,7 @@ class NetEvWait : public NetProc { virtual void dump(ostream&, unsigned ind) const; // This will ignore any statement. virtual void dump_inline(ostream&) const; - virtual DelayType delay_type() const; + virtual DelayType delay_type(bool print_delay=false) const; private: NetProc*statement_; @@ -3509,7 +3509,7 @@ class NetForever : public NetProc { virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; - virtual DelayType delay_type() const; + virtual DelayType delay_type(bool print_delay=false) const; virtual bool evaluate_function(const LineInfo&loc, map&ctx) const; @@ -3532,7 +3532,7 @@ class NetForLoop : public NetProc { virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; - virtual DelayType delay_type() const; + virtual DelayType delay_type(bool print_delay=false) const; virtual bool evaluate_function(const LineInfo&loc, map&ctx) const; @@ -3633,7 +3633,7 @@ class NetPDelay : public NetProc { virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; - virtual DelayType delay_type() const; + virtual DelayType delay_type(bool print_delay=false) const; bool emit_proc_recurse(struct target_t*) const; @@ -3658,7 +3658,7 @@ class NetRepeat : public NetProc { virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; - virtual DelayType delay_type() const; + virtual DelayType delay_type(bool print_delay=false) const; virtual bool evaluate_function(const LineInfo&loc, map&ctx) const; @@ -3739,7 +3739,7 @@ class NetTaskDef : public NetBaseDef { ~NetTaskDef(); void dump(ostream&, unsigned) const; - DelayType delay_type() const; + DelayType delay_type(bool print_delay=false) const; private: // not implemented NetTaskDef(const NetTaskDef&); @@ -3856,7 +3856,7 @@ class NetUTask : public NetProc { virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; - virtual DelayType delay_type() const; + virtual DelayType delay_type(bool print_delay=false) const; private: NetScope*task_; @@ -3881,7 +3881,7 @@ class NetWhile : public NetProc { virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; - virtual DelayType delay_type() const; + virtual DelayType delay_type(bool print_delay=false) const; virtual bool evaluate_function(const LineInfo&loc, map&ctx) const; From 9a8212a54f09adc538ca522a27eadd638e63119a Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 13 Dec 2017 21:55:27 -0800 Subject: [PATCH 541/595] Update tp the latest files from GTKWave --- vpi/lz4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpi/lz4.c b/vpi/lz4.c index 08cf6b5cd..c050cf1e0 100644 --- a/vpi/lz4.c +++ b/vpi/lz4.c @@ -825,7 +825,7 @@ _next_match: /* Match description too long : reduce it */ matchLength = (15-1) + (oMaxMatch-op) * 255; } - //printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH); + /*printf("offset %5i, matchLength%5i \n", (int)(ip-match), matchLength + MINMATCH);*/ ip += MINMATCH + matchLength; if (matchLength>=ML_MASK) From 7b84b29bbca2f0ce6f29744037ce1fef0924b2e2 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Sat, 16 Dec 2017 23:59:48 +1300 Subject: [PATCH 542/595] tgt-vvp: Output semicolon after .port_info statements Backwards compatablity is perserved due to the parser interperting the unexpected semicolon as an empty statement. --- tgt-vvp/vvp_scope.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index b272c36fa..4c3194d98 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -2304,7 +2304,7 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) unsigned width = ivl_scope_mod_module_port_width(net,idx); if( name == 0 ) name = ""; - fprintf( vvp_out, " .port_info %u %s %u \"%s\"\n", + fprintf( vvp_out, " .port_info %u %s %u \"%s\";\n", idx, vvp_port_info_type_str(ptype), width, vvp_mangle_name(name) ); } From d01e5accc08c6f87293b369c883a2c18f7c4b5a4 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Sun, 17 Dec 2017 00:06:09 +1300 Subject: [PATCH 543/595] vpp: Require semicolon after .port_info statements Optional until 12.0 --- vvp/parse.y | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/vvp/parse.y b/vvp/parse.y index 3276a3c58..309a3e282 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -27,6 +27,7 @@ # include # include # include "ivl_alloc.h" +# include "version_base.h" /* * These are bits in the lexor. @@ -708,9 +709,19 @@ statement /* Port information for scopes... currently this is just meta-data for VPI queries */ - | K_PORT_INFO T_NUMBER port_type T_NUMBER T_STRING + | K_PORT_INFO T_NUMBER port_type T_NUMBER T_STRING ';' { compile_port_info( $2 /* port_index */, $3, $4 /* width */, $5 /*&name */ ); } + /* Unfortunately, older versions didn't check for a semicolon at the end of + .port_info statements. + To insure backwards compatablitly with old files, we have a duplicate rule + that doesn't require a semicolon. After version 11, this rule will be + disabled (and can safely be deleted. */ + | K_PORT_INFO T_NUMBER port_type T_NUMBER T_STRING + { if (VERSION_MAJOR > 11) + yyerror("syntax error"); + compile_port_info( $2 /* port_index */, $3, $4 /* width */, + $5 /*&name */ ); } | K_TIMESCALE T_NUMBER T_NUMBER';' { compile_timescale($2, $3); } From 2bbd077dc90887028ca0770c32b4a8dc0a34010f Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 27 Dec 2017 14:41:43 -0800 Subject: [PATCH 544/595] Add some synthesis checks for the always_comb/ff/latch blocks --- elaborate.cc | 70 ++++-- expr_synth.cc | 3 +- net_event.cc | 1 + net_nex_input.cc | 190 ++++++++++------ net_nex_output.cc | 51 +++-- netlist.cc | 564 ++++++++++++++++++++++++++++++++++++++++++++-- netlist.h | 44 +++- 7 files changed, 785 insertions(+), 138 deletions(-) diff --git a/elaborate.cc b/elaborate.cc index e378e842a..f450a42ff 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -2906,11 +2906,12 @@ NetProc* PBlock::elaborate(Design*des, NetScope*scope) const if (nscope == 0) nscope = scope; - // Handle the special case that the block contains only one - // statement. There is no need to keep the block node. Also, - // don't elide named blocks, because they might be referenced - // elsewhere. - if ((list_.size() == 1) && (pscope_name() == 0)) { + // Handle the special case that the sequential block contains + // only one statement. There is no need to keep the block node. + // Also, don't elide named blocks, because they might be + // referenced elsewhere. + if ((type == NetBlock::SEQU) && (list_.size() == 1) && + (pscope_name() == 0)) { assert(list_[0]); NetProc*tmp = list_[0]->elaborate(des, nscope); return tmp; @@ -4190,6 +4191,7 @@ NetProc* PEventStatement::elaborate_st(Design*des, NetScope*scope, NetEvent*ev = new NetEvent(scope->local_symbol()); ev->set_line(*this); + ev->local_flag(true); unsigned expr_count = 0; NetEvWait*wa = new NetEvWait(enet); @@ -4470,6 +4472,8 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope, /* Create an event wait and an otherwise unreferenced event variable to force a perpetual wait. */ NetEvent*wait_event = new NetEvent(scope->local_symbol()); + wait_event->set_line(*this); + wait_event->local_flag(true); scope->add_event(wait_event); NetEvWait*wait = new NetEvWait(0); @@ -4490,6 +4494,8 @@ NetProc* PEventStatement::elaborate_wait(Design*des, NetScope*scope, eval_expr(expr); NetEvent*wait_event = new NetEvent(scope->local_symbol()); + wait_event->set_line(*this); + wait_event->local_flag(true); scope->add_event(wait_event); NetEvWait*wait = new NetEvWait(0 /* noop */); @@ -6110,10 +6116,10 @@ class later_defparams : public elaborator_work_item_t { bool Design::check_proc_delay() const { - bool result_flag = true; + bool result = false; for (const NetProcTop*pr = procs_ ; pr ; pr = pr->next_) { - /* If this is an always block and we have no or zero delay then + /* If this is an always process and we have no or zero delay then * a runtime infinite loop will happen. If we possibly have some * delay then print a warning that an infinite loop is possible. */ @@ -6128,7 +6134,7 @@ bool Design::check_proc_delay() const << " statement does not have any delay." << endl; cerr << pr->get_fileline() << ": : A runtime" << " infinite loop will occur." << endl; - result_flag = false; + result = true; } else if (dly_type == POSSIBLE_DELAY && warn_inf_loop) { cerr << pr->get_fileline() << ": warning: always" @@ -6137,20 +6143,20 @@ bool Design::check_proc_delay() const << " infinite loop may be possible." << endl; } - // The always_comb/ff/latch blocks have special delay - // rules that need to be checked. + // The always_comb/ff/latch processes also have special + // delay rules that need to be checked. if ((pr->type() == IVL_PR_ALWAYS_COMB) || (pr->type() == IVL_PR_ALWAYS_FF) || (pr->type() == IVL_PR_ALWAYS_LATCH)) { const NetEvWait *wait = dynamic_cast (pr->statement()); if (! wait) { - // The always_comb/latch have an event wait - // added automatically by the compiler. + // The always_comb/latch processes have an event + // control added automatically by the compiler. assert(pr->type() == IVL_PR_ALWAYS_FF); cerr << pr->get_fileline() << ": error: the " << "first statement of an always_ff must " << "be an event control." << endl; - result_flag = false; + result = true; } else if (wait->statement()->delay_type(true) != NO_DELAY) { cerr << pr->get_fileline() << ": error: there " << "must "; @@ -6165,7 +6171,7 @@ bool Design::check_proc_delay() const << "process."; } cerr << endl; - result_flag = false; + result = true; } } } @@ -6180,12 +6186,30 @@ bool Design::check_proc_delay() const if (dly_type != NO_DELAY && dly_type != ZERO_DELAY) { cerr << pr->get_fileline() << ": error: final" << " statement contains a delay." << endl; - result_flag = false; + result = true; } } } - return result_flag; + return result; +} + +/* + * Check to see if the always_* processes only contain synthesizable + * constructs. + */ +bool Design::check_proc_synth() const +{ + bool result = false; + for (const NetProcTop*pr = procs_ ; pr ; pr = pr->next_) { + if ((pr->type() == IVL_PR_ALWAYS_COMB) || + (pr->type() == IVL_PR_ALWAYS_FF) || + (pr->type() == IVL_PR_ALWAYS_LATCH)) { + result |= pr->statement()->check_synth(pr->type(), + pr->scope()); + } + } + return result; } /* @@ -6589,10 +6613,11 @@ Design* elaborate(listroots) // Now that everything is fully elaborated verify that we do // not have an always block with no delay (an infinite loop), // or a final block with a delay. - if (des->check_proc_delay() == false) { - delete des; - des = 0; - } + bool has_failure = des->check_proc_delay(); + + // Check to see if the always_comb/ff/latch processes only have + // synthesizable constructs + has_failure |= des->check_proc_synth(); if (debug_elaborate) { cerr << "" << ": debug: " @@ -6600,5 +6625,10 @@ Design* elaborate(listroots) << des->find_root_scopes().size() << " root scopes " << endl; } + if (has_failure) { + delete des; + des = 0; + } + return des; } diff --git a/expr_synth.cc b/expr_synth.cc index 6f8ca29b9..5c28e1adb 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2015 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2017 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 @@ -1358,6 +1358,7 @@ static NetEvWait* make_func_trigger(Design*des, NetScope*scope, NetExpr*root) if (nset && (nset->size() > 0)) { NetEvent*ev = new NetEvent(scope->local_symbol()); ev->set_line(*root); + ev->local_flag(true); NetEvProbe*pr = new NetEvProbe(scope, scope->local_symbol(), ev, NetEvProbe::ANYEDGE, diff --git a/net_event.cc b/net_event.cc index 8c66ff1bf..2b6eb8d35 100644 --- a/net_event.cc +++ b/net_event.cc @@ -28,6 +28,7 @@ NetEvent::NetEvent(perm_string n) : name_(n) { + local_flag_ = false; scope_ = 0; snext_ = 0; probes_ = 0; diff --git a/net_nex_input.cc b/net_nex_input.cc index f11ffad7e..38e7e148a 100644 --- a/net_nex_input.cc +++ b/net_nex_input.cc @@ -32,7 +32,7 @@ NexusSet* NetExpr::nex_input(bool, bool) const cerr << get_fileline() << ": internal error: nex_input not implemented: " << *this << endl; - return 0; + return new NexusSet; } NexusSet* NetProc::nex_input(bool, bool) const @@ -40,7 +40,7 @@ NexusSet* NetProc::nex_input(bool, bool) const cerr << get_fileline() << ": internal error: NetProc::nex_input not implemented" << endl; - return 0; + return new NexusSet; } NexusSet* NetEArrayPattern::nex_input(bool rem_out, bool search_funcs) const @@ -69,12 +69,12 @@ NexusSet* NetEBinary::nex_input(bool rem_out, bool search_funcs) const NexusSet* NetEConcat::nex_input(bool rem_out, bool search_funcs) const { - if (parms_[0] == NULL) return NULL; + if (parms_[0] == NULL) return new NexusSet; NexusSet*result = parms_[0]->nex_input(rem_out, search_funcs); for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) { if (parms_[idx] == NULL) { delete result; - return NULL; + return new NexusSet; } NexusSet*tmp = parms_[idx]->nex_input(rem_out, search_funcs); result->add(*tmp); @@ -140,10 +140,6 @@ NexusSet* NetESelect::nex_input(bool rem_out, bool search_funcs) const { NexusSet*result = base_? base_->nex_input(rem_out, search_funcs) : new NexusSet(); NexusSet*tmp = expr_->nex_input(rem_out, search_funcs); - if (tmp == NULL) { - delete result; - return NULL; - } result->add(*tmp); delete tmp; /* See the comment for NetESignal below. */ @@ -159,19 +155,18 @@ NexusSet* NetESelect::nex_input(bool rem_out, bool search_funcs) const */ NexusSet* NetESFunc::nex_input(bool rem_out, bool search_funcs) const { - if (parms_.empty()) - return new NexusSet; + NexusSet*result = new NexusSet; - NexusSet*result; - if (parms_[0]) result = parms_[0]->nex_input(rem_out, search_funcs); - else result = new NexusSet; - for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) { + if (parms_.empty()) return result; + + for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) { if (parms_[idx]) { NexusSet*tmp = parms_[idx]->nex_input(rem_out, search_funcs); result->add(*tmp); delete tmp; } } + return result; } @@ -259,9 +254,16 @@ NexusSet* NetEUnary::nex_input(bool rem_out, bool search_funcs) const return expr_->nex_input(rem_out, search_funcs); } +NexusSet* NetAlloc::nex_input(bool, bool) const +{ + return new NexusSet; +} + NexusSet* NetAssign_::nex_input(bool rem_out, bool search_funcs) const { + assert(! nest_); NexusSet*result = new NexusSet; + if (word_) { NexusSet*tmp = word_->nex_input(rem_out, search_funcs); result->add(*tmp); @@ -278,7 +280,13 @@ NexusSet* NetAssign_::nex_input(bool rem_out, bool search_funcs) const NexusSet* NetAssignBase::nex_input(bool rem_out, bool search_funcs) const { - NexusSet*result = rval_->nex_input(rem_out, search_funcs); + NexusSet*result = new NexusSet; + // For the deassign and release statements there is no R-value. + if (rval_) { + NexusSet*tmp = rval_->nex_input(rem_out, search_funcs); + result->add(*tmp); + delete tmp; + } /* It is possible that the lval_ can have nex_input values. In particular, index expressions are statement inputs as well, @@ -311,14 +319,13 @@ NexusSet* NetAssignBase::nex_input(bool rem_out, bool search_funcs) const */ NexusSet* NetBlock::nex_input(bool rem_out, bool search_funcs) const { - if (last_ == 0) - return new NexusSet; + if (last_ == 0) return new NexusSet; - if (type_ != SEQU) { + if (! search_funcs && (type_ != SEQU)) { cerr << get_fileline() << ": internal error: Sorry, " << "I don't know how to synthesize fork/join blocks." << endl; - return 0; + return new NexusSet; } NetProc*cur = last_->next_; @@ -332,7 +339,7 @@ NexusSet* NetBlock::nex_input(bool rem_out, bool search_funcs) const NexusSet*tmp = cur->nex_input(rem_out, search_funcs); /* Add the current input set to the accumulated input set. */ - if (tmp != 0) result->add(*tmp); + result->add(*tmp); delete tmp; /* Add the current outputs to the accumulated output set if @@ -359,8 +366,6 @@ NexusSet* NetBlock::nex_input(bool rem_out, bool search_funcs) const NexusSet* NetCase::nex_input(bool rem_out, bool search_funcs) const { NexusSet*result = expr_->nex_input(rem_out, search_funcs); - if (result == 0) - return 0; for (size_t idx = 0 ; idx < items_.size() ; idx += 1) { @@ -369,7 +374,6 @@ NexusSet* NetCase::nex_input(bool rem_out, bool search_funcs) const continue; NexusSet*tmp = items_[idx].statement->nex_input(rem_out, search_funcs); - assert(tmp); result->add(*tmp); delete tmp; @@ -378,7 +382,6 @@ NexusSet* NetCase::nex_input(bool rem_out, bool search_funcs) const guard. The default guard obviously has no input. */ if (items_[idx].guard) { tmp = items_[idx].guard->nex_input(rem_out, search_funcs); - assert(tmp); result->add(*tmp); delete tmp; } @@ -387,16 +390,10 @@ NexusSet* NetCase::nex_input(bool rem_out, bool search_funcs) const return result; } -NexusSet* NetCAssign::nex_input(bool, bool) const -{ - cerr << get_fileline() << ": internal warning: NetCAssign::nex_input()" - << " not implemented." << endl; - return new NexusSet; -} - NexusSet* NetCondit::nex_input(bool rem_out, bool search_funcs) const { NexusSet*result = expr_->nex_input(rem_out, search_funcs); + if (if_ != 0) { NexusSet*tmp = if_->nex_input(rem_out, search_funcs); result->add(*tmp); @@ -412,51 +409,85 @@ NexusSet* NetCondit::nex_input(bool rem_out, bool search_funcs) const return result; } +NexusSet* NetDisable::nex_input(bool, bool) const +{ + return new NexusSet; +} + NexusSet* NetDoWhile::nex_input(bool rem_out, bool search_funcs) const { - NexusSet*result = proc_->nex_input(rem_out, search_funcs); - NexusSet*tmp = cond_->nex_input(rem_out, search_funcs); - result->add(*tmp); - delete tmp; + NexusSet*result = cond_->nex_input(rem_out, search_funcs); + + if (proc_) { + NexusSet*tmp = proc_->nex_input(rem_out, search_funcs); + result->add(*tmp); + delete tmp; + } + return result; } +NexusSet* NetEvTrig::nex_input(bool, bool) const +{ + return new NexusSet; +} + NexusSet* NetEvWait::nex_input(bool rem_out, bool search_funcs) const { - NexusSet*result; - if (statement_) - result = statement_->nex_input(rem_out, search_funcs); - else - result = new NexusSet; + NexusSet*result = new NexusSet; + + if (statement_) { + NexusSet*tmp = statement_->nex_input(rem_out, search_funcs); + result->add(*tmp); + delete tmp; + } return result; } -NexusSet* NetForce::nex_input(bool, bool) const +NexusSet* NetForever::nex_input(bool rem_out, bool search_funcs) const { - cerr << get_fileline() << ": internal warning: NetForce::nex_input()" - << " not implemented." << endl; - return new NexusSet; + NexusSet*result = new NexusSet; + + if (statement_) { + NexusSet*tmp = statement_->nex_input(rem_out, search_funcs); + result->add(*tmp); + delete tmp; + } + + return result; } NexusSet* NetForLoop::nex_input(bool rem_out, bool search_funcs) const { - NexusSet*result = init_expr_->nex_input(rem_out, search_funcs); + NexusSet*result = new NexusSet; - NexusSet*tmp = condition_->nex_input(rem_out, search_funcs); - result->add(*tmp); - delete tmp; + if (init_expr_) { + NexusSet*tmp = init_expr_->nex_input(rem_out, search_funcs); + result->add(*tmp); + delete tmp; + } - tmp = statement_->nex_input(rem_out, search_funcs); - result->add(*tmp); - delete tmp; + if (condition_) { + NexusSet*tmp = condition_->nex_input(rem_out, search_funcs); + result->add(*tmp); + delete tmp; + } - tmp = step_statement_->nex_input(rem_out, search_funcs); - result->add(*tmp); - delete tmp; + if (step_statement_) { + NexusSet*tmp = step_statement_->nex_input(rem_out, search_funcs); + result->add(*tmp); + delete tmp; + } + + if (statement_) { + NexusSet*tmp = statement_->nex_input(rem_out, search_funcs); + result->add(*tmp); + delete tmp; + } if (gn_shared_loop_index_flag) { - tmp = new NexusSet(); + NexusSet*tmp = new NexusSet(); for (unsigned idx = 0 ; idx < index_->pin_count() ; idx += 1) tmp->add(index_->pin(idx).nexus(), 0, index_->vector_width()); @@ -467,10 +498,9 @@ NexusSet* NetForLoop::nex_input(bool rem_out, bool search_funcs) const return result; } -NexusSet* NetForever::nex_input(bool rem_out, bool search_funcs) const +NexusSet* NetFree::nex_input(bool, bool) const { - NexusSet*result = statement_->nex_input(rem_out, search_funcs); - return result; + return new NexusSet; } /* @@ -484,17 +514,27 @@ NexusSet* NetForever::nex_input(bool rem_out, bool search_funcs) const */ NexusSet* NetPDelay::nex_input(bool rem_out, bool search_funcs) const { - if (statement_ == 0) return 0; - NexusSet*result = statement_->nex_input(rem_out, search_funcs); + NexusSet*result = new NexusSet; + + if (statement_) { + NexusSet*tmp = statement_->nex_input(rem_out, search_funcs); + result->add(*tmp); + delete tmp; + } + return result; } NexusSet* NetRepeat::nex_input(bool rem_out, bool search_funcs) const { - NexusSet*result = statement_->nex_input(rem_out, search_funcs); - NexusSet*tmp = expr_->nex_input(rem_out, search_funcs); - result->add(*tmp); - delete tmp; + NexusSet*result = expr_->nex_input(rem_out, search_funcs); + + if (statement_) { + NexusSet*tmp = statement_->nex_input(rem_out, search_funcs); + result->add(*tmp); + delete tmp; + } + return result; } @@ -503,13 +543,11 @@ NexusSet* NetRepeat::nex_input(bool rem_out, bool search_funcs) const */ NexusSet* NetSTask::nex_input(bool rem_out, bool search_funcs) const { - if (parms_.empty()) - return new NexusSet; + NexusSet*result = new NexusSet; - NexusSet*result; - if (parms_[0]) result = parms_[0]->nex_input(rem_out, search_funcs); - else result = new NexusSet; - for (unsigned idx = 1 ; idx < parms_.size() ; idx += 1) { + if (parms_.empty()) return result; + + for (unsigned idx = 0 ; idx < parms_.size() ; idx += 1) { if (parms_[idx]) { NexusSet*tmp = parms_[idx]->nex_input(rem_out, search_funcs); result->add(*tmp); @@ -532,9 +570,13 @@ NexusSet* NetUTask::nex_input(bool, bool) const NexusSet* NetWhile::nex_input(bool rem_out, bool search_funcs) const { - NexusSet*result = proc_->nex_input(rem_out, search_funcs); - NexusSet*tmp = cond_->nex_input(rem_out, search_funcs); - result->add(*tmp); - delete tmp; + NexusSet*result = cond_->nex_input(rem_out, search_funcs); + + if (proc_) { + NexusSet*tmp = proc_->nex_input(rem_out, search_funcs); + result->add(*tmp); + delete tmp; + } + return result; } diff --git a/net_nex_output.cc b/net_nex_output.cc index 194947955..9c1d32e10 100644 --- a/net_nex_output.cc +++ b/net_nex_output.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2017 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 @@ -36,8 +36,13 @@ void NetProc::nex_output(NexusSet&) << endl; } +void NetAlloc::nex_output(NexusSet&) +{ +} + void NetAssign_::nex_output(NexusSet&out) { + assert(! nest_); assert(sig_); unsigned use_word = 0; unsigned use_base = 0; @@ -89,8 +94,7 @@ void NetAssignBase::nex_output(NexusSet&out) void NetBlock::nex_output(NexusSet&out) { - if (last_ == 0) - return; + if (last_ == 0) return; NetProc*cur = last_; do { @@ -104,10 +108,8 @@ void NetCase::nex_output(NexusSet&out) for (size_t idx = 0 ; idx < items_.size() ; idx += 1) { // Empty statements clearly have no output. - if (items_[idx].statement == 0) - continue; + if (items_[idx].statement == 0) continue; - assert(items_[idx].statement); items_[idx].statement->nex_output(out); } @@ -115,22 +117,31 @@ void NetCase::nex_output(NexusSet&out) void NetCondit::nex_output(NexusSet&out) { - if (if_ != 0) - if_->nex_output(out); - if (else_ != 0) - else_->nex_output(out); + if (if_) if_->nex_output(out); + if (else_) else_->nex_output(out); +} + +void NetDisable::nex_output(NexusSet&) +{ } void NetDoWhile::nex_output(NexusSet&out) { - if (proc_ != 0) - proc_->nex_output(out); + if (proc_) proc_->nex_output(out); +} + +void NetEvTrig::nex_output(NexusSet&) +{ } void NetEvWait::nex_output(NexusSet&out) { - assert(statement_); - statement_->nex_output(out); + if (statement_) statement_->nex_output(out); +} + +void NetForever::nex_output(NexusSet&out) +{ + if (statement_) statement_->nex_output(out); } void NetForLoop::nex_output(NexusSet&out) @@ -138,11 +149,20 @@ void NetForLoop::nex_output(NexusSet&out) if (statement_) statement_->nex_output(out); } +void NetFree::nex_output(NexusSet&) +{ +} + void NetPDelay::nex_output(NexusSet&out) { if (statement_) statement_->nex_output(out); } +void NetRepeat::nex_output(NexusSet&out) +{ + if (statement_) statement_->nex_output(out); +} + /* * For the purposes of synthesis, system task calls have no output at * all. This is OK because most system tasks are not synthesizable in @@ -163,6 +183,5 @@ void NetUTask::nex_output(NexusSet&) void NetWhile::nex_output(NexusSet&out) { - if (proc_ != 0) - proc_->nex_output(out); + if (proc_) proc_->nex_output(out); } diff --git a/netlist.cc b/netlist.cc index 70d65031e..106bb3be7 100644 --- a/netlist.cc +++ b/netlist.cc @@ -2779,12 +2779,20 @@ static DelayType get_loop_delay_type(const NetExpr*expr, const NetProc*proc, boo break; /* We have a constant true expression so the body always runs. */ case DEFINITE_DELAY: - result = proc->delay_type(print_delay); + if (proc) { + result = proc->delay_type(print_delay); + } else { + result = NO_DELAY; + } break; /* We don't know if the body will run so reduce a DEFINITE_DELAY * to a POSSIBLE_DELAY. All other stay the same. */ case POSSIBLE_DELAY: - result = combine_delays(NO_DELAY, proc->delay_type(print_delay)); + if (proc) { + result = combine_delays(NO_DELAY, proc->delay_type(print_delay)); + } else { + result = NO_DELAY; + } break; /* This should never happen since delay_type_from_expr() only * returns three different values. */ @@ -2814,7 +2822,7 @@ DelayType NetBlock::delay_type(bool print_delay) const for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) { DelayType dt = cur->delay_type(print_delay); if (dt < result) result = dt; - if (dt == NO_DELAY) break; + if ((dt == NO_DELAY) && !print_delay) break; } // A begin or join has the maximum delay. @@ -2823,7 +2831,7 @@ DelayType NetBlock::delay_type(bool print_delay) const for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) { DelayType dt = cur->delay_type(print_delay); if (dt > result) result = dt; - if (dt == DEFINITE_DELAY) break; + if ((dt == DEFINITE_DELAY) && !print_delay) break; } } @@ -2846,6 +2854,7 @@ DelayType NetCase::delay_type(bool print_delay) const } } +// FIXME: If all the cases are covered (e.g. an enum) then this is not true. /* If we don't have a default statement we don't know for sure * that we have a delay. */ if (!def_stmt) result = combine_delays(NO_DELAY, result); @@ -2865,29 +2874,31 @@ DelayType NetCondit::delay_type(bool print_delay) const */ DelayType NetDoWhile::delay_type(bool print_delay) const { - ivl_assert(*this, proc_); - return proc_->delay_type(print_delay); + if (proc_) return proc_->delay_type(print_delay); + + return ZERO_DELAY; } DelayType NetEvWait::delay_type(bool print_delay) const { if (print_delay) { cerr << get_fileline() << ": error: an event control is not allowed " - << "in an always_comb, always_ff or always_latch process." + "in an always_comb, always_ff or always_latch process." << endl; } + return DEFINITE_DELAY; } DelayType NetForever::delay_type(bool print_delay) const { - ivl_assert(*this, statement_); - return statement_->delay_type(print_delay); + if (statement_) return statement_->delay_type(print_delay); + + return ZERO_DELAY; } DelayType NetForLoop::delay_type(bool print_delay) const { - ivl_assert(*this, statement_); return get_loop_delay_type(condition_, statement_, print_delay); } @@ -2895,28 +2906,31 @@ DelayType NetPDelay::delay_type(bool print_delay) const { if (print_delay) { cerr << get_fileline() << ": error: a blocking delay is not allowed " - << "in an always_comb, always_ff or always_latch process." + "in an always_comb, always_ff or always_latch process." << endl; } + if (expr_) { - return delay_type_from_expr(expr_); - } else { - if (delay() > 0) { - return DEFINITE_DELAY; + if (statement_) { + return combine_delays(delay_type_from_expr(expr_), + statement_->delay_type(print_delay)); } else { - if (statement_) { - return combine_delays(ZERO_DELAY, - statement_->delay_type(print_delay)); - } else { - return ZERO_DELAY; - } + return delay_type_from_expr(expr_); } } + + if (delay() > 0) return DEFINITE_DELAY; + + if (statement_) { + return combine_delays(ZERO_DELAY, + statement_->delay_type(print_delay)); + } else { + return ZERO_DELAY; + } } DelayType NetRepeat::delay_type(bool print_delay) const { - ivl_assert(*this, statement_); return get_loop_delay_type(expr_, statement_, print_delay); } @@ -2930,8 +2944,512 @@ DelayType NetUTask::delay_type(bool print_delay) const return task()->task_def()->delay_type(print_delay); } +static bool do_expr_event_match(const NetExpr*expr, const NetEvWait*evwt) +{ + // The event wait should only have a single event. + if (evwt->nevents() != 1) return false; + // The event should have a single probe. + const NetEvent* evt = evwt->event(0); + if (evt->nprobe() != 1) return false; + // The probe should be for any edge. + const NetEvProbe *prb = evt->probe(0); + if (prb->edge() != NetEvProbe::ANYEDGE) return false; + // Create a NexusSet from the event probe signals. + NexusSet *ns_evwt = new NexusSet; + for (unsigned idx =0; idx < prb->pin_count(); idx += 1) { + if (! prb->pin(idx).is_linked()) { + delete ns_evwt; + return false; + } + // Casting away const is safe since this nexus set is only being read. + ns_evwt->add(const_cast (prb->pin(idx).nexus()), + 0, prb->pin(idx).nexus()->vector_width()); + } + // Get the NexusSet for the expression + NexusSet *ns_expr = expr->nex_input(); + // Make sure the event and expression NexusSets match exactly + if (ns_evwt->size() != ns_expr->size()) { + delete ns_evwt; + delete ns_expr; + return false; + } + ns_expr->rem(*ns_evwt); + delete ns_evwt; + if (ns_expr->size() != 0) { + delete ns_expr; + return false; + } + delete ns_expr; + + return true; +} + +static bool while_is_wait(const NetExpr*expr, const NetProc*stmt) +{ + if (const NetEvWait*evwt = dynamic_cast(stmt)) { + if (evwt->statement()) return false; + const NetEBComp*cond = dynamic_cast(expr); + if (! cond) return false; + if (cond->op() != 'N') return false; + const NetEConst*cval = dynamic_cast(cond->right()); + if (! cval) return false; + const verinum val = cval->value(); + if (val.len() != 1) return false; + if (val.get(0) != verinum::V1) return false; + if (! do_expr_event_match(cond->left(), evwt)) return false; + if (evwt->get_lineno() != cond->get_lineno()) return false; + if (evwt->get_file() != cond->get_file()) return false; + return true; + } + return false; +} + DelayType NetWhile::delay_type(bool print_delay) const { - ivl_assert(*this, proc_); + // If the wait was a constant value the compiler already removed it + // so we know we can only have a possible delay. + if (while_is_wait(cond_, proc_)) { + if (print_delay) { + cerr << get_fileline() << ": error: a wait statement is " + "not allowed in an " + "always_comb, always_ff or always_latch process." + << endl; + } + return POSSIBLE_DELAY; + } return get_loop_delay_type(cond_, proc_, print_delay); } + +/* + * These are the check_synth() functions. They are used to print + * a warning if the item is not synthesizable. + */ +static const char * get_process_type_as_string(ivl_process_type_t pr_type) +{ + switch (pr_type) { + case IVL_PR_ALWAYS_COMB: + return "in an always_comb process."; + break; + case IVL_PR_ALWAYS_FF: + return "in an always_ff process."; + break; + case IVL_PR_ALWAYS_LATCH: + return "in an always_latch process."; + break; + default: + assert(0); + return 0; + } +} + +static void print_synth_warning(const NetProc *net_proc, const char *name, + ivl_process_type_t pr_type) +{ + cerr << net_proc->get_fileline() << ": warning: " << name + << " statement cannot be synthesized " + << get_process_type_as_string(pr_type) << endl; +} + +static void check_if_logic_l_value(const NetAssignBase *base, + ivl_process_type_t pr_type) +{ + if (base->l_val_count() != 1) return; + + const NetAssign_*lval = base->l_val(0); + if (! lval) return; + + NetNet*sig = lval->sig(); + if (! sig) return; + + if ((sig->data_type() != IVL_VT_BOOL) && + (sig->data_type() != IVL_VT_LOGIC)) { + cerr << base->get_fileline() << ": warning: Assinging to a " + "non-integral variable ("<< sig->name() + << ") cannot be synthesized " + << get_process_type_as_string(pr_type) << endl; + } +} + +/* By default elements can be synthesized or ignored. */ +bool NetProc::check_synth(ivl_process_type_t /* pr_type */, + const NetScope* /* scope */ ) const +{ + return false; +} + +/* By default assign elements can be synthesized. */ +bool NetAssignBase::check_synth(ivl_process_type_t /* pr_type */, + const NetScope* /* scope */ ) const +{ + return false; +} + +bool NetAssign::check_synth(ivl_process_type_t pr_type, + const NetScope* /* scope */ ) const +{ + check_if_logic_l_value(this, pr_type); + +// FIXME: Check that ff/latch only use this for internal signals. + return false; +} + +bool NetAssignNB::check_synth(ivl_process_type_t pr_type, + const NetScope* /* scope */ ) const +{ + bool result = false; + if (pr_type == IVL_PR_ALWAYS_COMB) { + cerr << get_fileline() << ": warning: A non-blocking assignment " + "should not be used in an always_comb process." << endl; + } + + if (event_) { + cerr << get_fileline() << ": error: A non-blocking assignment " + "cannot be synthesized with an event control " + << get_process_type_as_string(pr_type) << endl; + result = true; + } + + check_if_logic_l_value(this, pr_type); + + return result; +} + +bool NetBlock::check_synth(ivl_process_type_t pr_type, + const NetScope* scope) const +{ + bool result = false; + // Only a begin/end can be synthesized. + if (type() != SEQU) { + cerr << get_fileline() << ": error: A fork/"; + switch (type()) { + case PARA: + cerr << "join"; + break; + case PARA_JOIN_ANY: + cerr << "join_any"; + break; + case PARA_JOIN_NONE: + cerr << "join_none"; + break; + default: + assert(0); + } + cerr << " statement cannot be synthesized " + << get_process_type_as_string(pr_type) << endl; + result = true; + } + + const NetScope*save_scope = scope; + if (subscope()) scope = subscope(); + if (scope != save_scope) { + result |= scope->check_synth(pr_type, scope); + } + for (const NetProc*cur = proc_first(); cur; cur = proc_next(cur)) { + result |= cur->check_synth(pr_type, scope); + } + scope = save_scope; + return result; +} + +bool NetCase::check_synth(ivl_process_type_t pr_type, + const NetScope* scope) const +{ + bool result = false; + for (unsigned idx = 0; idx < nitems(); idx += 1) { + if (stat(idx)) result |= stat(idx)->check_synth(pr_type, scope); + } +// FIXME: Check for ff/latch/comb structures. + return result; +} + +bool NetCAssign::check_synth(ivl_process_type_t pr_type, + const NetScope* /* scope */ ) const +{ + print_synth_warning(this, "A procedural assign", pr_type); + return false; +} + +bool NetCondit::check_synth(ivl_process_type_t pr_type, + const NetScope* scope) const +{ + bool result = false; + if (if_) result |= if_->check_synth(pr_type, scope); + if (else_) result |= else_->check_synth(pr_type, scope); +// FIXME: Check for ff/latch/comb structures. + return result; +} + +bool NetDeassign::check_synth(ivl_process_type_t pr_type, + const NetScope* /* scope */ ) const +{ + print_synth_warning(this, "A procedural deassign", pr_type); + return false; +} + +bool NetDisable::check_synth(ivl_process_type_t pr_type, + const NetScope* scope) const +{ + while (scope) { + if (scope != target_) scope = scope->parent(); + else break; + } + + + if (! scope) { + cerr << get_fileline() << ": warning: A disable statement can " + "only be synthesized when disabling an enclosing block " + << get_process_type_as_string(pr_type) << endl; + } + return false; +} + +bool NetDoWhile::check_synth(ivl_process_type_t pr_type, + const NetScope* scope) const +{ + bool result = false; + print_synth_warning(this, "A do/while", pr_type); + if (proc_) result |= proc_->check_synth(pr_type, scope); + return result; +} + +bool NetEvTrig::check_synth(ivl_process_type_t pr_type, + const NetScope* /* scope */ ) const +{ + print_synth_warning(this, "An event trigger", pr_type); + return false; +} + +// The delay check above has already marked this as an error. +bool NetEvWait::check_synth(ivl_process_type_t pr_type, + const NetScope* scope) const +{ + bool result = false; + if (statement_) result |= statement_->check_synth(pr_type, scope); + return result; +} + +bool NetForce::check_synth(ivl_process_type_t pr_type, + const NetScope* /* scope */ ) const +{ + print_synth_warning(this, "A force", pr_type); + return false; +} + +bool NetForever::check_synth(ivl_process_type_t pr_type, + const NetScope* scope) const +{ + bool result = false; + print_synth_warning(this, "A forever", pr_type); + if (statement_) result |= statement_->check_synth(pr_type, scope); + return result; +} + +/* + * A bunch of private routines to verify that a for loop has the correct + * structure for synthesis. + */ +static void print_for_idx_warning(const NetProc*proc, const char*check, + ivl_process_type_t pr_type, NetNet*idx) +{ + cerr << proc->get_fileline() << ": warning: A for statement must use " + "the index (" << idx->name() << ") in the " << check + << " expression to be synthesized " + << get_process_type_as_string(pr_type) << endl; +} + +static void check_for_const_synth(const NetExpr*expr, const NetProc*proc, + const char*str, ivl_process_type_t pr_type) +{ + if (! dynamic_cast(expr)) { + cerr << proc-> get_fileline() << ": warning: A for " + "statement must " << str + << " value to be synthesized " + << get_process_type_as_string(pr_type) << endl; + } +} + +static void check_for_bin_synth(const NetExpr*left,const NetExpr*right, + const char*str, const char*check, + const NetProc*proc, + ivl_process_type_t pr_type, NetNet*index) +{ + const NetESignal*lsig = dynamic_cast(left); + const NetESignal*rsig = dynamic_cast(right); + + if (lsig && (lsig->sig() == index)) { + check_for_const_synth(right, proc, str, pr_type); + } else if (rsig && (rsig->sig() == index)) { + check_for_const_synth(left, proc, str, pr_type); + } else { + print_for_idx_warning(proc, check, pr_type, index); + } +} + +static void print_for_step_warning(const NetProc*proc, + ivl_process_type_t pr_type) +{ + cerr << proc->get_fileline() << ": warning: A for statement step must " + "be a simple assignment statement to be synthesized " + << get_process_type_as_string(pr_type) << endl; +} + +static void print_for_step_warning(const NetProc*proc, + ivl_process_type_t pr_type, NetNet*idx) +{ + cerr << proc->get_fileline() << ": warning: A for statement step must " + "be an assignment to the index variable (" + << idx->name() << ") to be synthesized " + << get_process_type_as_string(pr_type) << endl; +} + +static void check_for_bstep_synth(const NetExpr*expr, const NetProc*proc, + ivl_process_type_t pr_type, NetNet*index) +{ + if (const NetECast*tmp = dynamic_cast(expr)) { + expr = tmp->expr(); + } + + if (const NetEBAdd*tmp = dynamic_cast(expr)) { + check_for_bin_synth(tmp->left(), tmp->right(), + "change by a constant", "step", proc, pr_type, + index); + } else { + cerr << proc->get_fileline() << ": warning: A for statement " + "step must be a simple binary +/- " + "to be synthesized " + << get_process_type_as_string(pr_type) << endl; + } +} + +static void check_for_step_synth(const NetAssign*assign, const NetProc*proc, + ivl_process_type_t pr_type, NetNet*index) +{ + if (assign->l_val_count() != 1) { + print_for_step_warning(proc, pr_type); + } else if (assign->l_val(0)->sig() != index) { + print_for_step_warning(proc, pr_type, index); + } else { + switch (assign->assign_operator()) { + case '+': + case '-': + check_for_const_synth(assign->rval(), proc, + "have a constant step", pr_type); + break; + case 0: + check_for_bstep_synth(assign->rval(), proc, pr_type, index); + break; + default: + cerr << proc->get_fileline() << ": warning: A for statement " + "step does not support operator '" + << assign->assign_operator() + << "' it must be +/- to be synthesized " + << get_process_type_as_string(pr_type) << endl; + break; + } + } +} + +bool NetForLoop::check_synth(ivl_process_type_t pr_type, + const NetScope* scope) const +{ + bool result = false; + +// FIXME: What about an enum (NetEConstEnum)? + if (! dynamic_cast(init_expr_)) { + cerr << get_fileline() << ": warning: A for statement must " + "have a constant initial value to be synthesized " + << get_process_type_as_string(pr_type) << endl; + } + +// FIXME: Do the following also need to be supported in the condition? +// It would seem like they are hard to use to find the bounds. +// From NetEBinary +// What about NetEBits sig & constant, etc. +// From NetEUnary +// What about NetEUBits ! sig or ! (sig == constat) +// What about NetEUReduce &signal + if (const NetESignal*tmp = dynamic_cast(condition_)) { + if (tmp->sig() != index_) { + print_for_idx_warning(this, "condition", pr_type, index_); + } + } else if (const NetEBComp*cmp = dynamic_cast(condition_)) { + check_for_bin_synth(cmp->left(), cmp->right(), + "compare against a constant", "condition", + this, pr_type, index_); + } else { + print_for_idx_warning(this, "condition", pr_type, index_); + } + + if (const NetAssign*tmp = dynamic_cast(step_statement_)) { + check_for_step_synth(tmp, this, pr_type, index_); + } else { + print_for_step_warning(this, pr_type); + } + + if (statement_) result |= statement_->check_synth(pr_type, scope); + return result; +} + +// The delay check above has already marked this as an error. +bool NetPDelay::check_synth(ivl_process_type_t /* pr_type */, + const NetScope* /* scope */ ) const +{ + return false; +} + +bool NetRelease::check_synth(ivl_process_type_t pr_type, + const NetScope* /* scope */ ) const +{ + print_synth_warning(this, "A release", pr_type); + return false; +} + +bool NetRepeat::check_synth(ivl_process_type_t pr_type, + const NetScope* scope) const +{ + bool result = false; + print_synth_warning(this, "A repeat", pr_type); + if (statement_) result |= statement_->check_synth(pr_type, scope); + return result; +} + +bool NetScope::check_synth(ivl_process_type_t pr_type, + const NetScope* /* scope */) const +{ + bool result = false; + // Skip local events/signals + for (NetEvent*cur = events_ ; cur ; cur = cur->snext_) { + if (cur->local_flag()) continue; + cerr << cur->get_fileline() << ": warning: An event (" + << cur->name() << ") cannot be synthesized " + << get_process_type_as_string(pr_type) << endl; + } + for (signals_map_iter_t cur = signals_map_.begin(); + cur != signals_map_.end() ; ++ cur) { + const NetNet*sig = cur->second; + if ((sig->data_type() != IVL_VT_BOOL) && + (sig->data_type() != IVL_VT_LOGIC)) { + cerr << sig->get_fileline() << ": warning: A non-integral " + "variable (" << sig->name() << ") cannot be " + "synthesized " + << get_process_type_as_string(pr_type) << endl; + } + } + return result; +} + +// FIXME: User task and function calls still need to be checked. +// : System task enables should be ignored and constant system functions +// : should also be okay. Non-constant system functions are an error. + +bool NetWhile::check_synth(ivl_process_type_t pr_type, + const NetScope* scope) const +{ + bool result = false; + // A wait is already maked as an error in the delay check above. + if (! while_is_wait(cond_, proc_)) { + print_synth_warning(this, "A while", pr_type); + if (proc_) result |= proc_->check_synth(pr_type, scope); + } + return result; +} diff --git a/netlist.h b/netlist.h index 2f431269e..8b129de54 100644 --- a/netlist.h +++ b/netlist.h @@ -1158,6 +1158,9 @@ class NetScope : public Definitions, public Attrib { perm_string local_symbol(); void dump(ostream&) const; + // Check to see if the scope has items that are not allowed + // in an always_comb/ff/latch process. + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; void emit_scope(struct target_t*tgt) const; bool emit_defs(struct target_t*tgt) const; @@ -2716,6 +2719,8 @@ class NetProc : public virtual LineInfo { // Recursively checks to see if there is delay in this element. virtual DelayType delay_type(bool print_delay=false) const; + // Check to see if the item is synthesizable. + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; protected: bool synth_async_block_substatement_(Design*des, NetScope*scope, @@ -2743,6 +2748,8 @@ class NetAlloc : public NetProc { const NetScope* scope() const; + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -2913,6 +2920,7 @@ class NetAssignBase : public NetProc { // This dumps all the lval structures. void dump_lval(ostream&) const; virtual void dump(ostream&, unsigned ind) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; private: NetAssign_*lval_; @@ -2934,6 +2942,7 @@ class NetAssign : public NetAssignBase { virtual bool emit_proc(struct target_t*) const; virtual int match_proc(struct proc_match_t*); virtual void dump(ostream&, unsigned ind) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; virtual bool evaluate_function(const LineInfo&loc, map&ctx) const; @@ -2956,6 +2965,7 @@ class NetAssignNB : public NetAssignBase { virtual bool emit_proc(struct target_t*) const; virtual int match_proc(struct proc_match_t*); virtual void dump(ostream&, unsigned ind) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; unsigned nevents() const; const NetEvent*event(unsigned) const; @@ -3019,6 +3029,7 @@ class NetBlock : public NetProc { virtual int match_proc(struct proc_match_t*); virtual void dump(ostream&, unsigned ind) const; virtual DelayType delay_type(bool print_delay=false) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; private: const Type type_; @@ -3066,6 +3077,7 @@ class NetCase : public NetProc { virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; virtual DelayType delay_type(bool print_delay=false) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; virtual bool evaluate_function(const LineInfo&loc, map&ctx) const; @@ -3102,9 +3114,9 @@ class NetCAssign : public NetAssignBase { explicit NetCAssign(NetAssign_*lv, NetExpr*rv); ~NetCAssign(); - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; virtual void dump(ostream&, unsigned ind) const; virtual bool emit_proc(struct target_t*) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; private: // not implemented NetCAssign(const NetCAssign&); @@ -3156,6 +3168,7 @@ class NetCondit : public NetProc { virtual int match_proc(struct proc_match_t*); virtual void dump(ostream&, unsigned ind) const; virtual DelayType delay_type(bool print_delay=false) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; virtual bool evaluate_function(const LineInfo&loc, map&ctx) const; @@ -3201,6 +3214,7 @@ class NetDeassign : public NetAssignBase { virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; private: // not implemented NetDeassign(const NetDeassign&); @@ -3224,8 +3238,11 @@ class NetDisable : public NetProc { const NetScope*target() const; + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; virtual bool evaluate_function(const LineInfo&loc, map&ctx) const; @@ -3257,6 +3274,7 @@ class NetDoWhile : public NetProc { virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; virtual DelayType delay_type(bool print_delay=false) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; virtual bool evaluate_function(const LineInfo&loc, map&ctx) const; @@ -3313,6 +3331,9 @@ class NetEvent : public LineInfo { perm_string name() const; + bool local_flag() const { return local_flag_; } + void local_flag(bool f) { local_flag_ = f; } + // Get information about probes connected to me. unsigned nprobe() const; NetEvProbe* probe(unsigned); @@ -3344,6 +3365,7 @@ class NetEvent : public LineInfo { private: perm_string name_; + bool local_flag_; // The NetScope class uses these to list the events. NetScope*scope_; @@ -3381,8 +3403,11 @@ class NetEvTrig : public NetProc { const NetEvent*event() const; + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; private: NetEvent*event_; @@ -3440,6 +3465,7 @@ class NetEvWait : public NetProc { // This will ignore any statement. virtual void dump_inline(ostream&) const; virtual DelayType delay_type(bool print_delay=false) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; private: NetProc*statement_; @@ -3488,10 +3514,9 @@ class NetForce : public NetAssignBase { explicit NetForce(NetAssign_*l, NetExpr*r); ~NetForce(); - virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; - virtual void dump(ostream&, unsigned ind) const; virtual bool emit_proc(struct target_t*) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; }; /* @@ -3507,9 +3532,11 @@ class NetForever : public NetProc { void emit_recurse(struct target_t*) const; virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; virtual DelayType delay_type(bool print_delay=false) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; virtual bool evaluate_function(const LineInfo&loc, map&ctx) const; @@ -3533,6 +3560,7 @@ class NetForLoop : public NetProc { virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; virtual DelayType delay_type(bool print_delay=false) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; virtual bool evaluate_function(const LineInfo&loc, map&ctx) const; @@ -3565,6 +3593,8 @@ class NetFree : public NetProc { const NetScope* scope() const; + virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; @@ -3634,6 +3664,7 @@ class NetPDelay : public NetProc { virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; virtual DelayType delay_type(bool print_delay=false) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; bool emit_proc_recurse(struct target_t*) const; @@ -3656,9 +3687,11 @@ class NetRepeat : public NetProc { void emit_recurse(struct target_t*) const; virtual NexusSet* nex_input(bool rem_out = true, bool search_funcs = false) const; + virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; virtual DelayType delay_type(bool print_delay=false) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; virtual bool evaluate_function(const LineInfo&loc, map&ctx) const; @@ -3681,6 +3714,7 @@ class NetRelease : public NetAssignBase { virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; private: }; @@ -3882,11 +3916,12 @@ class NetWhile : public NetProc { virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; virtual DelayType delay_type(bool print_delay=false) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; virtual bool evaluate_function(const LineInfo&loc, map&ctx) const; private: - NetExpr* cond_; + NetExpr*cond_; NetProc*proc_; }; @@ -4954,6 +4989,7 @@ class Design { void add_process(NetAnalogTop*); void delete_process(NetProcTop*); bool check_proc_delay() const; + bool check_proc_synth() const; NetNet* find_discipline_reference(ivl_discipline_t dis, NetScope*scope); From 7d11fa662e10210a042cc5b898c81607bd6b8624 Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 27 Dec 2017 14:49:15 -0800 Subject: [PATCH 545/595] Fix space issues --- netlist.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/netlist.cc b/netlist.cc index 106bb3be7..985dfb73b 100644 --- a/netlist.cc +++ b/netlist.cc @@ -2965,9 +2965,9 @@ static bool do_expr_event_match(const NetExpr*expr, const NetEvWait*evwt) ns_evwt->add(const_cast (prb->pin(idx).nexus()), 0, prb->pin(idx).nexus()->vector_width()); } - // Get the NexusSet for the expression + // Get the NexusSet for the expression. NexusSet *ns_expr = expr->nex_input(); - // Make sure the event and expression NexusSets match exactly + // Make sure the event and expression NexusSets match exactly. if (ns_evwt->size() != ns_expr->size()) { delete ns_evwt; delete ns_expr; From 932241ee8767e3b815c99b3078ae261492d8fd32 Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 27 Dec 2017 23:07:29 -0800 Subject: [PATCH 546/595] Check system/user tasks for always_comb/ff/latch synth. --- netlist.cc | 42 +++++++++++++++++++++++++++++++++++++++--- netlist.h | 3 +++ 2 files changed, 42 insertions(+), 3 deletions(-) diff --git a/netlist.cc b/netlist.cc index 985dfb73b..11c2af223 100644 --- a/netlist.cc +++ b/netlist.cc @@ -24,6 +24,7 @@ # include # include # include +# include # include "compiler.h" # include "netlist.h" # include "netmisc.h" @@ -3077,6 +3078,10 @@ bool NetProc::check_synth(ivl_process_type_t /* pr_type */, return false; } +// FIXME: User function calls still need to be checked (NetEUFunc). +// : Non-constant system functions need a warning (NetESFunc). +// : Constant functions should already be elaborated. + /* By default assign elements can be synthesized. */ bool NetAssignBase::check_synth(ivl_process_type_t /* pr_type */, const NetScope* /* scope */ ) const @@ -3438,9 +3443,40 @@ bool NetScope::check_synth(ivl_process_type_t pr_type, return result; } -// FIXME: User task and function calls still need to be checked. -// : System task enables should be ignored and constant system functions -// : should also be okay. Non-constant system functions are an error. +bool NetSTask::check_synth(ivl_process_type_t pr_type, + const NetScope* /* scope */) const +{ + if (strcmp(name(), "$ivl_darray_method$delete") == 0) { + cerr << get_fileline() << ": warning: Dynamic array " + "delete method cannot be synthesized " + << get_process_type_as_string(pr_type) << endl; + } else { + cerr << get_fileline() << ": warning: System task (" + << name() << ") cannot be synthesized " + << get_process_type_as_string(pr_type) << endl; + } + return false; +} + +bool NetTaskDef::check_synth(ivl_process_type_t pr_type, + const NetScope* scope) const +{ + const NetScope *tscope = this->scope(); + if (! tscope->is_auto()) { + cerr << tscope->get_def_file() << ":" + << tscope->get_def_lineno() + << ": warning: user task (" << tscope->basename() + << ") must be automatic to be synthesized " + << get_process_type_as_string(pr_type) << endl; + } + return proc_->check_synth(pr_type, scope); +} + +bool NetUTask::check_synth(ivl_process_type_t pr_type, + const NetScope* scope) const +{ + return task()->task_def()->check_synth(pr_type, scope); +} bool NetWhile::check_synth(ivl_process_type_t pr_type, const NetScope* scope) const diff --git a/netlist.h b/netlist.h index 8b129de54..4ef652339 100644 --- a/netlist.h +++ b/netlist.h @@ -3744,6 +3744,7 @@ class NetSTask : public NetProc { virtual void nex_output(NexusSet&); virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; virtual bool evaluate_function(const LineInfo&loc, map&ctx) const; @@ -3774,6 +3775,7 @@ class NetTaskDef : public NetBaseDef { void dump(ostream&, unsigned) const; DelayType delay_type(bool print_delay=false) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; private: // not implemented NetTaskDef(const NetTaskDef&); @@ -3891,6 +3893,7 @@ class NetUTask : public NetProc { virtual bool emit_proc(struct target_t*) const; virtual void dump(ostream&, unsigned ind) const; virtual DelayType delay_type(bool print_delay=false) const; + virtual bool check_synth(ivl_process_type_t pr_type, const NetScope*scope) const; private: NetScope*task_; From ca01385797875cb339fed5ff32b68111195a19e4 Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 28 Dec 2017 08:49:12 -0800 Subject: [PATCH 547/595] The synth check needs to check the task scope --- netlist.cc | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/netlist.cc b/netlist.cc index 11c2af223..803316a2a 100644 --- a/netlist.cc +++ b/netlist.cc @@ -2937,7 +2937,11 @@ DelayType NetRepeat::delay_type(bool print_delay) const DelayType NetTaskDef::delay_type(bool print_delay) const { - return proc_->delay_type(print_delay); + if (proc_) { + return proc_->delay_type(print_delay); + } else { + return NO_DELAY; + } } DelayType NetUTask::delay_type(bool print_delay) const @@ -3459,9 +3463,11 @@ bool NetSTask::check_synth(ivl_process_type_t pr_type, } bool NetTaskDef::check_synth(ivl_process_type_t pr_type, - const NetScope* scope) const + const NetScope* /* scope */) const { + bool result = false; const NetScope *tscope = this->scope(); + result |= tscope->check_synth(pr_type, tscope); if (! tscope->is_auto()) { cerr << tscope->get_def_file() << ":" << tscope->get_def_lineno() @@ -3469,7 +3475,8 @@ bool NetTaskDef::check_synth(ivl_process_type_t pr_type, << ") must be automatic to be synthesized " << get_process_type_as_string(pr_type) << endl; } - return proc_->check_synth(pr_type, scope); + if (proc_) result |= proc_->check_synth(pr_type, tscope); + return result; } bool NetUTask::check_synth(ivl_process_type_t pr_type, From 24a4ec3bb26c66d8f08b08d13b25d483ea9abfe1 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 1 Jan 2018 21:17:45 -0800 Subject: [PATCH 548/595] Hide the always_comb/latch TO event by not attaching it to a scope. --- vvp/compile.cc | 6 +++--- vvp/compile.h | 4 ++-- vvp/event.cc | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/vvp/compile.cc b/vvp/compile.cc index 0714fe5eb..c0792191d 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2018 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 @@ -495,8 +495,8 @@ bool vvp_net_resolv_list_s::resolve(bool mes) // the compiler output instead of implicitly in this code. assert(! vpip_peek_current_scope()->is_automatic()); t0_trigger_generated = true; - // Create an event with no name for the T0 trigger - compile_named_event(strdup(label()), strcpy(new char [1],"")); + // Create a local event with no name for the T0 trigger + compile_named_event(strdup(label()), strcpy(new char [1],""), true); tmp = vvp_net_lookup(label()); assert(tmp); tmp->link(port); diff --git a/vvp/compile.h b/vvp/compile.h index b49a6dea4..6ef0b122d 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -1,7 +1,7 @@ #ifndef IVL_compile_H #define IVL_compile_H /* - * Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2018 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 @@ -418,7 +418,7 @@ extern void compile_ufunc_vec4(char*label, char*code, unsigned wid, */ extern void compile_event(char*label, char*type, unsigned argc, struct symb_s*argv); -extern void compile_named_event(char*label, char*type); +extern void compile_named_event(char*label, char*type, bool local_flag=false); /* diff --git a/vvp/event.cc b/vvp/event.cc index 64504d9cc..6c6c7fe00 100644 --- a/vvp/event.cc +++ b/vvp/event.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2004-2018 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 @@ -829,7 +829,7 @@ static void compile_event_or(char*label, unsigned argc, struct symb_s*argv) * inputs, it is only accessed by behavioral trigger statements, which * in vvp are %set instructions. */ -void compile_named_event(char*label, char*name) +void compile_named_event(char*label, char*name, bool local_flag) { vvp_net_t*ptr = new vvp_net_t; @@ -842,7 +842,7 @@ void compile_named_event(char*label, char*name) } define_functor_symbol(label, ptr); compile_vpi_symbol(label, obj); - vpip_attach_to_current_scope(obj); + if (! local_flag) vpip_attach_to_current_scope(obj); free(label); delete[] name; From e7a9662b3d6da9fecef1bd2e6f56282621ba85e8 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 1 Jan 2018 21:34:37 -0800 Subject: [PATCH 549/595] A #0 is not allowed in a final block --- elaborate.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/elaborate.cc b/elaborate.cc index f450a42ff..87a85b059 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2018 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -6183,7 +6183,7 @@ bool Design::check_proc_delay() const if (pr->type() == IVL_PR_FINAL) { DelayType dly_type = pr->statement()->delay_type(); - if (dly_type != NO_DELAY && dly_type != ZERO_DELAY) { + if (dly_type != NO_DELAY) { cerr << pr->get_fileline() << ": error: final" << " statement contains a delay." << endl; result = true; From 0f95770418d2a0c3a390db81adae282c7df039b9 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 18 Feb 2018 12:53:29 +0000 Subject: [PATCH 550/595] Include compilation units in pform dump. --- main.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/main.cc b/main.cc index cb087239e..975e5abf9 100644 --- a/main.cc +++ b/main.cc @@ -1102,6 +1102,11 @@ int main(int argc, char*argv[]) ; cur != disciplines.end() ; ++ cur ) { pform_dump(out, (*cur).second); } + out << "PFORM DUMP COMPILATION UNITS:" << endl; + for (vector::iterator pac = pform_units.begin() + ; pac != pform_units.end() ; ++ pac) { + pform_dump(out, *pac); + } out << "PFORM DUMP PACKAGES:" << endl; for (map::iterator pac = pform_packages.begin() ; pac != pform_packages.end() ; ++ pac) { From caf83b02c1d65062003a1188b09936bb9b352056 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 18 Feb 2018 14:09:03 +0000 Subject: [PATCH 551/595] Enable variable declarations/initialisations in the compilation unit scope. --- elaborate.cc | 4 ++++ pform.cc | 21 ++++++++++++++------- pform_dump.cc | 2 ++ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/elaborate.cc b/elaborate.cc index 87a85b059..ffd9b2d34 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -5684,6 +5684,10 @@ bool PPackage::elaborate(Design*des, NetScope*scope) const // Elaborate class definitions. elaborate_classes(des, scope, classes); + // Elaborate the variable initialization statements, making a + // single initial process out of them. + result_flag &= elaborate_var_inits_(des, scope); + return result_flag; } diff --git a/pform.cc b/pform.cc index 189528985..f16a91c74 100644 --- a/pform.cc +++ b/pform.cc @@ -2682,7 +2682,8 @@ void pform_makewire(const vlltype&li, * net_decl_assign_t argument. */ void pform_makewire(const struct vlltype&li, - std::list*, str_pair_t , + std::list*delay, + str_pair_t str, std::list*assign_list, NetNet::Type type, data_type_t*data_type) @@ -2691,10 +2692,6 @@ void pform_makewire(const struct vlltype&li, VLerror(li, "error: variable declarations must be contained within a module."); return; } - if (is_compilation_unit(lexical_scope)) { - VLerror(li, "sorry: variable declarations in the $root scope are not yet supported."); - return; - } list*names = new list; @@ -2709,8 +2706,18 @@ void pform_makewire(const struct vlltype&li, while (! assign_list->empty()) { decl_assignment_t*first = assign_list->front(); assign_list->pop_front(); - // For now, do not handle assignment expressions. - assert(! first->expr.get()); + if (PExpr*expr = first->expr.release()) { + if (type == NetNet::REG || type == NetNet::IMPLICIT_REG) { + pform_make_var_init(li, first->name, expr); + } else { + PWire*cur = pform_get_wire_in_scope(first->name); + assert(cur); + PEIdent*lval = new PEIdent(first->name); + FILE_NAME(lval, li.text, li.first_line); + PGAssign*ass = pform_make_pgassign(lval, expr, delay, str); + FILE_NAME(ass, li.text, li.first_line); + } + } delete first; } } diff --git a/pform_dump.cc b/pform_dump.cc index b04f348a6..c0f329f86 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -1720,8 +1720,10 @@ void PPackage::pform_dump(std::ostream&out) const dump_localparams_(out, 4); dump_parameters_(out, 4); dump_enumerations_(out, 4); + dump_wires_(out, 4); dump_tasks_(out, 4); dump_funcs_(out, 4); + dump_var_inits_(out, 4); out << "endpackage" << endl; } From 2a21fe77ac2f6ee4dbbfcc78c2a8641e986f070b Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 18 Feb 2018 17:51:56 +0000 Subject: [PATCH 552/595] Output an error message when a SV variable declaration reuses a name. Assertion failures are not the right way to handle user code errors. --- pform.cc | 44 ++++++++++++++++++++++++++++---------------- pform.h | 12 ++++++++---- pform_class_type.cc | 8 ++++---- pform_string_type.cc | 9 ++++----- pform_struct_type.cc | 14 +++++++------- 5 files changed, 51 insertions(+), 36 deletions(-) diff --git a/pform.cc b/pform.cc index f16a91c74..ce036af83 100644 --- a/pform.cc +++ b/pform.cc @@ -737,16 +737,28 @@ static void pform_put_enum_type_in_scope(enum_type_t*enum_set) lexical_scope->enum_sets.insert(enum_set); } -PWire*pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetNet::PortType port_type, ivl_variable_type_t vt_type) +PWire*pform_get_make_wire_in_scope(const struct vlltype&li, perm_string name, + NetNet::Type net_type, NetNet::PortType port_type, + ivl_variable_type_t vt_type) { PWire*cur = pform_get_wire_in_scope(name); + + // If the wire already exists and is fully defined, this + // must be a redeclaration. Start again with a new wire. + if (cur && cur->get_data_type() != IVL_VT_NO_TYPE) { + LineInfo tloc; + FILE_NAME(&tloc, li); + cerr << tloc.get_fileline() << ": error: duplicate declaration " + "for net or variable '" << name << "'." << endl; + error_count += 1; + delete cur; + cur = 0; + } + if (cur == 0) { cur = new PWire(name, net_type, port_type, vt_type); pform_put_wire_in_scope(name, cur); } else { - // If this is a duplicate wire, the data type has already - // been set, then return NULL. - if (cur->get_data_type() != IVL_VT_NO_TYPE) return 0; bool rc = cur->set_wire_type(net_type); assert(rc); rc = cur->set_data_type(vt_type); @@ -3377,9 +3389,9 @@ void pform_set_port_type(const struct vlltype&li, delete attr; } -static void pform_set_integer_2atom(uint64_t width, bool signed_flag, perm_string name, NetNet::Type net_type, list*attr) +static void pform_set_integer_2atom(const struct vlltype&li, uint64_t width, bool signed_flag, perm_string name, NetNet::Type net_type, list*attr) { - PWire*cur = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, IVL_VT_BOOL); + PWire*cur = pform_get_make_wire_in_scope(li, name, net_type, NetNet::NOT_A_PORT, IVL_VT_BOOL); assert(cur); cur->set_signed(signed_flag); @@ -3393,12 +3405,12 @@ static void pform_set_integer_2atom(uint64_t width, bool signed_flag, perm_strin pform_bind_attributes(cur->attributes, attr, true); } -static void pform_set_integer_2atom(uint64_t width, bool signed_flag, list*names, NetNet::Type net_type, list*attr) +static void pform_set_integer_2atom(const struct vlltype&li, uint64_t width, bool signed_flag, list*names, NetNet::Type net_type, list*attr) { for (list::iterator cur = names->begin() ; cur != names->end() ; ++ cur ) { perm_string txt = *cur; - pform_set_integer_2atom(width, signed_flag, txt, net_type, attr); + pform_set_integer_2atom(li, width, signed_flag, txt, net_type, attr); } } @@ -3409,7 +3421,7 @@ template static void pform_set2_data_type(const struct vlltype&li, T*d VLerror(li, "Compound type is not PACKED in this context."); } - PWire*net = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, base_type); + PWire*net = pform_get_make_wire_in_scope(li, name, net_type, NetNet::NOT_A_PORT, base_type); assert(net); net->set_data_type(data_type); pform_bind_attributes(net->attributes, attr, true); @@ -3423,11 +3435,11 @@ template static void pform_set2_data_type(const struct vlltype&li, T*d } } -static void pform_set_enum(enum_type_t*enum_type, +static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, perm_string name, NetNet::Type net_type, std::list*attr) { - PWire*cur = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, enum_type->base_type); + PWire*cur = pform_get_make_wire_in_scope(li, name, net_type, NetNet::NOT_A_PORT, enum_type->base_type); assert(cur); cur->set_signed(enum_type->signed_flag); @@ -3466,7 +3478,7 @@ static void pform_set_enum(const struct vlltype&li, enum_type_t*enum_type, for (list::iterator cur = names->begin() ; cur != names->end() ; ++ cur) { perm_string txt = *cur; - pform_set_enum(enum_type, txt, net_type, attr); + pform_set_enum(li, enum_type, txt, net_type, attr); } } @@ -3490,11 +3502,11 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list (data_type)) { - pform_set_integer_2atom(atom2_type->type_code, atom2_type->signed_flag, names, net_type, attr); + pform_set_integer_2atom(li, atom2_type->type_code, atom2_type->signed_flag, names, net_type, attr); } else if (struct_type_t*struct_type = dynamic_cast (data_type)) { - pform_set_struct_type(struct_type, names, net_type, attr); + pform_set_struct_type(li, struct_type, names, net_type, attr); } else if (enum_type_t*enum_type = dynamic_cast (data_type)) { @@ -3515,7 +3527,7 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list (data_type)) { - pform_set_class_type(class_type, names, net_type, attr); + pform_set_class_type(li, class_type, names, net_type, attr); } else if (parray_type_t*array_type = dynamic_cast (data_type)) { @@ -3523,7 +3535,7 @@ void pform_set_data_type(const struct vlltype&li, data_type_t*data_type, list (data_type)) { - pform_set_string_type(string_type, names, net_type, attr); + pform_set_string_type(li, string_type, names, net_type, attr); } else { VLerror(li, "internal error: Unexpected data_type."); diff --git a/pform.h b/pform.h index 7157f7c75..2b9c04f23 100644 --- a/pform.h +++ b/pform.h @@ -147,7 +147,11 @@ extern bool pform_in_interface(void); */ extern PWire* pform_get_wire_in_scope(perm_string name); -extern PWire* pform_get_make_wire_in_scope(perm_string name, NetNet::Type net_type, NetNet::PortType port_type, ivl_variable_type_t vt_type); +extern PWire* pform_get_make_wire_in_scope(const struct vlltype&li, + perm_string name, + NetNet::Type net_type, + NetNet::PortType port_type, + ivl_variable_type_t vt_type); /* * The parser uses startmodule and endmodule together to build up a @@ -386,11 +390,11 @@ extern void pform_set_reg_idx(perm_string name, extern void pform_set_data_type(const struct vlltype&li, data_type_t*, list*names, NetNet::Type net_type, list*attr); -extern void pform_set_struct_type(struct_type_t*struct_type, std::list*names, NetNet::Type net_type, std::list*attr); +extern void pform_set_struct_type(const struct vlltype&li, struct_type_t*struct_type, std::list*names, NetNet::Type net_type, std::list*attr); -extern void pform_set_string_type(const string_type_t*string_type, std::list*names, NetNet::Type net_type, std::list*attr); +extern void pform_set_string_type(const struct vlltype&li, const string_type_t*string_type, std::list*names, NetNet::Type net_type, std::list*attr); -extern void pform_set_class_type(class_type_t*class_type, std::list*names, NetNet::Type net_type, std::list*addr); +extern void pform_set_class_type(const struct vlltype&li, class_type_t*class_type, std::list*names, NetNet::Type net_type, std::list*addr); /* pform_set_attrib and pform_set_type_attrib exist to support the diff --git a/pform_class_type.cc b/pform_class_type.cc index ec2f99de4..9c1b7354e 100644 --- a/pform_class_type.cc +++ b/pform_class_type.cc @@ -22,18 +22,18 @@ # include "parse_misc.h" # include "ivl_assert.h" -static void pform_set_class_type(class_type_t*class_type, perm_string name, NetNet::Type net_type, list*attr) +static void pform_set_class_type(const struct vlltype&li, class_type_t*class_type, perm_string name, NetNet::Type net_type, list*attr) { - PWire*net = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, IVL_VT_CLASS); + PWire*net = pform_get_make_wire_in_scope(li, name, net_type, NetNet::NOT_A_PORT, IVL_VT_CLASS); assert(net); net->set_data_type(class_type); pform_bind_attributes(net->attributes, attr, true); } -void pform_set_class_type(class_type_t*class_type, list*names, NetNet::Type net_type, list*attr) +void pform_set_class_type(const struct vlltype&li, class_type_t*class_type, list*names, NetNet::Type net_type, list*attr) { for (list::iterator cur = names->begin() ; cur != names->end() ; ++ cur) { - pform_set_class_type(class_type, *cur, net_type, attr); + pform_set_class_type(li, class_type, *cur, net_type, attr); } } diff --git a/pform_string_type.cc b/pform_string_type.cc index 50a7f4fce..9d1ec73bc 100644 --- a/pform_string_type.cc +++ b/pform_string_type.cc @@ -21,18 +21,17 @@ # include "parse_misc.h" # include "ivl_assert.h" -static void pform_set_string_type(const string_type_t*, perm_string name, NetNet::Type net_type, list*attr) +static void pform_set_string_type(const struct vlltype&li, const string_type_t*, perm_string name, NetNet::Type net_type, list*attr) { - PWire*net = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, IVL_VT_STRING); + PWire*net = pform_get_make_wire_in_scope(li, name, net_type, NetNet::NOT_A_PORT, IVL_VT_STRING); assert(net); pform_bind_attributes(net->attributes, attr, true); } -void pform_set_string_type(const string_type_t*string_type, list*names, NetNet::Type net_type, list*attr) +void pform_set_string_type(const struct vlltype&li, const string_type_t*string_type, list*names, NetNet::Type net_type, list*attr) { for (list::iterator cur = names->begin() ; cur != names->end() ; ++ cur) { - pform_set_string_type(string_type, *cur, net_type, attr); + pform_set_string_type(li, string_type, *cur, net_type, attr); } } - diff --git a/pform_struct_type.cc b/pform_struct_type.cc index 433e66a91..d4ef9e7c9 100644 --- a/pform_struct_type.cc +++ b/pform_struct_type.cc @@ -62,20 +62,20 @@ ivl_variable_type_t struct_type_t::figure_packed_base_type(void) const * out the base type of the packed variable. Elaboration, later on, * well figure out the rest. */ -static void pform_set_packed_struct(struct_type_t*struct_type, perm_string name, NetNet::Type net_type, list*attr) +static void pform_set_packed_struct(const struct vlltype&li, struct_type_t*struct_type, perm_string name, NetNet::Type net_type, list*attr) { ivl_variable_type_t base_type = struct_type->figure_packed_base_type(); - PWire*net = pform_get_make_wire_in_scope(name, net_type, NetNet::NOT_A_PORT, base_type); + PWire*net = pform_get_make_wire_in_scope(li, name, net_type, NetNet::NOT_A_PORT, base_type); assert(net); net->set_data_type(struct_type); pform_bind_attributes(net->attributes, attr, true); } -static void pform_set_struct_type(struct_type_t*struct_type, perm_string name, NetNet::Type net_type, list*attr) +static void pform_set_struct_type(const struct vlltype&li, struct_type_t*struct_type, perm_string name, NetNet::Type net_type, list*attr) { if (struct_type->packed_flag) { - pform_set_packed_struct(struct_type, name, net_type, attr); + pform_set_packed_struct(li, struct_type, name, net_type, attr); return; } @@ -83,11 +83,11 @@ static void pform_set_struct_type(struct_type_t*struct_type, perm_string name, N // a "sorry" message, so no need to do anything here. } -void pform_set_struct_type(struct_type_t*struct_type, list*names, NetNet::Type net_type, list*attr) +void pform_set_struct_type(const struct vlltype&li, struct_type_t*struct_type, list*names, NetNet::Type net_type, list*attr) { for (list::iterator cur = names->begin() ; cur != names->end() ; ++ cur) { - pform_set_struct_type(struct_type, *cur, net_type, attr); + pform_set_struct_type(li, struct_type, *cur, net_type, attr); } } @@ -99,7 +99,7 @@ static void pform_makewire(const struct vlltype&li, { ivl_variable_type_t base_type = struct_type->figure_packed_base_type(); - PWire*cur = pform_get_make_wire_in_scope(name, NetNet::WIRE, ptype, base_type); + PWire*cur = pform_get_make_wire_in_scope(li, name, NetNet::WIRE, ptype, base_type); assert(cur); FILE_NAME(cur, li); cur->set_data_type(struct_type); From f8a2a4816c1215e14d51208183664afd5cbb6f0f Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 18 Feb 2018 19:21:18 +0000 Subject: [PATCH 553/595] Enable parameter/localparameter definitions in the compilation unit scope. --- pform.cc | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/pform.cc b/pform.cc index ce036af83..d93d48659 100644 --- a/pform.cc +++ b/pform.cc @@ -3017,14 +3017,12 @@ void pform_set_parameter(const struct vlltype&loc, VLerror(loc, "error: parameter declarations must be contained within a module."); return; } - if (is_compilation_unit(scope)) { - VLerror(loc, "sorry: parameter declarations in the $root scope are not yet supported."); - return; - } if (scope == pform_cur_generate) { VLerror("parameter declarations are not permitted in generate blocks"); return; } + PScopeExtra*scopex = find_nearest_scopex(lexical_scope); + assert(scopex); // Check if the parameter name is already in the dictionary. if (scope->parameters.find(name) != scope->parameters.end()) { @@ -3032,14 +3030,14 @@ void pform_set_parameter(const struct vlltype&loc, FILE_NAME(&tloc, loc); cerr << tloc.get_fileline() << ": error: duplicate definition " "for parameter '" << name << "' in '" - << pform_cur_module.front()->mod_name() << "'." << endl; + << scopex->pscope_name() << "'." << endl; error_count += 1; } if (scope->localparams.find(name) != scope->localparams.end()) { LineInfo tloc; FILE_NAME(&tloc, loc); cerr << tloc.get_fileline() << ": error: localparam and " - << "parameter in '" << pform_cur_module.front()->mod_name() + << "parameter in '" << scopex->pscope_name() << "' have the same name '" << name << "'." << endl; error_count += 1; } @@ -3051,7 +3049,7 @@ void pform_set_parameter(const struct vlltype&loc, LineInfo tloc; FILE_NAME(&tloc, loc); cerr << tloc.get_fileline() << ": error: specparam and " - "parameter in '" << pform_cur_module.front()->mod_name() + "parameter in '" << scopex->pscope_name() << "' have the same name '" << name << "'." << endl; error_count += 1; } @@ -3092,10 +3090,8 @@ void pform_set_localparam(const struct vlltype&loc, VLerror(loc, "error: localparam declarations must be contained within a module."); return; } - if (is_compilation_unit(scope)) { - VLerror(loc, "sorry: localparam declarations in the $root scope are not yet supported."); - return; - } + PScopeExtra*scopex = find_nearest_scopex(lexical_scope); + assert(scopex); // Check if the localparam name is already in the dictionary. if (scope->localparams.find(name) != scope->localparams.end()) { @@ -3103,14 +3099,14 @@ void pform_set_localparam(const struct vlltype&loc, FILE_NAME(&tloc, loc); cerr << tloc.get_fileline() << ": error: duplicate definition " "for localparam '" << name << "' in '" - << pform_cur_module.front()->mod_name() << "'." << endl; + << scopex->pscope_name() << "'." << endl; error_count += 1; } if (scope->parameters.find(name) != scope->parameters.end()) { LineInfo tloc; FILE_NAME(&tloc, loc); cerr << tloc.get_fileline() << ": error: parameter and " - << "localparam in '" << pform_cur_module.front()->mod_name() + << "localparam in '" << scopex->pscope_name() << "' have the same name '" << name << "'." << endl; error_count += 1; } @@ -3121,7 +3117,7 @@ void pform_set_localparam(const struct vlltype&loc, LineInfo tloc; FILE_NAME(&tloc, loc); cerr << tloc.get_fileline() << ": error: specparam and " - "localparam in '" << pform_cur_module.front()->mod_name() + "localparam in '" << scopex->pscope_name() << "' have the same name '" << name << "'." << endl; error_count += 1; } From 6b1b402a790d29a7948897d33462b934c2e97cca Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 20 Feb 2018 20:59:26 +0000 Subject: [PATCH 554/595] Fix for br1027: incorrect inference of task/function port direction. In traditional Verilog, each task_port_item must have an explicit port direction. In SystemVerilog, if the port direction is not specified, it should be inherited from the preceding task_port_item for that task/function, and only the first task_port_item should infer the direction to be 'input'. --- parse.y | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/parse.y b/parse.y index 48dbe2d9a..f68df4098 100644 --- a/parse.y +++ b/parse.y @@ -593,7 +593,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector %type function_item function_item_list function_item_list_opt %type task_item task_item_list task_item_list_opt -%type tf_port_declaration tf_port_item tf_port_list tf_port_list_opt +%type tf_port_declaration tf_port_item tf_port_item_list tf_port_list tf_port_list_opt %type modport_simple_port port_name parameter_value_byname %type port_name_list parameter_value_byname_list @@ -2133,10 +2133,14 @@ tf_port_item /* IEEE1800-2005: A.2.7 */ : port_direction_opt data_type_or_implicit IDENTIFIER dimensions_opt tf_port_item_expr_opt { vector*tmp; - NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT? NetNet::PINPUT : $1; + NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT ? port_declaration_context.port_type : $1; perm_string name = lex_strings.make($3); list* ilist = list_from_identifier($3); + if (use_port_type == NetNet::PIMPLICIT) { + yyerror(@1, "error: missing task/function port direction."); + use_port_type = NetNet::PINPUT; // for error recovery + } if (($2 == 0) && ($1==NetNet::PIMPLICIT)) { // Detect special case this is an undecorated // identifier and we need to get the declaration from @@ -2148,7 +2152,6 @@ tf_port_item /* IEEE1800-2005: A.2.7 */ port_declaration_context.data_type, ilist); - } else { // Otherwise, the decorations for this identifier // indicate the type. Save the type for any right @@ -2195,8 +2198,15 @@ tf_port_item_expr_opt ; tf_port_list /* IEEE1800-2005: A.2.7 */ + : { port_declaration_context.port_type = gn_system_verilog() ? NetNet::PINPUT : NetNet::PIMPLICIT; + port_declaration_context.data_type = 0; + } + tf_port_item_list + { $$ = $2; } + ; - : tf_port_list ',' tf_port_item +tf_port_item_list + : tf_port_item_list ',' tf_port_item { vector*tmp; if ($1 && $3) { size_t s1 = $1->size(); @@ -2222,11 +2232,11 @@ tf_port_list /* IEEE1800-2005: A.2.7 */ { yyerror(@2, "error: Syntax error in task/function port declaration."); $$ = $3; } - | tf_port_list ',' + | tf_port_item_list ',' { yyerror(@2, "error: NULL port declarations are not allowed."); $$ = $1; } - | tf_port_list ';' + | tf_port_item_list ';' { yyerror(@2, "error: ';' is an invalid port declaration separator."); $$ = $1; } From 69d80839a5156202ea3b0704218bde5bc31424fb Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Wed, 21 Feb 2018 20:07:13 +0000 Subject: [PATCH 555/595] Improved check for missing task/function port direction. --- parse.y | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/parse.y b/parse.y index f68df4098..c55dac843 100644 --- a/parse.y +++ b/parse.y @@ -2133,7 +2133,9 @@ tf_port_item /* IEEE1800-2005: A.2.7 */ : port_direction_opt data_type_or_implicit IDENTIFIER dimensions_opt tf_port_item_expr_opt { vector*tmp; - NetNet::PortType use_port_type = $1==NetNet::PIMPLICIT ? port_declaration_context.port_type : $1; + NetNet::PortType use_port_type = $1; + if ((use_port_type == NetNet::PIMPLICIT) && (gn_system_verilog() || ($2 == 0))) + use_port_type = port_declaration_context.port_type; perm_string name = lex_strings.make($3); list* ilist = list_from_identifier($3); From 36eef5154ff156703fbe99ab43901b8e33f7d557 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Fri, 23 Feb 2018 22:07:59 +0000 Subject: [PATCH 556/595] Implement supply->strong strength reduction for non-resistive switches. As specified in 1364-2005 section 7.11. --- vvp/island_tran.cc | 25 ++++++++++++++---------- vvp/npmos.cc | 32 ++++++++++++++++++++++--------- vvp/npmos.h | 9 +++++---- vvp/vvp_net.cc | 47 ++++++++++++++++++++++------------------------ vvp/vvp_net.h | 10 ++++++---- 5 files changed, 71 insertions(+), 52 deletions(-) diff --git a/vvp/island_tran.cc b/vvp/island_tran.cc index 17240dc78..ae51b41f5 100644 --- a/vvp/island_tran.cc +++ b/vvp/island_tran.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2012 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2018 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 @@ -45,14 +45,14 @@ struct vvp_island_branch_tran : public vvp_island_branch { vvp_island_branch_tran(vvp_net_t*en__, bool active_high__, unsigned width__, unsigned part__, - unsigned offset__); + unsigned offset__, bool resistive__); bool run_test_enabled(); void run_resolution(); void run_output(); vvp_net_t*en; unsigned width, part, offset; - bool active_high; + bool active_high, resistive; tran_state_t state; }; @@ -60,9 +60,10 @@ vvp_island_branch_tran::vvp_island_branch_tran(vvp_net_t*en__, bool active_high__, unsigned width__, unsigned part__, - unsigned offset__) + unsigned offset__, + bool resistive__) : en(en__), width(width__), part(part__), offset(offset__), - active_high(active_high__) + active_high(active_high__), resistive(resistive__) { state = en__ ? tran_disabled : tran_enabled; } @@ -235,7 +236,8 @@ bool vvp_island_branch_tran::run_test_enabled() // input is 'x' or 'z'. We use the rules that are given for MOS switches. inline vvp_vector8_t resolve_ambiguous(const vvp_vector8_t&a, const vvp_vector8_t&b, - tran_state_t state) + tran_state_t state, + unsigned str_map[8]) { assert(a.size() == b.size()); vvp_vector8_t out (a.size()); @@ -243,6 +245,9 @@ inline vvp_vector8_t resolve_ambiguous(const vvp_vector8_t&a, for (unsigned idx = 0 ; idx < out.size() ; idx += 1) { vvp_scalar_t a_bit = a.value(idx); vvp_scalar_t b_bit = b.value(idx); + b_bit = vvp_scalar_t(b_bit.value(), + str_map[b_bit.strength0()], + str_map[b_bit.strength1()]); if (state == tran_unknown) { switch (b_bit.value()) { case BIT4_0: @@ -293,8 +298,8 @@ static void push_value_through_branch(const vvp_vector8_t&val, // previously collected (and resolved) for the port. if (branch->width == 0) { // There are no part selects. - dst_port->value = resolve_ambiguous(dst_port->value, val, - branch->state); + dst_port->value = resolve_ambiguous(dst_port->value, val, branch->state, + vvp_switch_strength_map[branch->resistive]); } else if (dst_ab == 1) { // The other side is a strict subset (part select) @@ -413,7 +418,7 @@ void compile_island_tranif(int sense, char*island, char*pa, char*pb, char*pe) vvp_island_branch_tran*br = new vvp_island_branch_tran(en, sense ? true : false, - 0, 0, 0); + 0, 0, 0, false); use_island->add_branch(br, pa, pb); @@ -430,7 +435,7 @@ void compile_island_tranvp(char*island, char*pa, char*pb, free(island); vvp_island_branch_tran*br = new vvp_island_branch_tran(NULL, false, - wid, par, off); + wid, par, off, false); use_island->add_branch(br, pa, pb); diff --git a/vvp/npmos.cc b/vvp/npmos.cc index 1359c9691..1eae2bc07 100644 --- a/vvp/npmos.cc +++ b/vvp/npmos.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2005-2018 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 @@ -19,9 +19,10 @@ # include "npmos.h" -vvp_fun_pmos_::vvp_fun_pmos_(bool enable_invert) +vvp_fun_pmos_::vvp_fun_pmos_(bool enable_invert, bool resistive) { inv_en_ = enable_invert; + resistive_ = resistive; } @@ -58,12 +59,18 @@ void vvp_fun_pmos_::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit, void vvp_fun_pmos_::generate_output_(vvp_net_ptr_t ptr) { + const unsigned*strength_map = vvp_switch_strength_map[resistive_]; + vvp_vector8_t out (bit_.size()); for (unsigned idx = 0 ; idx < out.size() ; idx += 1) { vvp_bit4_t b_en = en_.value(idx); vvp_scalar_t b_bit = bit_.value(idx); + b_bit = vvp_scalar_t(b_bit.value(), + strength_map[b_bit.strength0()], + strength_map[b_bit.strength1()]); + switch (b_en) { case BIT4_0: out.set_bit(idx, b_bit); @@ -93,7 +100,7 @@ void vvp_fun_pmos_::generate_output_(vvp_net_ptr_t ptr) vvp_fun_pmos::vvp_fun_pmos(bool enable_invert) -: vvp_fun_pmos_(enable_invert) +: vvp_fun_pmos_(enable_invert, false) { } @@ -112,7 +119,7 @@ void vvp_fun_pmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit) } vvp_fun_rpmos::vvp_fun_rpmos(bool enable_invert) -: vvp_fun_pmos_(enable_invert) +: vvp_fun_pmos_(enable_invert, true) { } @@ -126,7 +133,7 @@ void vvp_fun_rpmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit) if (ptr.port() != 0) return; - bit_ = resistive_reduction(bit); + bit_ = bit; generate_output_(ptr); } @@ -135,8 +142,9 @@ void vvp_fun_rpmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit) * CMOS primitive. */ -vvp_fun_cmos_::vvp_fun_cmos_() +vvp_fun_cmos_::vvp_fun_cmos_(bool resistive) { + resistive_ = resistive; } void vvp_fun_cmos_::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t &bit, @@ -175,6 +183,8 @@ void vvp_fun_cmos_::recv_vec8_pv(vvp_net_ptr_t ptr, const vvp_vector8_t&bit, void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr) { + const unsigned*strength_map = vvp_switch_strength_map[resistive_]; + vvp_vector8_t out (bit_.size()); for (unsigned idx = 0 ; idx < out.size() ; idx += 1) { @@ -182,6 +192,10 @@ void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr) vvp_bit4_t b_p_en = p_en_.value(idx); vvp_scalar_t b_bit = bit_.value(idx); + b_bit = vvp_scalar_t(b_bit.value(), + strength_map[b_bit.strength0()], + strength_map[b_bit.strength1()]); + if (b_n_en == BIT4_1 || b_p_en == BIT4_0) { out.set_bit(idx, b_bit); } else if (b_n_en == BIT4_0 && b_p_en == BIT4_1) { @@ -206,7 +220,7 @@ void vvp_fun_cmos_::generate_output_(vvp_net_ptr_t ptr) } vvp_fun_cmos::vvp_fun_cmos() -: vvp_fun_cmos_() +: vvp_fun_cmos_(false) { } @@ -225,7 +239,7 @@ void vvp_fun_cmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit) } vvp_fun_rcmos::vvp_fun_rcmos() -: vvp_fun_cmos_() +: vvp_fun_cmos_(true) { } @@ -239,6 +253,6 @@ void vvp_fun_rcmos::recv_vec8(vvp_net_ptr_t ptr, const vvp_vector8_t&bit) if (ptr.port() != 0) return; - bit_ = resistive_reduction(bit); + bit_ = bit; generate_output_(ptr); } diff --git a/vvp/npmos.h b/vvp/npmos.h index cb6950685..9a91ca49d 100644 --- a/vvp/npmos.h +++ b/vvp/npmos.h @@ -1,7 +1,7 @@ #ifndef IVL_npmos_H #define IVL_npmos_H /* - * Copyright (c) 2005-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2005-2018 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 @@ -46,7 +46,7 @@ class vvp_fun_pmos_ : public vvp_net_fun_t { public: - explicit vvp_fun_pmos_(bool enable_invert); + explicit vvp_fun_pmos_(bool enable_invert, bool resistive); void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t&bit, vvp_context_t); @@ -62,7 +62,7 @@ class vvp_fun_pmos_ : public vvp_net_fun_t { vvp_vector8_t bit_; vvp_vector4_t en_; - bool inv_en_; + bool inv_en_, resistive_; }; class vvp_fun_pmos : public vvp_fun_pmos_ { @@ -109,7 +109,7 @@ class vvp_fun_rpmos : public vvp_fun_pmos_ { class vvp_fun_cmos_ : public vvp_net_fun_t { public: - explicit vvp_fun_cmos_(); + explicit vvp_fun_cmos_(bool resistive); void recv_vec4(vvp_net_ptr_t port, const vvp_vector4_t &bit, vvp_context_t); @@ -126,6 +126,7 @@ class vvp_fun_cmos_ : public vvp_net_fun_t { vvp_vector8_t bit_; vvp_vector4_t n_en_; vvp_vector4_t p_en_; + bool resistive_; }; class vvp_fun_cmos : public vvp_fun_cmos_ { diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index 4b53978fa..73852fcba 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2004-2018 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 @@ -3686,31 +3686,28 @@ vvp_scalar_t fully_featured_resolv_(vvp_scalar_t a, vvp_scalar_t b) return res; } -vvp_vector8_t resistive_reduction(const vvp_vector8_t&that) -{ - static unsigned rstr[8] = { - 0, /* Hi-Z --> Hi-Z */ - 1, /* Small capacitance --> Small capacitance */ - 1, /* Medium capacitance --> Small capacitance */ - 2, /* Weak drive --> Medium capacitance */ - 2, /* Large capacitance --> Medium capacitance */ - 3, /* Pull drive --> Weak drive */ - 5, /* Strong drive --> Pull drive */ - 5 /* Supply drive --> Pull drive */ - }; - - vvp_vector8_t res (that.size()); - - for (unsigned idx = 0 ; idx < res.size() ; idx += 1) { - vvp_scalar_t bit = that.value(idx); - bit = vvp_scalar_t(bit.value(), - rstr[bit.strength0()], - rstr[bit.strength1()]); - res.set_bit(idx, bit); +unsigned vvp_switch_strength_map[2][8] = { + { // non-resistive + 0, /* High impedance --> High impedance */ + 1, /* Small capacitor --> Small capacitor */ + 2, /* Medium capacitor --> Medium capacitor */ + 3, /* Weak drive --> Weak drive */ + 4, /* Large capacitor --> Large capacitor */ + 5, /* Pull drive --> Pull drive */ + 6, /* Strong drive --> Strong drive */ + 6 /* Supply drive --> Strong drive */ + }, + { // resistive + 0, /* High impedance --> High impedance */ + 1, /* Small capacitor --> Small capacitor */ + 1, /* Medium capacitor --> Small capacitor */ + 2, /* Weak drive --> Medium capacitor */ + 2, /* Large capacitor --> Medium capacitor */ + 3, /* Pull drive --> Weak drive */ + 5, /* Strong drive --> Pull drive */ + 5 /* Supply drive --> Pull drive */ } - - return res; -} +}; vvp_vector4_t reduce4(const vvp_vector8_t&that) { diff --git a/vvp/vvp_net.h b/vvp/vvp_net.h index b5bf544c1..c143fa571 100644 --- a/vvp/vvp_net.h +++ b/vvp/vvp_net.h @@ -1,7 +1,7 @@ #ifndef IVL_vvp_net_H #define IVL_vvp_net_H /* - * Copyright (c) 2004-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2004-2018 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 @@ -954,9 +954,11 @@ inline vvp_vector8_t resolve(const vvp_vector8_t&a, const vvp_vector8_t&b) return out; } - /* This function implements the strength reduction implied by - Verilog standard resistive devices. */ -extern vvp_vector8_t resistive_reduction(const vvp_vector8_t&a); + /* This lookup tabke implements the strength reduction implied by + Verilog standard switch devices. The major dimension selects + between non-resistive and resistive devices. */ +extern unsigned vvp_switch_strength_map[2][8]; + /* The reduce4 function converts a vector8 to a vector4, losing strength information in the process. */ extern vvp_vector4_t reduce4(const vvp_vector8_t&that); From 5cfb7d68ae9482b8d73365f64b47baf33a61f767 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Fri, 23 Feb 2018 22:30:32 +0000 Subject: [PATCH 557/595] Add support for rtran switches in vvp. --- tgt-vvp/draw_switch.c | 14 +++++++++++--- vvp/compile.h | 2 +- vvp/island_tran.cc | 5 +++-- vvp/lexor.lex | 5 ++++- vvp/parse.y | 20 +++++++++++++++----- 5 files changed, 34 insertions(+), 12 deletions(-) diff --git a/tgt-vvp/draw_switch.c b/tgt-vvp/draw_switch.c index 01a6f30a5..fa0391810 100644 --- a/tgt-vvp/draw_switch.c +++ b/tgt-vvp/draw_switch.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2018 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 @@ -73,6 +73,15 @@ void draw_switch_in_scope(ivl_switch_t sw) } switch (ivl_switch_type(sw)) { + case IVL_SW_RTRAN: + fprintf(vvp_out, " .rtran"); + break; + case IVL_SW_RTRANIF0: + fprintf(vvp_out, " .rtranif0"); + break; + case IVL_SW_RTRANIF1: + fprintf(vvp_out, " .rtranif1"); + break; case IVL_SW_TRAN: fprintf(vvp_out, " .tran"); break; @@ -88,8 +97,7 @@ void draw_switch_in_scope(ivl_switch_t sw) break; default: - fprintf(stderr, "%s:%u: tgt-vvp sorry: resistive switch modeling " - "is not currently supported.\n", + fprintf(stderr, "%s:%u: tgt-vvp error: unrecognised switch type.\n", ivl_switch_file(sw), ivl_switch_lineno(sw)); vvp_errors += 1; return; diff --git a/vvp/compile.h b/vvp/compile.h index 6ef0b122d..8dec1e311 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -556,7 +556,7 @@ extern void compile_island_cleanup(void); extern void compile_island_tran(char*label); extern void compile_island_tranif(int sense, char*island, - char*ba, char*bb, char*src); + char*ba, char*bb, char*src, bool resistive); extern void compile_island_tranvp(char*island, char*ba, char*bb, unsigned width, unsigned part, unsigned off); diff --git a/vvp/island_tran.cc b/vvp/island_tran.cc index ae51b41f5..7d2953708 100644 --- a/vvp/island_tran.cc +++ b/vvp/island_tran.cc @@ -401,7 +401,8 @@ void compile_island_tran(char*label) compile_island_base(label, use_island); } -void compile_island_tranif(int sense, char*island, char*pa, char*pb, char*pe) +void compile_island_tranif(int sense, char*island, char*pa, char*pb, char*pe, + bool resistive) { vvp_island*use_island = compile_find_island(island); assert(use_island); @@ -418,7 +419,7 @@ void compile_island_tranif(int sense, char*island, char*pa, char*pb, char*pe) vvp_island_branch_tran*br = new vvp_island_branch_tran(en, sense ? true : false, - 0, 0, 0, false); + 0, 0, 0, resistive); use_island->add_branch(br, pa, pb); diff --git a/vvp/lexor.lex b/vvp/lexor.lex index 06313f4ef..94318db35 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -4,7 +4,7 @@ %{ /* - * Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2018 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 @@ -196,6 +196,9 @@ static char* strdupnew(char const *str) ".reduce/xnor" { return K_REDUCE_XNOR; } ".repeat" { return K_REPEAT; } ".resolv" { return K_RESOLV; } +".rtran" { return K_RTRAN; } +".rtranif0" { return K_RTRANIF0; } +".rtranif1" { return K_RTRANIF1; } ".scope" { return K_SCOPE; } ".sfunc" { return K_SFUNC; } ".sfunc/e" { return K_SFUNC_E; } diff --git a/vvp/parse.y b/vvp/parse.y index 309a3e282..a6ae822ac 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -1,7 +1,7 @@ %{ /* - * Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2018 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 @@ -93,7 +93,8 @@ static struct __vpiModPath*modpath_dst = 0; %token K_PARAM_STR K_PARAM_L K_PARAM_REAL K_PART K_PART_PV %token K_PART_V K_PART_V_S K_PORT K_PORT_INFO K_PV K_REDUCE_AND K_REDUCE_OR K_REDUCE_XOR %token K_REDUCE_NAND K_REDUCE_NOR K_REDUCE_XNOR K_REPEAT -%token K_RESOLV K_SCOPE K_SFUNC K_SFUNC_E K_SHIFTL K_SHIFTR K_SHIFTRS +%token K_RESOLV K_RTRAN K_RTRANIF0 K_RTRANIF1 +%token K_SCOPE K_SFUNC K_SFUNC_E K_SHIFTL K_SHIFTR K_SHIFTRS %token K_SUBSTITUTE %token K_THREAD K_TIMESCALE K_TRAN K_TRANIF0 K_TRANIF1 K_TRANVP %token K_UFUNC_REAL K_UFUNC_VEC4 K_UFUNC_E K_UDP K_UDP_C K_UDP_S @@ -870,14 +871,23 @@ statement | T_LABEL K_EXPORT T_SYMBOL ';' { compile_island_export($1, $3); } + | K_RTRAN T_SYMBOL ',' T_SYMBOL T_SYMBOL ';' + { compile_island_tranif(0, $2, $4, $5, 0, 1); } + + | K_RTRANIF0 T_SYMBOL ',' T_SYMBOL T_SYMBOL ',' T_SYMBOL ';' + { compile_island_tranif(0, $2, $4, $5, $7, 1); } + + | K_RTRANIF1 T_SYMBOL ',' T_SYMBOL T_SYMBOL ',' T_SYMBOL ';' + { compile_island_tranif(1, $2, $4, $5, $7, 1); } + | K_TRAN T_SYMBOL ',' T_SYMBOL T_SYMBOL ';' - { compile_island_tranif(0, $2, $4, $5, 0); } + { compile_island_tranif(0, $2, $4, $5, 0, 0); } | K_TRANIF0 T_SYMBOL ',' T_SYMBOL T_SYMBOL ',' T_SYMBOL ';' - { compile_island_tranif(0, $2, $4, $5, $7); } + { compile_island_tranif(0, $2, $4, $5, $7, 0); } | K_TRANIF1 T_SYMBOL ',' T_SYMBOL T_SYMBOL ',' T_SYMBOL ';' - { compile_island_tranif(1, $2, $4, $5, $7); } + { compile_island_tranif(1, $2, $4, $5, $7, 0); } | K_TRANVP T_NUMBER T_NUMBER T_NUMBER ',' T_SYMBOL ',' T_SYMBOL T_SYMBOL ';' { compile_island_tranvp($6, $8, $9, $2, $3, $4); } From fdaf92353237e95de579381f6955862bf608f60e Mon Sep 17 00:00:00 2001 From: Aaron Parks Date: Wed, 28 Mar 2018 12:24:47 -0700 Subject: [PATCH 558/595] Fixed install step misnomer in README --- README.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.txt b/README.txt index a2e535955..3ba1503db 100644 --- a/README.txt +++ b/README.txt @@ -85,7 +85,7 @@ If you are building from git, you have to run the command below before compile the source. This will generate the "configure" file, which is automatically done when building from tarball. - sh configure.sh + sh autoconf.sh Normally, this command automatically figures out everything it needs to know. It generally works pretty well. There are a few flags to the From 6c9b3c39b46cd2604af2aac633af391aa01875be Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 11 Apr 2018 13:39:53 -0700 Subject: [PATCH 559/595] Add the --ccflags option to iverilog-vpi --- iverilog-vpi.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/iverilog-vpi.sh b/iverilog-vpi.sh index 3b918d7f0..026e3e6ea 100644 --- a/iverilog-vpi.sh +++ b/iverilog-vpi.sh @@ -96,6 +96,11 @@ do exit; ;; + --ccflags) + echo "$CXXFLAGS" + exit; + ;; + --ldflags) echo "$LDFLAGS" exit; From 5a4e99b0e8a973a5e8002ae76da0d46d83236547 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 12 May 2018 23:40:29 +0100 Subject: [PATCH 560/595] Fix br1029 - correct rounding when vpi_get_value converts real to integer string. --- vvp/vpi_callback.cc | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index 914afb7ec..45f4798af 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2018 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 @@ -774,6 +774,15 @@ void vvp_signal_value::get_signal_value(struct t_vpi_value*vp) } } +static double vlg_round(double rval) +{ + if (rval >= 0.0) { + return floor(rval + 0.5); + } else { + return ceil(rval - 0.5); + } +} + static void real_signal_value(struct t_vpi_value*vp, double rval) { char*rbuf = (char *) need_result_buf(64 + 1, RBUF_VAL); @@ -791,31 +800,26 @@ static void real_signal_value(struct t_vpi_value*vp, double rval) if (rval != rval || (rval && (rval == 0.5*rval))) { rval = 0.0; } else { - if (rval >= 0.0) rval = floor(rval + 0.5); - else rval = ceil(rval - 0.5); + rval = vlg_round(rval); } vp->value.integer = (PLI_INT32)rval; break; case vpiDecStrVal: -#if !defined(__GNUC__) - if (isnan(rval)) - sprintf(rbuf, "%s", "nan"); - else - sprintf(rbuf, "%0.0f", rval); -#else - sprintf(rbuf, "%0.0f", rval); -#endif + if (isnan(rval)) + sprintf(rbuf, "%s", "nan"); + else + sprintf(rbuf, "%0.0f", vlg_round(rval)); vp->value.str = rbuf; break; case vpiHexStrVal: - sprintf(rbuf, "%lx", (long)rval); + sprintf(rbuf, "%lx", (long)vlg_round(rval)); vp->value.str = rbuf; break; case vpiBinStrVal: { - unsigned long val = (unsigned long)rval; + unsigned long val = (unsigned long)vlg_round(rval); unsigned len = 0; while (val > 0) { @@ -823,7 +827,7 @@ static void real_signal_value(struct t_vpi_value*vp, double rval) val /= 2; } - val = (unsigned long)rval; + val = (unsigned long)vlg_round(rval); for (unsigned idx = 0 ; idx < len ; idx += 1) { rbuf[len-idx-1] = (val & 1)? '1' : '0'; val /= 2; From 87c01c55c05a13bf2a471a8600346809ab85040d Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 14 May 2018 21:30:56 +0100 Subject: [PATCH 561/595] Don't allow non-vectorable arguments to $signed/$unsigned. This led to an assertion failure in many cases (see br1029). 1364-2012 indicates it is illegal. --- elab_expr.cc | 9 ++++++++- vhdlpp/std_funcs.cc | 4 ++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 8722039c1..e5940801b 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2018 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -1456,6 +1456,13 @@ NetExpr* PECallFunction::elaborate_sfunc_(Design*des, NetScope*scope, return 0; } + if (!type_is_vectorable(expr_type_)) { + cerr << get_fileline() << ": error: The argument to " + << name << " must be a vector type." << endl; + des->errors += 1; + return 0; + } + if (debug_elaborate) { cerr << get_fileline() << ": PECallFunction::elaborate_sfunc_: " << name << " expression is the argument cast to expr_wid=" << expr_wid << endl; diff --git a/vhdlpp/std_funcs.cc b/vhdlpp/std_funcs.cc index 4e4a992f4..2880bba98 100644 --- a/vhdlpp/std_funcs.cc +++ b/vhdlpp/std_funcs.cc @@ -1,5 +1,5 @@ /* - * Copyright CERN 2016 + * Copyright CERN 2016-2018 * @author Maciej Suminski (maciej.suminski@cern.ch) * * This source code is free software; you can redistribute it @@ -201,7 +201,7 @@ void preload_std_funcs(void) args = new list(); args->push_back(new InterfacePort(&primitive_REAL)); register_std_subprogram(new SubprogramBuiltin(perm_string::literal("integer"), - perm_string::literal("$signed"), + perm_string::literal("int'"), args, &primitive_INTEGER)); /* function std_logic_vector From 6e49ab10ec13a7c90deb07195724e917eb5188ec Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 14 May 2018 22:14:51 +0100 Subject: [PATCH 562/595] Further fix for br1029. The code in vpi_callback.cc is replicated in vpi_vthr_vector.cc, so we have to replicate the fix. This should really be factored out. --- vvp/vpi_vthr_vector.cc | 32 ++++++++++++++++++-------------- 1 file changed, 18 insertions(+), 14 deletions(-) diff --git a/vvp/vpi_vthr_vector.cc b/vvp/vpi_vthr_vector.cc index c55214b79..20a37c738 100644 --- a/vvp/vpi_vthr_vector.cc +++ b/vvp/vpi_vthr_vector.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2018 Stephen Williams (steve@icarus.com) * Copyright (c) 2001 Stephan Boettcher * * This source code is free software; you can redistribute it @@ -80,6 +80,15 @@ static int vthr_word_get(int code, vpiHandle ref) } } +static double vlg_round(double rval) +{ + if (rval >= 0.0) { + return floor(rval + 0.5); + } else { + return ceil(rval - 0.5); + } +} + static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp) { struct __vpiVThrWord*obj = dynamic_cast<__vpiVThrWord*>(ref); @@ -108,31 +117,26 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp) if (val != val || (val && (val == 0.5*val))) { val = 0.0; } else { - if (val >= 0.0) val = floor(val + 0.5); - else val = ceil(val - 0.5); + val = vlg_round(val); } vp->value.integer = (PLI_INT32)val; break; case vpiDecStrVal: -#if !defined(__GNUC__) - if (isnan(val)) - sprintf(rbuf, "%s", "nan"); - else - sprintf(rbuf, "%0.0f", val); -#else - sprintf(rbuf, "%0.0f", val); -#endif + if (isnan(val)) + sprintf(rbuf, "%s", "nan"); + else + sprintf(rbuf, "%0.0f", vlg_round(val)); vp->value.str = rbuf; break; case vpiHexStrVal: - sprintf(rbuf, "%lx", (long)val); + sprintf(rbuf, "%lx", (long)vlg_round(val)); vp->value.str = rbuf; break; case vpiBinStrVal: { - unsigned long vali = (unsigned long)val; + unsigned long vali = (unsigned long)vlg_round(val); unsigned len = 0; while (vali > 0) { @@ -140,7 +144,7 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp) vali /= 2; } - vali = (unsigned long)val; + vali = (unsigned long)vlg_round(val); for (unsigned idx = 0 ; idx < len ; idx += 1) { rbuf[len-idx-1] = (vali & 1)? '1' : '0'; vali /= 2; From 7ad5b59a6f7d2e46aefe9dbb85bcc8ea1c7dd9b5 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 12 Jun 2018 21:59:58 +0100 Subject: [PATCH 563/595] Fix for GitHub issue #199: handle signed division overflow. When performing a signed division or modulus operation using native arithmetic, trap the special case that the numerator is the minimum integer value and the denominator is -1, as this gives an undefined result in C++. --- verinum.cc | 9 ++++++--- vvp/vthread.cc | 12 +++++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/verinum.cc b/verinum.cc index c5f4be65e..7b466053b 100644 --- a/verinum.cc +++ b/verinum.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2018 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 @@ -22,6 +22,7 @@ # include "verinum.h" # include # include +# include # include // Needed to get pow for as_double(). # include // Needed to get snprintf for as_string(). # include @@ -1444,7 +1445,8 @@ verinum operator / (const verinum&left, const verinum&right) if (use_len <= (8*sizeof(long) - 1)) { long l = left.as_long(); long r = right.as_long(); - long v = l / r; + bool overflow = (l == LONG_MIN) && (r == -1); + long v = overflow ? LONG_MIN : l / r; for (unsigned idx = 0 ; idx < use_len ; idx += 1) { result.set(idx, (v & 1)? verinum::V1 : verinum::V0); v >>= 1; @@ -1518,7 +1520,8 @@ verinum operator % (const verinum&left, const verinum&right) /* Use native signed modulus to do the work. */ long l = left.as_long(); long r = right.as_long(); - long v = l % r; + bool overflow = (l == LONG_MIN) && (r == -1); + long v = overflow ? 0 : l % r; for (unsigned idx = 0 ; idx < use_len ; idx += 1) { result.set(idx, (v & 1)? verinum::V1 : verinum::V0); v >>= 1; diff --git a/vvp/vthread.cc b/vvp/vthread.cc index 3bed3ed59..710404062 100644 --- a/vvp/vthread.cc +++ b/vvp/vthread.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2018 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 @@ -2707,6 +2707,10 @@ bool of_DIV_S(vthread_t thr, vvp_code_t) if (bp[0] == 0) { vvp_vector4_t tmp(wid, BIT4_X); vala = tmp; + } else if (((long)ap[0] == LONG_MIN) && ((long)bp[0] == -1)) { + vvp_vector4_t tmp(wid, BIT4_0); + tmp.set_bit(wid-1, BIT4_1); + vala = tmp; } else { long tmpa = (long) ap[0]; long tmpb = (long) bp[0]; @@ -3996,6 +4000,9 @@ bool of_MOD_S(vthread_t thr, vvp_code_t) if (rv == 0) goto x_out; + if ((lv == LONG_LONG_MIN) && (rv == -1)) + goto zero_out; + /* Sign extend the signed operands when needed. */ if (wid < 8*sizeof(long long)) { if (lv & (1LL << (wid-1))) @@ -4027,6 +4034,9 @@ bool of_MOD_S(vthread_t thr, vvp_code_t) x_out: vala = vvp_vector4_t(wid, BIT4_X); return true; + zero_out: + vala = vvp_vector4_t(wid, BIT4_0); + return true; } /* From 11c826216a63cfeefe05f79f7023f669ef6e962a Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 12 Jun 2018 22:58:07 +0100 Subject: [PATCH 564/595] Fix for GitHub issue #198 - support octal display for thread variables. --- vvp/vpi_vthr_vector.cc | 51 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/vvp/vpi_vthr_vector.cc b/vvp/vpi_vthr_vector.cc index 20a37c738..ba553cf3e 100644 --- a/vvp/vpi_vthr_vector.cc +++ b/vvp/vpi_vthr_vector.cc @@ -130,6 +130,11 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp) vp->value.str = rbuf; break; + case vpiOctStrVal: + sprintf(rbuf, "%lo", (long)vlg_round(val)); + vp->value.str = rbuf; + break; + case vpiHexStrVal: sprintf(rbuf, "%lx", (long)vlg_round(val)); vp->value.str = rbuf; @@ -283,6 +288,7 @@ class __vpiVThrVec4Stack : public __vpiHandle { void vpi_get_value_int_ (p_vpi_value vp, const vvp_vector4_t&val); void vpi_get_value_real_ (p_vpi_value vp, const vvp_vector4_t&val); void vpi_get_value_strength_(p_vpi_value vp, const vvp_vector4_t&val); + void vpi_get_value_octstr_(p_vpi_value vp, const vvp_vector4_t&val); void vpi_get_value_hexstr_(p_vpi_value vp, const vvp_vector4_t&val); void vpi_get_value_vector_(p_vpi_value vp, const vvp_vector4_t&val); private: @@ -350,6 +356,9 @@ void __vpiVThrVec4Stack::vpi_get_value(p_vpi_value vp) case vpiDecStrVal: vpi_get_value_decstr_(vp, val); break; + case vpiOctStrVal: + vpi_get_value_octstr_(vp, val); + break; case vpiHexStrVal: vpi_get_value_hexstr_(vp, val); break; @@ -400,6 +409,48 @@ void __vpiVThrVec4Stack::vpi_get_value_decstr_(p_vpi_value vp, const vvp_vector4 vp->value.str = rbuf; } +void __vpiVThrVec4Stack::vpi_get_value_octstr_(p_vpi_value vp, const vvp_vector4_t&val) +{ + unsigned wid = val.size(); + unsigned owid = (wid + 2) / 3; + char*rbuf = (char*) need_result_buf(owid+1, RBUF_VAL); + rbuf[owid] = 0; + + unsigned oval = 0; + for (unsigned idx = 0; idx < wid ; idx += 1) { + unsigned tmp = 0; + switch (val.value(idx)) { + case BIT4_0: + tmp = 0; + break; + case BIT4_1: + tmp = 1; + break; + case BIT4_X: + tmp = 2; + break; + case BIT4_Z: + tmp = 3; + break; + } + + oval = oval | (tmp << 2*(idx%3)); + + if (idx%3 == 2) { + owid -= 1; + rbuf[owid] = oct_digits[oval]; + oval = 0; + } + } + + if (owid > 0) { + owid -= 1; + rbuf[owid] = oct_digits[oval]; + oval = 0; + } + vp->value.str = rbuf; +} + void __vpiVThrVec4Stack::vpi_get_value_hexstr_(p_vpi_value vp, const vvp_vector4_t&val) { unsigned wid = val.size(); From ff8ccc0b3e9c2a23576297dc916ae866ba457b81 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 16 Jul 2018 09:02:24 -0700 Subject: [PATCH 565/595] Update fstapi.c to the latest version --- vpi/fstapi.c | 69 ++++++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/vpi/fstapi.c b/vpi/fstapi.c index 18d38ec99..386d6705e 100644 --- a/vpi/fstapi.c +++ b/vpi/fstapi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2015 Tony Bybell. + * Copyright (c) 2009-2018 Tony Bybell. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -128,6 +128,7 @@ void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint3 #include #endif +#define FST_APIMESS "FSTAPI | " /***********************/ /*** ***/ @@ -193,7 +194,7 @@ if(nam) /* cppcheck warning fix: nam is always defined, so this is not needed */ dwRetVal = GetTempPath(MAX_PATH, lpTempPathBuffer); if((dwRetVal > MAX_PATH) || (dwRetVal == 0)) { - fprintf(stderr, "GetTempPath() failed in "__FILE__" line %d, exiting.\n", __LINE__); + fprintf(stderr, FST_APIMESS"GetTempPath() failed in "__FILE__" line %d, exiting.\n", __LINE__); exit(255); } else @@ -201,7 +202,7 @@ if(nam) /* cppcheck warning fix: nam is always defined, so this is not needed */ uRetVal = GetTempFileName(lpTempPathBuffer, TEXT("FSTW"), 0, szTempFileName); if (uRetVal == 0) { - fprintf(stderr, "GetTempFileName() failed in "__FILE__" line %d, exiting.\n", __LINE__); + fprintf(stderr, FST_APIMESS"GetTempFileName() failed in "__FILE__" line %d, exiting.\n", __LINE__); exit(255); } else @@ -803,7 +804,7 @@ if(rc<0) { xc->fseek_failed = 1; #ifdef FST_DEBUG - fprintf(stderr, "Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence); + fprintf(stderr, FST_APIMESS"Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence); perror("Why"); #endif } @@ -1663,7 +1664,7 @@ if(zerocnt) /* fpos += */ fstWriterVarint(f, (zerocnt << 1)); /* scan-build */ } #ifdef FST_DEBUG -fprintf(stderr, "value chains: %d\n", cnt); +fprintf(stderr, FST_APIMESS"value chains: %d\n", cnt); #endif xc->vchg_mem[0] = '!'; @@ -1738,7 +1739,7 @@ if(xc->dump_size_limit) xc2->size_limit_locked = 1; xc2->is_initial_time = 1; /* to trick emit value and emit time change */ #ifdef FST_DEBUG - fprintf(stderr, "<< dump file size limit reached, stopping dumping >>\n"); + fprintf(stderr, FST_APIMESS"<< dump file size limit reached, stopping dumping >>\n"); #endif } } @@ -2478,7 +2479,7 @@ if(xc) #ifndef FST_WRITER_PARALLEL if(xc->parallel_enabled) { - fprintf(stderr, "ERROR: fstWriterSetParallelMode(), FST_WRITER_PARALLEL not enabled during compile, exiting.\n"); + fprintf(stderr, FST_APIMESS"fstWriterSetParallelMode(), FST_WRITER_PARALLEL not enabled during compile, exiting.\n"); exit(255); } #endif @@ -2760,7 +2761,7 @@ if((xc) && (handle <= xc->maxhandle)) xc->vchg_mem = realloc(xc->vchg_mem, xc->vchg_alloc_siz); if(!xc->vchg_mem) { - fprintf(stderr, "FATAL ERROR, could not realloc() in fstWriterEmitValueChange, exiting.\n"); + fprintf(stderr, FST_APIMESS"Could not realloc() in fstWriterEmitValueChange, exiting.\n"); exit(255); } } @@ -2874,7 +2875,7 @@ if((xc) && (handle <= xc->maxhandle)) xc->vchg_mem = realloc(xc->vchg_mem, xc->vchg_alloc_siz); if(!xc->vchg_mem) { - fprintf(stderr, "FATAL ERROR, could not realloc() in fstWriterEmitVariableLengthValueChange, exiting.\n"); + fprintf(stderr, FST_APIMESS"Could not realloc() in fstWriterEmitVariableLengthValueChange, exiting.\n"); exit(255); } } @@ -3119,7 +3120,7 @@ if(rc<0) { xc->fseek_failed = 1; #ifdef FST_DEBUG - fprintf(stderr, "Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence); + fprintf(stderr, FST_APIMESS"Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence); perror("Why"); #endif } @@ -3748,6 +3749,10 @@ if(!xc->fh) else /* FST_BL_SKIP */ { pass_status = 0; + if(xc->fh) + { + fclose(xc->fh); xc->fh = NULL; /* needed in case .hier file is missing and there are no hier sections */ + } } free(mem); @@ -4435,7 +4440,7 @@ if(gzread_pass_status) if(rc != Z_OK) { - printf("geom uncompress rc = %d\n", rc); + fprintf(stderr, FST_APIMESS"fstReaderInit(), geom uncompress rc = %d, exiting.\n", rc); exit(255); } @@ -4726,7 +4731,7 @@ for(;;) if((sectype == EOF) || (sectype == FST_BL_SKIP)) { #ifdef FST_DEBUG - fprintf(stderr, "<< EOF >>\n"); + fprintf(stderr, FST_APIMESS"<< EOF >>\n"); #endif break; } @@ -4765,9 +4770,9 @@ for(;;) mem_required_for_traversal = fstReaderUint64(xc->f); mem_for_traversal = malloc(mem_required_for_traversal + 66); /* add in potential fastlz overhead */ #ifdef FST_DEBUG - fprintf(stderr, "sec: %u seclen: %d begtim: %d endtim: %d\n", + fprintf(stderr, FST_APIMESS"sec: %u seclen: %d begtim: %d endtim: %d\n", secnum, (int)seclen, (int)beg_tim, (int)end_tim); - fprintf(stderr, "\tmem_required_for_traversal: %d\n", (int)mem_required_for_traversal); + fprintf(stderr, FST_APIMESS"mem_required_for_traversal: %d\n", (int)mem_required_for_traversal); #endif /* process time block */ { @@ -4785,7 +4790,7 @@ for(;;) tsec_clen = fstReaderUint64(xc->f); tsec_nitems = fstReaderUint64(xc->f); #ifdef FST_DEBUG - fprintf(stderr, "\ttime section unc: %d, com: %d (%d items)\n", + fprintf(stderr, FST_APIMESS"time section unc: %d, com: %d (%d items)\n", (int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems); #endif if(tsec_clen > seclen) break; /* corrupted tsec_clen: by definition it can't be larger than size of section */ @@ -4805,7 +4810,7 @@ for(;;) if(rc != Z_OK) { - printf("tsec uncompress rc = %d\n", rc); + fprintf(stderr, FST_APIMESS"fstReaderIterBlocks2(), tsec uncompress rc = %d, exiting.\n", rc); exit(255); } @@ -4881,7 +4886,7 @@ for(;;) rc = uncompress(mu, &destlen, mc, sourcelen); if(rc != Z_OK) { - printf("rc: %d\n", rc); + fprintf(stderr, FST_APIMESS"fstReaderIterBlocks2(), frame uncompress rc: %d, exiting.\n", rc); exit(255); } free(mc); @@ -5044,9 +5049,9 @@ for(;;) packtype = fgetc(xc->f); #ifdef FST_DEBUG - fprintf(stderr, "\tframe_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", + fprintf(stderr, FST_APIMESS"frame_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", (int)frame_uclen, (int)frame_clen, (int)frame_maxhandle); - fprintf(stderr, "\tvc_maxhandle: %d, packtype: %c\n", (int)vc_maxhandle, packtype); + fprintf(stderr, FST_APIMESS"vc_maxhandle: %d, packtype: %c\n", (int)vc_maxhandle, packtype); #endif indx_pntr = blkpos + seclen - 24 -tsec_clen -8; @@ -5054,7 +5059,7 @@ for(;;) chain_clen = fstReaderUint64(xc->f); indx_pos = indx_pntr - chain_clen; #ifdef FST_DEBUG - fprintf(stderr, "\tindx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen); + fprintf(stderr, FST_APIMESS"indx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen); #endif chain_cmem = malloc(chain_clen); if(!chain_cmem) goto block_err; @@ -5173,7 +5178,7 @@ for(;;) } #ifdef FST_DEBUG - fprintf(stderr, "\tdecompressed chain idx len: %"PRIu32"\n", idx); + fprintf(stderr, FST_APIMESS"decompressed chain idx len: %"PRIu32"\n", idx); #endif mc_mem_len = 16384; @@ -5241,7 +5246,7 @@ for(;;) if(rc != Z_OK) { - printf("\tfac: %d clen: %d (rc=%d)\n", (int)i, (int)val, rc); + fprintf(stderr, FST_APIMESS"fstReaderIterBlocks2(), fac: %d clen: %d (rc=%d), exiting.\n", (int)i, (int)val, rc); exit(255); } @@ -5793,9 +5798,9 @@ mem_required_for_traversal = fstReaderUint64(xc->f); #ifdef FST_DEBUG -fprintf(stderr, "rvat sec: %u seclen: %d begtim: %d endtim: %d\n", +fprintf(stderr, FST_APIMESS"rvat sec: %u seclen: %d begtim: %d endtim: %d\n", secnum, (int)seclen, (int)beg_tim, (int)end_tim); -fprintf(stderr, "\tmem_required_for_traversal: %d\n", (int)mem_required_for_traversal); +fprintf(stderr, FST_APIMESS"mem_required_for_traversal: %d\n", (int)mem_required_for_traversal); #endif /* process time block */ @@ -5814,7 +5819,7 @@ tsec_uclen = fstReaderUint64(xc->f); tsec_clen = fstReaderUint64(xc->f); tsec_nitems = fstReaderUint64(xc->f); #ifdef FST_DEBUG -fprintf(stderr, "\ttime section unc: %d, com: %d (%d items)\n", +fprintf(stderr, FST_APIMESS"time section unc: %d, com: %d (%d items)\n", (int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems); #endif ucdata = malloc(tsec_uclen); @@ -5831,7 +5836,7 @@ if(tsec_uclen != tsec_clen) if(rc != Z_OK) { - printf("tsec uncompress rc = %d\n", rc); + fprintf(stderr, FST_APIMESS"fstReaderGetValueFromHandleAtTime(), tsec uncompress rc = %d, exiting.\n", rc); exit(255); } @@ -5879,7 +5884,7 @@ if(frame_uclen == frame_clen) rc = uncompress(xc->rvat_frame_data, &destlen, mc, sourcelen); if(rc != Z_OK) { - printf("decompress rc: %d\n", rc); + fprintf(stderr, FST_APIMESS"fstReaderGetValueFromHandleAtTime(), frame decompress rc: %d, exiting.\n", rc); exit(255); } free(mc); @@ -5890,9 +5895,9 @@ xc->rvat_vc_start = ftello(xc->f); /* points to '!' character */ xc->rvat_packtype = fgetc(xc->f); #ifdef FST_DEBUG -fprintf(stderr, "\tframe_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", +fprintf(stderr, FST_APIMESS"frame_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", (int)frame_uclen, (int)frame_clen, (int)xc->rvat_frame_maxhandle); -fprintf(stderr, "\tvc_maxhandle: %d\n", (int)xc->rvat_vc_maxhandle); +fprintf(stderr, FST_APIMESS"vc_maxhandle: %d\n", (int)xc->rvat_vc_maxhandle); #endif indx_pntr = blkpos + seclen - 24 -tsec_clen -8; @@ -5900,7 +5905,7 @@ fstReaderFseeko(xc, xc->f, indx_pntr, SEEK_SET); chain_clen = fstReaderUint64(xc->f); indx_pos = indx_pntr - chain_clen; #ifdef FST_DEBUG -fprintf(stderr, "\tindx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen); +fprintf(stderr, FST_APIMESS"indx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen); #endif chain_cmem = malloc(chain_clen); fstReaderFseeko(xc, xc->f, indx_pos, SEEK_SET); @@ -6011,7 +6016,7 @@ for(i=0;irvat_data_valid = 1; @@ -6071,7 +6076,7 @@ if(!xc->rvat_chain_mem) if(rc != Z_OK) { - printf("\tclen: %d (rc=%d)\n", (int)xc->rvat_chain_len, rc); + fprintf(stderr, FST_APIMESS"fstReaderGetValueFromHandleAtTime(), rvat decompress clen: %d (rc=%d), exiting.\n", (int)xc->rvat_chain_len, rc); exit(255); } From 40558160e7e4217eca3fcdf60fa357391e5f2700 Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 30 Aug 2018 22:29:22 -0700 Subject: [PATCH 566/595] Add support for bit vector system function in vpi --- netlist.cc | 2 +- vpi/Makefile.in | 3 +- vpi/sys_bit_vec.c | 340 ++++++++++++++++++++++++++++++++++++++++++++++ vpi/sys_priv.c | 22 ++- vpi/sys_priv.h | 8 +- vpi/sys_table.c | 4 +- vpi/system.sft | 6 + 7 files changed, 380 insertions(+), 5 deletions(-) create mode 100644 vpi/sys_bit_vec.c diff --git a/netlist.cc b/netlist.cc index 803316a2a..c0650959e 100644 --- a/netlist.cc +++ b/netlist.cc @@ -2954,7 +2954,7 @@ static bool do_expr_event_match(const NetExpr*expr, const NetEvWait*evwt) // The event wait should only have a single event. if (evwt->nevents() != 1) return false; // The event should have a single probe. - const NetEvent* evt = evwt->event(0); + const NetEvent *evt = evwt->event(0); if (evt->nprobe() != 1) return false; // The probe should be for any edge. const NetEvProbe *prb = evt->probe(0); diff --git a/vpi/Makefile.in b/vpi/Makefile.in index aebdb70b2..366683ac8 100644 --- a/vpi/Makefile.in +++ b/vpi/Makefile.in @@ -51,7 +51,8 @@ CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@ LDFLAGS = @LDFLAGS@ # Object files for system.vpi -O = sys_table.o sys_convert.o sys_countdrivers.o sys_darray.o sys_deposit.o sys_display.o \ +O = sys_table.o sys_bit_vec.o sys_convert.o sys_countdrivers.o sys_darray.o \ + sys_deposit.o sys_display.o \ sys_fileio.o sys_finish.o sys_icarus.o sys_plusargs.o sys_queue.o \ sys_random.o sys_random_mti.o sys_readmem.o sys_readmem_lex.o sys_scanf.o \ sys_sdf.o sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o \ diff --git a/vpi/sys_bit_vec.c b/vpi/sys_bit_vec.c new file mode 100644 index 000000000..074f2f221 --- /dev/null +++ b/vpi/sys_bit_vec.c @@ -0,0 +1,340 @@ +/* + * Copyright (C) 2018 Cary R. (cygcary@yahoo.com) + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include +#include "vpi_user.h" +#include "sys_priv.h" + +/* + * Check that $couintbits() is called with the correct arguments. + */ +static PLI_INT32 sys_countbits_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv, arg; + int cb_count = 1; + + assert(callh != 0); + argv = vpi_iterate(vpiArgument, callh); + (void)name; /* Parameter is not used. */ + + /* $countbits() must have arguments. */ + if (argv == 0) { + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("$countbits() requires at least two arguments.\n"); + vpi_control(vpiFinish, 1); + return 0; + } + + /* The 1st argument must be numeric. */ + arg = vpi_scan(argv); + if (! is_numeric_obj(arg)) { + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("The first argument to $countbits() must be numeric.\n"); + vpi_control(vpiFinish, 1); + } + + /* We need one or more numeric control bit arguments. */ + arg = vpi_scan(argv); + if (! arg) { + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("$countbits() requires at least one control bit " + "argument.\n"); + vpi_control(vpiFinish, 1); + } + + do { + if (arg && ! is_numeric_obj(arg)) { + vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("Control bit argument %d to $countbits() must " + "be numeric.\n", cb_count); + vpi_control(vpiFinish, 1); + } + ++cb_count; + if (arg) arg = vpi_scan(argv); + } while (arg); + + return 0; +} + +/* Count the number of bits in the expression that match the search bits. */ +static PLI_INT32 count_bits_in_expr(vpiHandle expr_arg, char search[4]) +{ + s_vpi_value val; + PLI_INT32 result; + PLI_INT32 size = vpi_get(vpiSize, expr_arg); + assert(size > 0); + + val.format = vpiVectorVal; + vpi_get_value(expr_arg, &val); + + result = 0; + for (unsigned lp = 0; lp < (unsigned)size; ++lp) { + unsigned offset = lp / 32; + unsigned bit = lp % 32; + unsigned abit, bbit; + abit = (val.value.vector[offset].aval >> bit) & 0x1; + bbit = (val.value.vector[offset].bval >> bit) & 0x1; + if (search[(bbit<<1)|abit]) ++result; + } + + return result; +} + +static PLI_INT32 sys_countbits_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle expr_arg = vpi_scan(argv); + vpiHandle arg; + char search[4]; + (void)name; /* Parameter is not used. */ + + /* Scan the control bit arguments and mark which control bits to + * include in the count. */ + for (unsigned lp = 0; lp < 4 ; ++lp) search[lp] = 0; + while ((arg = vpi_scan(argv))) { + s_vpi_value val; + val.format = vpiScalarVal; + vpi_get_value(arg, &val); + switch (val.value.scalar) { + case vpi0: + search[0] = 1; + break; + case vpi1: + search[1] = 1; + break; + case vpiZ: + search[2] = 1; + break; + case vpiX: + search[3] = 1; + break; + default: + vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), + (int)vpi_get(vpiLineNo, callh)); + vpi_printf("Unknown scalar control bit argument %d passed " + "to $countbits() will be ignored.\n", + val.value.scalar); + break; + } + } + + put_integer_value(callh, count_bits_in_expr(expr_arg, search)); + + return 0; +} + +/* Count the number of ones in the expression. */ +static PLI_INT32 count_ones_in_expr(vpiHandle expr_arg) +{ + s_vpi_value val; + PLI_INT32 result; + PLI_INT32 size = vpi_get(vpiSize, expr_arg); + assert(size > 0); + + val.format = vpiVectorVal; + vpi_get_value(expr_arg, &val); + + result = 0; + size = (size + 31) / 32; + for (unsigned lp = 0; lp < (unsigned)size; ++lp) { + PLI_UINT32 ones = ~val.value.vector[lp].bval & + val.value.vector[lp].aval; + while (ones) { + if (ones & 0x1) ++result; + ones >>= 1; + } + } + + return result; +} + +static PLI_INT32 sys_countones_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle expr_arg = vpi_scan(argv); + (void)name; /* Parameter is not used. */ + + vpi_free_object(argv); + + put_integer_value(callh, count_ones_in_expr(expr_arg)); + + return 0; +} + +/* Check to see if the expression is onehot. */ +static PLI_INT32 is_onehot(vpiHandle expr_arg, unsigned zero_is_okay) +{ + s_vpi_value val; + unsigned found_a_one; + PLI_INT32 size = vpi_get(vpiSize, expr_arg); + assert(size > 0); + + val.format = vpiVectorVal; + vpi_get_value(expr_arg, &val); + + found_a_one = 0; + size = (size + 31) / 32; + for (unsigned lp = 0; lp < (unsigned)size; ++lp) { + PLI_UINT32 ones = ~val.value.vector[lp].bval & + val.value.vector[lp].aval; + while (ones) { + if (ones & 0x1) { + if (found_a_one) return vpi0; + found_a_one = 1; + } + ones >>= 1; + } + } + + if (found_a_one) return vpi1; + else if (zero_is_okay) return vpi1; + return vpi0; +} + +static PLI_INT32 sys_onehot_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle expr_arg = vpi_scan(argv); + (void)name; /* Parameter is not used. */ + + vpi_free_object(argv); + + put_scalar_value(callh, is_onehot(expr_arg, 0)); + + return 0; +} + +static PLI_INT32 sys_onehot0_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle expr_arg = vpi_scan(argv); + (void)name; /* Parameter is not used. */ + + vpi_free_object(argv); + + put_scalar_value(callh, is_onehot(expr_arg, 1)); + + return 0; +} + +/* Check to see if the expression has an undefined value. */ +static PLI_INT32 is_unknown(vpiHandle expr_arg) +{ + s_vpi_value val; + PLI_INT32 size = vpi_get(vpiSize, expr_arg); + assert(size > 0); + + val.format = vpiVectorVal; + vpi_get_value(expr_arg, &val); + + size = (size + 31) / 32; + for (unsigned lp = 0; lp < (unsigned)size; ++lp) { + if (val.value.vector[lp].bval) return vpi1; + } + + return vpi0; +} + +static PLI_INT32 sys_isunknown_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) +{ + vpiHandle callh = vpi_handle(vpiSysTfCall, 0); + vpiHandle argv = vpi_iterate(vpiArgument, callh); + vpiHandle expr_arg = vpi_scan(argv); + (void)name; /* Parameter is not used. */ + + vpi_free_object(argv); + + put_scalar_value(callh, is_unknown(expr_arg)); + + return 0; +} + +static PLI_INT32 sys_bit_vec_sizetf(ICARUS_VPI_CONST PLI_BYTE8 *name) +{ + (void)name; /* Parameter is not used. */ + + return 1; +} + +/* + * Register the functions with Verilog. + */ +void sys_bit_vec_register(void) +{ + s_vpi_systf_data tf_data; + vpiHandle res; + + tf_data.type = vpiSysFunc; + tf_data.sysfunctype = vpiIntFunc; + tf_data.calltf = sys_countbits_calltf; + tf_data.compiletf = sys_countbits_compiletf; + tf_data.sizetf = 0; + tf_data.tfname = "$countbits"; + tf_data.user_data = 0; + res = vpi_register_systf(&tf_data); + vpip_make_systf_system_defined(res); + + tf_data.type = vpiSysFunc; + tf_data.sysfunctype = vpiIntFunc; + tf_data.calltf = sys_countones_calltf; + tf_data.compiletf = sys_one_numeric_arg_compiletf; + tf_data.sizetf = 0; + tf_data.tfname = "$countones"; + tf_data.user_data = "$countones"; + res = vpi_register_systf(&tf_data); + vpip_make_systf_system_defined(res); + + tf_data.type = vpiSysFunc; + tf_data.sysfunctype = vpiSizedFunc; + tf_data.calltf = sys_onehot_calltf; + tf_data.compiletf = sys_one_numeric_arg_compiletf; + tf_data.sizetf = sys_bit_vec_sizetf; + tf_data.tfname = "$onehot"; + tf_data.user_data = "$onehot"; + res = vpi_register_systf(&tf_data); + vpip_make_systf_system_defined(res); + + tf_data.type = vpiSysFunc; + tf_data.sysfunctype = vpiSizedFunc; + tf_data.calltf = sys_onehot0_calltf; + tf_data.compiletf = sys_one_numeric_arg_compiletf; + tf_data.sizetf = sys_bit_vec_sizetf; + tf_data.tfname = "$onehot0"; + tf_data.user_data = "$onehot0"; + res = vpi_register_systf(&tf_data); + vpip_make_systf_system_defined(res); + + tf_data.type = vpiSysFunc; + tf_data.sysfunctype = vpiSizedFunc; + tf_data.calltf = sys_isunknown_calltf; + tf_data.compiletf = sys_one_numeric_arg_compiletf; + tf_data.sizetf = sys_bit_vec_sizetf; + tf_data.tfname = "$isunknown"; + tf_data.user_data = "$isunknown"; + res = vpi_register_systf(&tf_data); + vpip_make_systf_system_defined(res); +} diff --git a/vpi/sys_priv.c b/vpi/sys_priv.c index b8f333ebe..dd9714325 100644 --- a/vpi/sys_priv.c +++ b/vpi/sys_priv.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2018 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 @@ -399,3 +399,23 @@ PLI_INT32 sys_one_string_arg_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) return 0; } + +/* Return an integer value to the caller. */ +void put_integer_value(vpiHandle callh, PLI_INT32 result) +{ + s_vpi_value val; + + val.format = vpiIntVal; + val.value.integer = result; + vpi_put_value(callh, &val, 0, vpiNoDelay); +} + +/* Return a scalar value to the caller. */ +void put_scalar_value(vpiHandle callh, PLI_INT32 result) +{ + s_vpi_value val; + + val.format = vpiScalarVal; + val.value.scalar = result; + vpi_put_value(callh, &val, 0, vpiNoDelay); +} diff --git a/vpi/sys_priv.h b/vpi/sys_priv.h index 36553b250..d9052d51d 100644 --- a/vpi/sys_priv.h +++ b/vpi/sys_priv.h @@ -1,7 +1,7 @@ #ifndef IVL_sys_priv_H #define IVL_sys_priv_H /* - * Copyright (c) 2002-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2018 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 @@ -65,4 +65,10 @@ extern PLI_INT32 sys_one_opt_numeric_arg_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *n extern PLI_INT32 sys_two_numeric_args_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name); extern PLI_INT32 sys_one_string_arg_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name); +/* + * The standard put/return a value to the caller routines. + */ +extern void put_integer_value(vpiHandle callh, PLI_INT32 result); +extern void put_scalar_value(vpiHandle callh, PLI_INT32 result); + #endif /* IVL_sys_priv_H */ diff --git a/vpi/sys_table.c b/vpi/sys_table.c index bb5e3ad7e..a78754534 100644 --- a/vpi/sys_table.c +++ b/vpi/sys_table.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2010,2012 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2018 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 @@ -23,6 +23,7 @@ # include # include +extern void sys_bit_vec_register(void); extern void sys_convert_register(void); extern void sys_countdrivers_register(void); extern void sys_darray_register(void); @@ -196,6 +197,7 @@ static void sys_lxt_or_vcd_register(void) } void (*vlog_startup_routines[])(void) = { + sys_bit_vec_register, sys_convert_register, sys_countdrivers_register, sys_darray_register, diff --git a/vpi/system.sft b/vpi/system.sft index be082c85f..93e67cfd2 100644 --- a/vpi/system.sft +++ b/vpi/system.sft @@ -17,6 +17,12 @@ $dist_erlang vpiSysFuncInt $clog2 vpiSysFuncInt $q_full vpiSysFuncInt +$countbits vpiSysFuncInt +$countones vpiSysFuncInt +$onehot vpiSysFuncSized 1 unsigned +$onehot0 vpiSysFuncSized 1 unsigned +$isunknown vpiSysFuncSized 1 unsigned + $abstime vpiSysFuncReal $simparam vpiSysFuncReal $simparam$str vpiSysFuncSized 1024 unsigned From b35f9e13c7b56c9e868e4c53a69b19c3b7b88a8e Mon Sep 17 00:00:00 2001 From: Cary R Date: Sun, 2 Sep 2018 18:40:22 -0700 Subject: [PATCH 567/595] Move the bit vector functions to the SV table --- vpi/Makefile.in | 6 +++--- vpi/sys_table.c | 2 -- vpi/system.sft | 6 ------ vpi/v2009.sft | 6 ++++++ vpi/{sys_bit_vec.c => v2009_bitvec.c} | 0 vpi/v2009_table.c | 4 +++- 6 files changed, 12 insertions(+), 12 deletions(-) rename vpi/{sys_bit_vec.c => v2009_bitvec.c} (100%) diff --git a/vpi/Makefile.in b/vpi/Makefile.in index 366683ac8..88173cbda 100644 --- a/vpi/Makefile.in +++ b/vpi/Makefile.in @@ -51,8 +51,8 @@ CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@ LDFLAGS = @LDFLAGS@ # Object files for system.vpi -O = sys_table.o sys_bit_vec.o sys_convert.o sys_countdrivers.o sys_darray.o \ - sys_deposit.o sys_display.o \ +O = sys_table.o sys_convert.o sys_countdrivers.o sys_darray.o sys_deposit.o \ + sys_display.o \ sys_fileio.o sys_finish.o sys_icarus.o sys_plusargs.o sys_queue.o \ sys_random.o sys_random_mti.o sys_readmem.o sys_readmem_lex.o sys_scanf.o \ sys_sdf.o sys_time.o sys_vcd.o sys_vcdoff.o vcd_priv.o mt19937int.o \ @@ -74,7 +74,7 @@ M = sys_clog2.o v2005_math.o # Object files for va_math.vpi V = va_math.o -V2009 = v2009_table.o v2009_array.o v2009_enum.o v2009_string.o +V2009 = v2009_table.o v2009_array.o v2009_bitvec.o v2009_enum.o v2009_string.o VHDL_SYS = vhdl_table.o sys_priv.o diff --git a/vpi/sys_table.c b/vpi/sys_table.c index a78754534..23b2c9142 100644 --- a/vpi/sys_table.c +++ b/vpi/sys_table.c @@ -23,7 +23,6 @@ # include # include -extern void sys_bit_vec_register(void); extern void sys_convert_register(void); extern void sys_countdrivers_register(void); extern void sys_darray_register(void); @@ -197,7 +196,6 @@ static void sys_lxt_or_vcd_register(void) } void (*vlog_startup_routines[])(void) = { - sys_bit_vec_register, sys_convert_register, sys_countdrivers_register, sys_darray_register, diff --git a/vpi/system.sft b/vpi/system.sft index 93e67cfd2..be082c85f 100644 --- a/vpi/system.sft +++ b/vpi/system.sft @@ -17,12 +17,6 @@ $dist_erlang vpiSysFuncInt $clog2 vpiSysFuncInt $q_full vpiSysFuncInt -$countbits vpiSysFuncInt -$countones vpiSysFuncInt -$onehot vpiSysFuncSized 1 unsigned -$onehot0 vpiSysFuncSized 1 unsigned -$isunknown vpiSysFuncSized 1 unsigned - $abstime vpiSysFuncReal $simparam vpiSysFuncReal $simparam$str vpiSysFuncSized 1024 unsigned diff --git a/vpi/v2009.sft b/vpi/v2009.sft index e2a84620b..e60c8cfdd 100644 --- a/vpi/v2009.sft +++ b/vpi/v2009.sft @@ -12,5 +12,11 @@ $high vpiSysFuncInt $increment vpiSysFuncInt $size vpiSysFuncInt +$countbits vpiSysFuncInt +$countones vpiSysFuncInt +$onehot vpiSysFuncSized 1 unsigned +$onehot0 vpiSysFuncSized 1 unsigned +$isunknown vpiSysFuncSized 1 unsigned + $ivl_array_method$to_vec vpiSysFuncVoid $ivl_array_method$from_vec vpiSysFuncVoid diff --git a/vpi/sys_bit_vec.c b/vpi/v2009_bitvec.c similarity index 100% rename from vpi/sys_bit_vec.c rename to vpi/v2009_bitvec.c diff --git a/vpi/v2009_table.c b/vpi/v2009_table.c index 4e3328779..a8d613ba2 100644 --- a/vpi/v2009_table.c +++ b/vpi/v2009_table.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2010-2018 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 @@ -18,11 +18,13 @@ */ extern void v2009_array_register(void); +extern void v2009_bitvec_register(void); extern void v2009_enum_register(void); extern void v2009_string_register(void); void (*vlog_startup_routines[])(void) = { v2009_array_register, + v2009_sys_bitvec_register, v2009_enum_register, v2009_string_register, 0 From 2b030ce27a8b0db2666b9a1b55f0bfa7dbdf70ff Mon Sep 17 00:00:00 2001 From: Cary R Date: Sun, 2 Sep 2018 18:41:36 -0700 Subject: [PATCH 568/595] Update the bit vector table name --- vpi/v2009_bitvec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpi/v2009_bitvec.c b/vpi/v2009_bitvec.c index 074f2f221..6f67cf43b 100644 --- a/vpi/v2009_bitvec.c +++ b/vpi/v2009_bitvec.c @@ -283,7 +283,7 @@ static PLI_INT32 sys_bit_vec_sizetf(ICARUS_VPI_CONST PLI_BYTE8 *name) /* * Register the functions with Verilog. */ -void sys_bit_vec_register(void) +void sys_bitvec_register(void) { s_vpi_systf_data tf_data; vpiHandle res; From 1da9b2cea0cd0641344887b0a50bc809516e2971 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 3 Sep 2018 08:29:07 -0700 Subject: [PATCH 569/595] Add support for constant $countones, $isunknown, $onehot, $onehot0 --- eval_tree.cc | 166 +++++++++++++++++++++++++++++++++++++++------ netlist.h | 2 +- vpi/Makefile.in | 3 +- vpi/v2009_bitvec.c | 34 +++++----- vpi/v2009_table.c | 2 +- 5 files changed, 165 insertions(+), 42 deletions(-) diff --git a/eval_tree.cc b/eval_tree.cc index 7536bd56b..3140f8f4b 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2018 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 @@ -1908,15 +1908,62 @@ NetExpr* NetESFunc::evaluate_min_max_(ID id, const NetExpr*arg0_, return res; } -NetEConst* NetESFunc::evaluate_countbits_(const NetExpr* /*arg0*/, - const NetExpr* /*arg1*/) const +static void no_string_arg(const NetESFunc*info) { - return 0; + cerr << info->get_fileline() << ": error: constant function " + << info->name() << "() does not support a string argument." + << endl; } -NetEConst* NetESFunc::evaluate_countones_(const NetExpr* /*arg*/) const +NetEConst* NetESFunc::evaluate_countbits_(const NetExpr* arg, + const NetExpr* /*arg1*/) const { - return 0; + const NetEConst*tmpi = dynamic_cast(arg); + + NetEConst*res = 0; + + if (tmpi) { + verinum value = tmpi->value(); + + if (value.is_string()) { + no_string_arg(this); + return 0; + } + + cerr << get_fileline() << ": error: constant function " + << name_ << "() is not currently supported." + << endl; + } + + return res; +} + +NetEConst* NetESFunc::evaluate_countones_(const NetExpr* arg) const +{ + const NetEConst*tmpi = dynamic_cast(arg); + + NetEConst*res = 0; + + if (tmpi) { + verinum value = tmpi->value(); + int count = 0; + + if (value.is_string()) { + no_string_arg(this); + return 0; + } + + for (unsigned bit=0; bit < value.len(); ++bit) { + if (value[bit] == verinum::V1) count += 1; + } + + verinum tmp (count, integer_width); + tmp.has_sign(true); + res = new NetEConst(tmp); + ivl_assert(*this, res); + } + + return res; } /* Get the total number of dimensions for the given expression. */ @@ -1939,19 +1986,92 @@ NetEConst* NetESFunc::evaluate_dimensions_(const NetExpr*arg) const return new NetEConst(verinum(verinum(res), integer_width)); } -NetEConst* NetESFunc::evaluate_isunknown_(const NetExpr* /*arg*/) const +NetEConst* NetESFunc::evaluate_isunknown_(const NetExpr* arg) const { - return 0; + const NetEConst*tmpi = dynamic_cast(arg); + + NetEConst*res = 0; + + if (tmpi) { + verinum value = tmpi->value(); + unsigned is_unknown = 1; + + if (value.is_string()) { + no_string_arg(this); + return 0; + } + + if (value.is_defined()) is_unknown = 0; + + verinum tmp (is_unknown, 1U); + tmp.has_sign(false); + res = new NetEConst(tmp); + ivl_assert(*this, res); + } + + return res; } -NetEConst* NetESFunc::evaluate_onehot_(const NetExpr* /*arg*/) const +static bool is_onehot(verinum&value, bool zero_is_okay) { - return 0; + bool found_a_one = false; + + for (unsigned bit=0; bit < value.len(); ++bit) { + if (value[bit] == verinum::V1) { + if (found_a_one) return false; + found_a_one = true; + } + } + + /* If no one bit was found return true if zero is okay. */ + if (zero_is_okay) found_a_one = true; + return found_a_one; } -NetEConst* NetESFunc::evaluate_onehot0_(const NetExpr* /*arg*/) const +NetEConst* NetESFunc::evaluate_onehot_(const NetExpr* arg) const { - return 0; + const NetEConst*tmpi = dynamic_cast(arg); + + NetEConst*res = 0; + + if (tmpi) { + verinum value = tmpi->value(); + + if (value.is_string()) { + no_string_arg(this); + return 0; + } + + verinum tmp (is_onehot(value, false), 1U); + tmp.has_sign(false); + res = new NetEConst(tmp); + ivl_assert(*this, res); + } + + return res; +} + +NetEConst* NetESFunc::evaluate_onehot0_(const NetExpr* arg) const +{ + const NetEConst*tmpi = dynamic_cast(arg); + + NetEConst*res = 0; + + if (tmpi) { + verinum value = tmpi->value(); + + if (value.is_string()) { + no_string_arg(this); + return 0; + } + + verinum tmp (is_onehot(value, true), 1U); + tmp.has_sign(false); + res = new NetEConst(tmp); + ivl_assert(*this, res); + } + + return res; } /* Get the number of unpacked dimensions for the given expression. */ @@ -2194,12 +2314,12 @@ NetESFunc::ID NetESFunc::built_in_id_() const built_in_func["$unpacked_dimensions" ] = UPDIMS; } - /* These are available in 1800-2009 and later. */ + /* This is available in 1800-2009 and later. */ if (funcs_need_init && (generation_flag >= GN_VER2009)) { built_in_func["$countones" ] = CTONES; } - /* These are available in 1800-2012 and later. */ + /* This is available in 1800-2012 and later. */ if (funcs_need_init && (generation_flag >= GN_VER2012)) { built_in_func["$countbits" ] = CTBITS; } @@ -2226,7 +2346,7 @@ NetESFunc::ID NetESFunc::built_in_id_() const NetExpr* NetESFunc::eval_tree() { - /* Get the ID for this system function if it is can be used as a + /* Get the ID for this system function if it can be used as a * constant function. */ ID id = built_in_id_(); if (id == NOT_BUILT_IN) return 0; @@ -2234,8 +2354,9 @@ NetExpr* NetESFunc::eval_tree() switch (parms_.size()) { case 1: if (! takes_nargs_(id, 1)) { - cerr << get_fileline() << ": error: " << name_ - << "() does not support a single argument." << endl; + cerr << get_fileline() << ": error: constant function " + << name_ << "() does not support a single argument." + << endl; return 0; } eval_expr(parms_[0]); @@ -2243,8 +2364,9 @@ NetExpr* NetESFunc::eval_tree() case 2: if (! takes_nargs_(id, 2)) { - cerr << get_fileline() << ": error: " << name_ - << "() does not support two arguments." << endl; + cerr << get_fileline() << ": error: constant function " + << name_ << "() does not support two arguments." + << endl; return 0; } eval_expr(parms_[0]); @@ -2254,13 +2376,13 @@ NetExpr* NetESFunc::eval_tree() default: /* Check to see if the function was called correctly. */ if (! takes_nargs_(id, parms_.size())) { - cerr << get_fileline() << ": error: " << name_ - << "() does not support " << parms_.size() + cerr << get_fileline() << ": error: constant function " + << name_ << "() does not support " << parms_.size() << " arguments." << endl; return 0; } // HERE: Need to add support for a multi argument $countbits(). - cerr << get_fileline() << ": sorry: functions with " + cerr << get_fileline() << ": sorry: constant functions with " << parms_.size() << " arguments are not supported: " << name_ << "()." << endl; return 0; diff --git a/netlist.h b/netlist.h index 4ef652339..39130e3cd 100644 --- a/netlist.h +++ b/netlist.h @@ -4605,7 +4605,7 @@ class NetESFunc : public NetExpr { /* Added in SystemVerilog 2009 and later. */ CTONES = 0x00020024, /* $countones takes one argument. */ /* Added in SystemVerilog 2012 and later. */ - CTBITS = 0xfffe0025, /* $countbits takes one or more arguments. */ + CTBITS = 0xfffc0025, /* $countbits takes two or more arguments. */ /* Added as Icarus extensions to Verilog-A. */ ABS = 0x00020026, /* $abs takes one argument. */ MAX = 0x00040027, /* $max takes two argument. */ diff --git a/vpi/Makefile.in b/vpi/Makefile.in index 88173cbda..cf62786e2 100644 --- a/vpi/Makefile.in +++ b/vpi/Makefile.in @@ -74,7 +74,8 @@ M = sys_clog2.o v2005_math.o # Object files for va_math.vpi V = va_math.o -V2009 = v2009_table.o v2009_array.o v2009_bitvec.o v2009_enum.o v2009_string.o +V2009 = v2009_table.o v2009_array.o v2009_bitvec.o v2009_enum.o v2009_string.o \ + sys_priv.o VHDL_SYS = vhdl_table.o sys_priv.o diff --git a/vpi/v2009_bitvec.c b/vpi/v2009_bitvec.c index 6f67cf43b..cc824b9bb 100644 --- a/vpi/v2009_bitvec.c +++ b/vpi/v2009_bitvec.c @@ -23,7 +23,7 @@ /* * Check that $couintbits() is called with the correct arguments. */ -static PLI_INT32 sys_countbits_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) +static PLI_INT32 countbits_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv, arg; @@ -100,7 +100,7 @@ static PLI_INT32 count_bits_in_expr(vpiHandle expr_arg, char search[4]) return result; } -static PLI_INT32 sys_countbits_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) +static PLI_INT32 countbits_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); @@ -169,7 +169,7 @@ static PLI_INT32 count_ones_in_expr(vpiHandle expr_arg) return result; } -static PLI_INT32 sys_countones_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) +static PLI_INT32 countones_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); @@ -213,7 +213,7 @@ static PLI_INT32 is_onehot(vpiHandle expr_arg, unsigned zero_is_okay) return vpi0; } -static PLI_INT32 sys_onehot_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) +static PLI_INT32 onehot_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); @@ -227,7 +227,7 @@ static PLI_INT32 sys_onehot_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) return 0; } -static PLI_INT32 sys_onehot0_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) +static PLI_INT32 onehot0_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); @@ -259,7 +259,7 @@ static PLI_INT32 is_unknown(vpiHandle expr_arg) return vpi0; } -static PLI_INT32 sys_isunknown_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) +static PLI_INT32 isunknown_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, callh); @@ -273,7 +273,7 @@ static PLI_INT32 sys_isunknown_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) return 0; } -static PLI_INT32 sys_bit_vec_sizetf(ICARUS_VPI_CONST PLI_BYTE8 *name) +static PLI_INT32 bit_vec_sizetf(ICARUS_VPI_CONST PLI_BYTE8 *name) { (void)name; /* Parameter is not used. */ @@ -283,15 +283,15 @@ static PLI_INT32 sys_bit_vec_sizetf(ICARUS_VPI_CONST PLI_BYTE8 *name) /* * Register the functions with Verilog. */ -void sys_bitvec_register(void) +void v2009_bitvec_register(void) { s_vpi_systf_data tf_data; vpiHandle res; tf_data.type = vpiSysFunc; tf_data.sysfunctype = vpiIntFunc; - tf_data.calltf = sys_countbits_calltf; - tf_data.compiletf = sys_countbits_compiletf; + tf_data.calltf = countbits_calltf; + tf_data.compiletf = countbits_compiletf; tf_data.sizetf = 0; tf_data.tfname = "$countbits"; tf_data.user_data = 0; @@ -300,7 +300,7 @@ void sys_bitvec_register(void) tf_data.type = vpiSysFunc; tf_data.sysfunctype = vpiIntFunc; - tf_data.calltf = sys_countones_calltf; + tf_data.calltf = countones_calltf; tf_data.compiletf = sys_one_numeric_arg_compiletf; tf_data.sizetf = 0; tf_data.tfname = "$countones"; @@ -310,9 +310,9 @@ void sys_bitvec_register(void) tf_data.type = vpiSysFunc; tf_data.sysfunctype = vpiSizedFunc; - tf_data.calltf = sys_onehot_calltf; + tf_data.calltf = onehot_calltf; tf_data.compiletf = sys_one_numeric_arg_compiletf; - tf_data.sizetf = sys_bit_vec_sizetf; + tf_data.sizetf = bit_vec_sizetf; tf_data.tfname = "$onehot"; tf_data.user_data = "$onehot"; res = vpi_register_systf(&tf_data); @@ -320,9 +320,9 @@ void sys_bitvec_register(void) tf_data.type = vpiSysFunc; tf_data.sysfunctype = vpiSizedFunc; - tf_data.calltf = sys_onehot0_calltf; + tf_data.calltf = onehot0_calltf; tf_data.compiletf = sys_one_numeric_arg_compiletf; - tf_data.sizetf = sys_bit_vec_sizetf; + tf_data.sizetf = bit_vec_sizetf; tf_data.tfname = "$onehot0"; tf_data.user_data = "$onehot0"; res = vpi_register_systf(&tf_data); @@ -330,9 +330,9 @@ void sys_bitvec_register(void) tf_data.type = vpiSysFunc; tf_data.sysfunctype = vpiSizedFunc; - tf_data.calltf = sys_isunknown_calltf; + tf_data.calltf = isunknown_calltf; tf_data.compiletf = sys_one_numeric_arg_compiletf; - tf_data.sizetf = sys_bit_vec_sizetf; + tf_data.sizetf = bit_vec_sizetf; tf_data.tfname = "$isunknown"; tf_data.user_data = "$isunknown"; res = vpi_register_systf(&tf_data); diff --git a/vpi/v2009_table.c b/vpi/v2009_table.c index a8d613ba2..1a3f8ee2b 100644 --- a/vpi/v2009_table.c +++ b/vpi/v2009_table.c @@ -24,7 +24,7 @@ extern void v2009_string_register(void); void (*vlog_startup_routines[])(void) = { v2009_array_register, - v2009_sys_bitvec_register, + v2009_bitvec_register, v2009_enum_register, v2009_string_register, 0 From e6f957b0b6b279a2aac947f49c344b4314e37605 Mon Sep 17 00:00:00 2001 From: Cary R Date: Mon, 3 Sep 2018 15:58:05 -0700 Subject: [PATCH 570/595] Add support for a constant $countbits() function --- eval_tree.cc | 95 +++++++++++++++++++++++++++++++++++++++++----------- netlist.h | 3 +- 2 files changed, 76 insertions(+), 22 deletions(-) diff --git a/eval_tree.cc b/eval_tree.cc index 3140f8f4b..4a6c1c915 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -1908,17 +1908,16 @@ NetExpr* NetESFunc::evaluate_min_max_(ID id, const NetExpr*arg0_, return res; } -static void no_string_arg(const NetESFunc*info) +static void no_string_arg(const NetESFunc*info, unsigned arg_num) { cerr << info->get_fileline() << ": error: constant function " - << info->name() << "() does not support a string argument." - << endl; + << info->name() << "() does not support a string argument (" + << arg_num+1 << ")." << endl; } -NetEConst* NetESFunc::evaluate_countbits_(const NetExpr* arg, - const NetExpr* /*arg1*/) const +NetEConst* NetESFunc::evaluate_countbits_() const { - const NetEConst*tmpi = dynamic_cast(arg); + const NetEConst*tmpi = dynamic_cast(parms_[0]); NetEConst*res = 0; @@ -1926,13 +1925,63 @@ NetEConst* NetESFunc::evaluate_countbits_(const NetExpr* arg, verinum value = tmpi->value(); if (value.is_string()) { - no_string_arg(this); + no_string_arg(this, 0); return 0; } - cerr << get_fileline() << ": error: constant function " - << name_ << "() is not currently supported." - << endl; + /* Find which values need to be counted. */ + bool count_0 = false; + bool count_1 = false; + bool count_z = false; + bool count_x = false; + for (unsigned arg=1; arg < parms_.size(); ++arg) { + const NetEConst*argi = dynamic_cast(parms_[arg]); + if (! argi) return 0; + verinum check_for = argi->value(); + if (check_for.is_string()) { + no_string_arg(this, arg); + return 0; + } + switch (check_for[0]) { + case verinum::V0: + count_0 = true; + break; + case verinum::V1: + count_1 = true; + break; + case verinum::Vz: + count_z = true; + break; + case verinum::Vx: + count_x = true; + break; + } + } + + /* Search each bit of the vector looking for the values to + * be counted. */ + int count = 0; + for (unsigned bit=0; bit < value.len(); ++bit) { + switch (value[bit]) { + case verinum::V0: + if (count_0) ++count; + break; + case verinum::V1: + if (count_1) ++count; + break; + case verinum::Vz: + if (count_z) ++count; + break; + case verinum::Vx: + if (count_x) ++count; + break; + } + } + + verinum tmp (count, integer_width); + tmp.has_sign(true); + res = new NetEConst(tmp); + ivl_assert(*this, res); } return res; @@ -1949,12 +1998,12 @@ NetEConst* NetESFunc::evaluate_countones_(const NetExpr* arg) const int count = 0; if (value.is_string()) { - no_string_arg(this); + no_string_arg(this, 0); return 0; } for (unsigned bit=0; bit < value.len(); ++bit) { - if (value[bit] == verinum::V1) count += 1; + if (value[bit] == verinum::V1) ++count; } verinum tmp (count, integer_width); @@ -1997,7 +2046,7 @@ NetEConst* NetESFunc::evaluate_isunknown_(const NetExpr* arg) const unsigned is_unknown = 1; if (value.is_string()) { - no_string_arg(this); + no_string_arg(this, 0); return 0; } @@ -2038,7 +2087,7 @@ NetEConst* NetESFunc::evaluate_onehot_(const NetExpr* arg) const verinum value = tmpi->value(); if (value.is_string()) { - no_string_arg(this); + no_string_arg(this, 0); return 0; } @@ -2061,7 +2110,7 @@ NetEConst* NetESFunc::evaluate_onehot0_(const NetExpr* arg) const verinum value = tmpi->value(); if (value.is_string()) { - no_string_arg(this); + no_string_arg(this, 0); return 0; } @@ -2243,7 +2292,7 @@ NetExpr* NetESFunc::evaluate_two_arg_(ID id, const NetExpr*arg0, { switch (id) { case CTBITS: - return evaluate_countbits_(arg0, arg1); + return evaluate_countbits_(); /* The array functions are handled together. */ case HIGH: case INCR: @@ -2381,10 +2430,16 @@ NetExpr* NetESFunc::eval_tree() << " arguments." << endl; return 0; } -// HERE: Need to add support for a multi argument $countbits(). - cerr << get_fileline() << ": sorry: constant functions with " - << parms_.size() << " arguments are not supported: " - << name_ << "()." << endl; + if (id == CTBITS) { + for (unsigned bit = 0; bit < parms_.size(); ++bit) { + eval_expr(parms_[bit]); + } + return evaluate_countbits_(); + } else { + cerr << get_fileline() << ": sorry: constant functions with " + << parms_.size() << " arguments are not supported: " + << name_ << "()." << endl; + } return 0; } } diff --git a/netlist.h b/netlist.h index 39130e3cd..31cfc889e 100644 --- a/netlist.h +++ b/netlist.h @@ -4657,8 +4657,7 @@ class NetESFunc : public NetExpr { NetEConst* evaluate_array_funcs_(ID id, const NetExpr*arg0, const NetExpr*arg1) const; - NetEConst* evaluate_countbits_(const NetExpr*arg0, - const NetExpr*arg1) const; + NetEConst* evaluate_countbits_(void) const; public: bool is_built_in() const { return built_in_id_() != NOT_BUILT_IN; }; From 3f24557e9041472077cdefbebbca65d1a7e5e621 Mon Sep 17 00:00:00 2001 From: Cary R Date: Sun, 23 Sep 2018 22:23:43 -0700 Subject: [PATCH 571/595] Add some more always_ff synth checks --- elaborate.cc | 129 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/elaborate.cc b/elaborate.cc index ffd9b2d34..588ccf11a 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -6198,6 +6198,132 @@ bool Design::check_proc_delay() const return result; } +static void print_nexus_name(const Nexus*nex) +{ + for (const Link*cur = nex->first_nlink(); cur; cur = cur->next_nlink()) { + if (cur->get_dir() != Link::OUTPUT) continue; + const NetPins*obj = cur->get_obj(); + // For a NetNet (signal) just use the name. + if (const NetNet*net = dynamic_cast(obj)) { + cerr << net->name(); + return; + // For a NetPartSelect calculate the name. + } else if (const NetPartSelect*ps = dynamic_cast(obj)) { + assert(ps->pin_count() >= 2); + assert(ps->pin(1).get_dir() == Link::INPUT); + assert(ps->pin(1).is_linked()); + print_nexus_name(ps->pin(1).nexus()); + cerr << "[]"; + return; + // For a NetUReduce calculate the name. + } else if (const NetUReduce*reduce = dynamic_cast(obj)) { + assert(reduce->pin_count() == 2); + assert(reduce->pin(1).get_dir() == Link::INPUT); + assert(reduce->pin(1).is_linked()); + switch (reduce->type()) { + case NetUReduce::AND: + cerr << "&"; + break; + case NetUReduce::OR: + cerr << "|"; + break; + case NetUReduce::XOR: + cerr << "^"; + break; + case NetUReduce::NAND: + cerr << "~&"; + break; + case NetUReduce::NOR: + cerr << "~|"; + break; + case NetUReduce::XNOR: + cerr << "~^"; + break; + case NetUReduce::NONE: + assert(0); + } + print_nexus_name(reduce->pin(1).nexus()); + return; + } else if (const NetLogic*logic = dynamic_cast(obj)) { + assert(logic->pin_count() >= 2); + assert(logic->pin(1).get_dir() == Link::INPUT); + assert(logic->pin(1).is_linked()); + switch (logic->type()) { + case NetLogic::NOT: + cerr << "~"; + break; + default: + // The other operators should never be used here, + // so just return the nexus name. + cerr << nex->name(); + return; + } + print_nexus_name(logic->pin(1).nexus()); + return; + } + // Use the following to find the type of anything that may be missing: + // cerr << "(" << typeid(*obj).name() << ") "; + } + // Otherwise just use the nexus name so somthing is printed. + cerr << nex->name(); +} + +static void print_event_probe_name(const NetEvProbe *prb) +{ + assert(prb->pin_count() == 1); + assert(prb->pin(0).get_dir() == Link::INPUT); + assert(prb->pin(0).is_linked()); + print_nexus_name(prb->pin(0).nexus()); +} + +static void check_event_probe_width(const LineInfo *info, const NetEvProbe *prb) +{ + assert(prb->pin_count() == 1); + assert(prb->pin(0).get_dir() == Link::INPUT); + assert(prb->pin(0).is_linked()); + if (prb->edge() == NetEvProbe::ANYEDGE) return; + if (prb->pin(0).nexus()->vector_width() > 1) { + cerr << info->get_fileline() << " Warning: Synthesis wants " + "the sensitivity list expressions for '"; + switch (prb->edge()) { + case NetEvProbe::POSEDGE: + cerr << "posedge "; + break; + case NetEvProbe::NEGEDGE: + cerr << "negedge "; + break; + default: + break; + } + print_nexus_name(prb->pin(0).nexus()); + cerr << "' to be a single bit." << endl; + } +} + +static void check_ff_sensitivity(const NetProc* statement) +{ + const NetEvWait *evwt = dynamic_cast (statement); + // We have already checked for and reported if the first statmemnt is + // not a wait. + if (! evwt) return; + + for (unsigned cevt = 0; cevt < evwt->nevents(); cevt += 1) { + const NetEvent *evt = evwt->event(cevt); + for (unsigned cprb = 0; cprb < evt->nprobe(); cprb += 1) { + const NetEvProbe *prb = evt->probe(cprb); + check_event_probe_width(evwt, prb); + if (prb->edge() == NetEvProbe::ANYEDGE) { + cerr << evwt->get_fileline() << " Warning: Synthesis " + "requires the sensitivity list of an " + "always_ff process to only be edge " + "sensitive. "; + print_event_probe_name(prb); + cerr << " is missing a pos/negedge." << endl; + } + } + } +} + /* * Check to see if the always_* processes only contain synthesizable * constructs. @@ -6211,6 +6337,9 @@ bool Design::check_proc_synth() const (pr->type() == IVL_PR_ALWAYS_LATCH)) { result |= pr->statement()->check_synth(pr->type(), pr->scope()); + if (pr->type() == IVL_PR_ALWAYS_FF) { + check_ff_sensitivity(pr->statement()); + } } } return result; From 8df2f0cadf4b41695b99e9472dc3632062ef5e17 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Fri, 28 Sep 2018 10:01:15 +0100 Subject: [PATCH 572/595] Fix broken links to SourceForge bug/patch trackers (GitHub issue #207). Also add link to GitHub issues, as a lot of users report bugs there. --- BUGS.txt | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/BUGS.txt b/BUGS.txt index 14e39b774..3d201b240 100644 --- a/BUGS.txt +++ b/BUGS.txt @@ -116,13 +116,17 @@ programs. RESEARCHING EXISTING/PAST BUGS, AND FILING REPORTS -The URL is the main -bug tracking system. Once you believe you have found a bug, you may -browse the bugs database for existing bugs that may be related to -yours. You might find that your bug has already been fixed in a later -release or snapshot. If that's the case, then you are set. Also, -consider if you are reporting a bug or really asking for a new -feature, and use the appropriate tracker. +The URL is the main +bug tracking system, although some users have reported bugs at +. Once you believe +you have found a bug, you may browse the bugs database for existing +bugs that may be related to yours. You might find that your bug has +already been fixed in a later release or snapshot. If that's the case, +then you are set. Also, consider if you are reporting a bug or really +asking for a new feature, and use the appropriate tracker. + + system (although you will also find bug rep + The bug database supports basic keyword searches, and you can optionally limit your search to active bugs, or fixed bugs. You may @@ -145,7 +149,7 @@ version from git. Please see the developer documentation for more detailed instructions -- . When you make a patch, submit it to the "Patches" tracker at -. Patches added to +. Patches added to the "Patches" tracker enter the developer workflow, are checked, applied to the appropriate git branch, and are pushed. Then the tracker item is closed. @@ -158,7 +162,7 @@ clarification before applying it.) COPYRIGHT ISSUES -Icarus Verilog is Copyright (c) 1998-2008 Stephen Williams except +Icarus Verilog is Copyright (c) 1998-2018 Stephen Williams except where otherwise noted. Minor patches are covered as derivative works (or editorial comment or whatever the appropriate legal term is) and folded into the rest of ivl. However, if a submission can reasonably From 0d494da702a8c481f0d0f7b2b411e5b76d50d629 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 29 Sep 2018 08:53:32 +0100 Subject: [PATCH 573/595] Further fixes for const-correctness. - allow ICARUS_VPI_CONST to be pre-defined by the user - use it for sizetf as well as for compiletf and calltf - fix remaining warnings when it is defined as 'const' --- libveriuser/veriusertfs.c | 12 ++++++------ vpi/sys_convert.c | 7 +++---- vpi/sys_random.c | 4 ++-- vpi/sys_scanf.c | 28 ++++++++++++++-------------- vpi/v2009_enum.c | 6 +++--- vpi/vams_simparam.c | 4 ++-- vpi_user.h | 8 +++++--- 7 files changed, 35 insertions(+), 34 deletions(-) diff --git a/libveriuser/veriusertfs.c b/libveriuser/veriusertfs.c index 979b2b5d3..3c455b800 100644 --- a/libveriuser/veriusertfs.c +++ b/libveriuser/veriusertfs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2014 Michael Ruff (mruff at chiaro.com) + * Copyright (c) 2002-2018 Michael Ruff (mruff at chiaro.com) * Michael Runyan (mrunyan at chiaro.com) * * This source code is free software; you can redistribute it @@ -42,8 +42,8 @@ typedef struct t_pli_data { int paramvc; /* parameter number for misctf */ } s_pli_data, *p_pli_data; -static PLI_INT32 compiletf(char *); -static PLI_INT32 calltf(char *); +static PLI_INT32 compiletf(ICARUS_VPI_CONST PLI_BYTE8 *); +static PLI_INT32 calltf(ICARUS_VPI_CONST PLI_BYTE8 *); static PLI_INT32 callback(p_cb_data); /* @@ -150,7 +150,7 @@ void veriusertfs_register_table(p_tfcell vtable) tf_data.tfname = tf->tfname; tf_data.compiletf = compiletf; tf_data.calltf = calltf; - tf_data.sizetf = (PLI_INT32 (*)(PLI_BYTE8 *))tf->sizetf; + tf_data.sizetf = (PLI_INT32 (*)(ICARUS_VPI_CONST PLI_BYTE8 *))tf->sizetf; tf_data.user_data = (char *)data; if (pli_trace) { @@ -180,7 +180,7 @@ void veriusertfs_register_table(p_tfcell vtable) * This function calls the veriusertfs checktf and sets up all the * callbacks misctf requires. */ -static PLI_INT32 compiletf(char *data) +static PLI_INT32 compiletf(ICARUS_VPI_CONST PLI_BYTE8*data) { p_pli_data pli; p_tfcell tf; @@ -260,7 +260,7 @@ static PLI_INT32 compiletf(char *data) /* * This function is the wrapper for the veriusertfs calltf routine. */ -static PLI_INT32 calltf(char *data) +static PLI_INT32 calltf(ICARUS_VPI_CONST PLI_BYTE8*data) { int rc = 0; p_pli_data pli; diff --git a/vpi/sys_convert.c b/vpi/sys_convert.c index 389e3c764..8f78fec5a 100644 --- a/vpi/sys_convert.c +++ b/vpi/sys_convert.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2014 Michael Ruff (mruff at chiaro.com) + * Copyright (c) 2003-2018 Michael Ruff (mruff at chiaro.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 @@ -90,12 +90,12 @@ static void error_message(vpiHandle callh, const char* msg) vpi_control(vpiFinish, 1); } -static PLI_INT32 sizetf_32 (PLI_BYTE8*name) +static PLI_INT32 sizetf_32 (ICARUS_VPI_CONST PLI_BYTE8*name) { (void)name; /* Parameter is not used. */ return 32; } -static PLI_INT32 sizetf_64 (PLI_BYTE8*name) +static PLI_INT32 sizetf_64 (ICARUS_VPI_CONST PLI_BYTE8*name) { (void)name; /* Parameter is not used. */ return 64; @@ -288,4 +288,3 @@ void sys_convert_register(void) res = vpi_register_systf(&tf_data); vpip_make_systf_system_defined(res); } - diff --git a/vpi/sys_random.c b/vpi/sys_random.c index f774764a6..72bb1c66f 100644 --- a/vpi/sys_random.c +++ b/vpi/sys_random.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2018 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 @@ -924,7 +924,7 @@ static PLI_INT32 sys_dist_erlang_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) return 0; } -static PLI_INT32 sys_rand_func_sizetf(PLI_BYTE8 *name) +static PLI_INT32 sys_rand_func_sizetf(ICARUS_VPI_CONST PLI_BYTE8 *name) { (void)name; /* Parameter is not used. */ return 32; diff --git a/vpi/sys_scanf.c b/vpi/sys_scanf.c index 2e86cae2d..de567eba6 100644 --- a/vpi/sys_scanf.c +++ b/vpi/sys_scanf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006-2015 Stephen Williams (steve@icarus.com) + * Copyright (c) 2006-2018 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 @@ -219,7 +219,7 @@ static double get_float(struct byte_source *src, unsigned width, int *match) */ static int scan_format_float(vpiHandle callh, vpiHandle argv, struct byte_source *src, unsigned width, - unsigned suppress_flag, PLI_BYTE8 *name, + unsigned suppress_flag, ICARUS_VPI_CONST PLI_BYTE8 *name, char code) { vpiHandle arg; @@ -266,7 +266,7 @@ static int scan_format_float(vpiHandle callh, vpiHandle argv, */ static int scan_format_float_time(vpiHandle callh, vpiHandle argv, struct byte_source*src, unsigned width, - unsigned suppress_flag, PLI_BYTE8 *name) + unsigned suppress_flag, ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle scope = vpi_handle(vpiScope, callh); int time_units = vpi_get(vpiTimeUnit, scope); @@ -330,7 +330,7 @@ static int scan_format_float_time(vpiHandle callh, vpiHandle argv, */ static int scan_format_base(vpiHandle callh, vpiHandle argv, struct byte_source *src, unsigned width, - unsigned suppress_flag, PLI_BYTE8 *name, + unsigned suppress_flag, ICARUS_VPI_CONST PLI_BYTE8 *name, const char *match, char code, PLI_INT32 type) { @@ -406,7 +406,7 @@ static int scan_format_base(vpiHandle callh, vpiHandle argv, */ static int scan_format_binary(vpiHandle callh, vpiHandle argv, struct byte_source *src, int width, - unsigned suppress_flag, PLI_BYTE8 *name) + unsigned suppress_flag, ICARUS_VPI_CONST PLI_BYTE8 *name) { return scan_format_base(callh, argv, src, width, suppress_flag, name, "01xzXZ?_", 'b', vpiBinStrVal); @@ -420,7 +420,7 @@ static int scan_format_binary(vpiHandle callh, vpiHandle argv, */ static int scan_format_char(vpiHandle callh, vpiHandle argv, struct byte_source *src, unsigned width, - unsigned suppress_flag, PLI_BYTE8 *name) + unsigned suppress_flag, ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle arg; s_vpi_value val; @@ -466,7 +466,7 @@ static int scan_format_char(vpiHandle callh, vpiHandle argv, */ static int scan_format_decimal(vpiHandle callh, vpiHandle argv, struct byte_source *src, unsigned width, - unsigned suppress_flag, PLI_BYTE8 *name) + unsigned suppress_flag, ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle arg; char *strval = malloc(1); @@ -585,7 +585,7 @@ static int scan_format_decimal(vpiHandle callh, vpiHandle argv, */ static int scan_format_hex(vpiHandle callh, vpiHandle argv, struct byte_source *src, unsigned width, - unsigned suppress_flag, PLI_BYTE8 *name) + unsigned suppress_flag, ICARUS_VPI_CONST PLI_BYTE8 *name) { return scan_format_base(callh, argv, src, width, suppress_flag, name, "0123456789abcdefxzABCDEFXZ?_", 'h', @@ -597,7 +597,7 @@ static int scan_format_hex(vpiHandle callh, vpiHandle argv, */ static int scan_format_octal(vpiHandle callh, vpiHandle argv, struct byte_source *src, unsigned width, - unsigned suppress_flag, PLI_BYTE8 *name) + unsigned suppress_flag, ICARUS_VPI_CONST PLI_BYTE8 *name) { return scan_format_base(callh, argv, src, width, suppress_flag, name, "01234567xzXZ?_", 'o', vpiOctStrVal); @@ -608,7 +608,7 @@ static int scan_format_octal(vpiHandle callh, vpiHandle argv, * Routine to return the current hierarchical path (implements %m). */ static int scan_format_module_path(vpiHandle callh, vpiHandle argv, - unsigned suppress_flag, PLI_BYTE8 *name) + unsigned suppress_flag, ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle scope, arg; char *module_path; @@ -650,7 +650,7 @@ static int scan_format_module_path(vpiHandle callh, vpiHandle argv, */ static int scan_format_string(vpiHandle callh, vpiHandle argv, struct byte_source *src, unsigned width, - unsigned suppress_flag, PLI_BYTE8 *name) + unsigned suppress_flag, ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle arg; char *strval = malloc(1); @@ -729,7 +729,7 @@ static int scan_format_string(vpiHandle callh, vpiHandle argv, */ static int scan_format_two_state(vpiHandle callh, vpiHandle argv, struct byte_source *src, unsigned width, - unsigned suppress_flag, PLI_BYTE8 *name) + unsigned suppress_flag, ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle arg; p_vpi_vecval val_ptr; @@ -868,7 +868,7 @@ static int scan_format_two_state(vpiHandle callh, vpiHandle argv, */ static int scan_format_four_state(vpiHandle callh, vpiHandle argv, struct byte_source *src, unsigned width, - unsigned suppress_flag, PLI_BYTE8 *name) + unsigned suppress_flag, ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle arg; p_vpi_vecval val_ptr; @@ -1006,7 +1006,7 @@ static int scan_format_four_state(vpiHandle callh, vpiHandle argv, * passed to this function, which processes the rest of the function. */ static int scan_format(vpiHandle callh, struct byte_source*src, vpiHandle argv, - PLI_BYTE8 *name) + ICARUS_VPI_CONST PLI_BYTE8 *name) { s_vpi_value val; vpiHandle item; diff --git a/vpi/v2009_enum.c b/vpi/v2009_enum.c index be9aaa9fa..a8983e28a 100644 --- a/vpi/v2009_enum.c +++ b/vpi/v2009_enum.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2010-2018 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 @@ -226,7 +226,7 @@ static void fill_handle_with_init(vpiHandle arg, int is_two_state) /* * Implement the next()/prev() enumeration methods. */ -static PLI_INT32 ivl_enum_method_next_prev_calltf(PLI_BYTE8*name) +static PLI_INT32 ivl_enum_method_next_prev_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) { vpiHandle sys = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, sys); @@ -431,7 +431,7 @@ static PLI_INT32 ivl_enum_method_name_compiletf(ICARUS_VPI_CONST PLI_BYTE8*name) /* * Implement the name() enumeration method. */ -static PLI_INT32 ivl_enum_method_name_calltf(PLI_BYTE8*name) +static PLI_INT32 ivl_enum_method_name_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) { vpiHandle sys = vpi_handle(vpiSysTfCall, 0); vpiHandle argv = vpi_iterate(vpiArgument, sys); diff --git a/vpi/vams_simparam.c b/vpi/vams_simparam.c index 6d5e8b30d..2de9818a9 100644 --- a/vpi/vams_simparam.c +++ b/vpi/vams_simparam.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2008-2014 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2008-2018 Cary R. (cygcary@yahoo.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -247,7 +247,7 @@ static PLI_INT32 simparam_str_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name_ext) return 0; } -static PLI_INT32 simparam_str_sizetf(PLI_BYTE8 *name_ext) +static PLI_INT32 simparam_str_sizetf(ICARUS_VPI_CONST PLI_BYTE8 *name_ext) { (void) name_ext; /* Parameter is not used. */ return MAX_STRING_RESULT; /* 128 characters max! */ diff --git a/vpi_user.h b/vpi_user.h index 8fb8b12d8..db0a9bd5f 100644 --- a/vpi_user.h +++ b/vpi_user.h @@ -1,7 +1,7 @@ #ifndef VPI_USER_H #define VPI_USER_H /* - * Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2018 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 @@ -46,7 +46,9 @@ EXTERN_C_START # include # include "_pli_types.h" +#ifndef ICARUS_VPI_CONST #define ICARUS_VPI_CONST +#endif #ifdef __cplusplus typedef class __vpiHandle *vpiHandle; #else @@ -63,7 +65,7 @@ typedef struct t_vpi_systf_data { const char *tfname; PLI_INT32 (*calltf) (ICARUS_VPI_CONST PLI_BYTE8*); PLI_INT32 (*compiletf)(ICARUS_VPI_CONST PLI_BYTE8*); - PLI_INT32 (*sizetf) (PLI_BYTE8*); + PLI_INT32 (*sizetf) (ICARUS_VPI_CONST PLI_BYTE8*); ICARUS_VPI_CONST PLI_BYTE8 *user_data; } s_vpi_systf_data, *p_vpi_systf_data; @@ -466,7 +468,7 @@ typedef struct t_cb_data { p_vpi_time time; p_vpi_value value; PLI_INT32 index; - char *user_data; + ICARUS_VPI_CONST PLI_BYTE8 *user_data; } s_cb_data, *p_cb_data; #define cbValueChange 1 From b066a5815e3a96538658fd31fab7f70e1cb677f1 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 29 Sep 2018 21:22:17 +0100 Subject: [PATCH 574/595] Allow %c format to output null characters (GitHub issue #209) Currently $display et al. output nothing when the expression corresponding to a %c format specification has the value 0. As Verilog provides no other way to write raw bytes to a file, we should allow 0 values to be written. Other simulators allow this. --- vpi/sys_display.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/vpi/sys_display.c b/vpi/sys_display.c index 5ecc8c5b4..50d968b99 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2018 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 @@ -415,23 +415,23 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, } else { char ch = value.value.str[strlen(value.value.str)-1]; - /* If the default buffer is too small, make it big enough. */ - size = width + 1; - if (size > ini_size) result = realloc(result, size*sizeof(char)); - /* If the width is less than one then use a width of one. */ if (width < 1) width = 1; + size = width + 1; + assert(size <= ini_size); + if (ljust == 0) { if (width > 1) { - char *cp = malloc((width+1)*sizeof(char)); - memset(cp, (ld_zero == 1 ? '0': ' '), width-1); - cp[width-1] = ch; - cp[width] = '\0'; - sprintf(result, "%*s", width, cp); - free(cp); - } else sprintf(result, "%c", ch); - } else sprintf(result, "%-*c", width, ch); - size = strlen(result) + 1; + memset(result, (ld_zero == 1 ? '0': ' '), width-1); + } + result[width-1] = ch; + } else { + result[0] = ch; + if (width > 1) { + memset(result+1, ' ', width-1); + } + } + result[width] = '\0'; } } break; From 603ff303f5795c5cd1a548b32b438dae539536c7 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 29 Sep 2018 23:25:04 +0100 Subject: [PATCH 575/595] Cleanly terminate vvp on SIGHUP or SIGTERM (GitHub issue #203). --- vvp/schedule.cc | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/vvp/schedule.cc b/vvp/schedule.cc index b2fc085a3..5b2244cc3 100644 --- a/vvp/schedule.cc +++ b/vvp/schedule.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2018 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 @@ -606,27 +606,36 @@ bool schedule_stopped(void) /* * These are the signal handling infrastructure. The SIGINT signal - * leads to an implicit $stop. + * leads to an implicit $stop. The SIGHUP and SIGTERM signals lead + * to an implicit $finish. */ -extern "C" void signals_handler(int) +extern bool stop_is_finish; + +extern "C" void signals_handler(int signum) { #ifdef __MINGW32__ // Windows implements the original UNIX semantics for signal, // so we have to re-establish the signal handler each time a // signal is caught. - signal(SIGINT, &signals_handler); + signal(signum, &signals_handler); #endif + if (signum != SIGINT) + stop_is_finish = true; schedule_stopped_flag = true; } static void signals_capture(void) { - signal(SIGINT, &signals_handler); + signal(SIGHUP, &signals_handler); + signal(SIGINT, &signals_handler); + signal(SIGTERM, &signals_handler); } static void signals_revert(void) { - signal(SIGINT, SIG_DFL); + signal(SIGHUP, SIG_DFL); + signal(SIGINT, SIG_DFL); + signal(SIGTERM, SIG_DFL); } /* From 542fe2cf77f0e99032f75b8c651156b41da338f7 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 6 Oct 2018 11:48:19 +0100 Subject: [PATCH 576/595] Enable checks for VPI const-correctness. Note we only want these enabled when building the compiler and runtime binaries. If we included the ICARUS_VPI_CONST definition in the global CPP_FLAGS, that would propagate to the flags used by iverilog-vpi, so would affect compilation of user VPI code. --- libveriuser/Makefile.in | 2 +- vpi/Makefile.in | 2 +- vvp/Makefile.in | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/libveriuser/Makefile.in b/libveriuser/Makefile.in index bdc09330f..989d7c980 100644 --- a/libveriuser/Makefile.in +++ b/libveriuser/Makefile.in @@ -47,7 +47,7 @@ LDRELOCFLAGS = @LDRELOCFLAGS@ LDTARGETFLAGS = @LDTARGETFLAGS@ -CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ @PICFLAG@ +CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ -DICARUS_VPI_CONST=const @PICFLAG@ CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@ A = a_close.o a_compare_handles.o a_configure.o a_fetch_argc.o \ diff --git a/vpi/Makefile.in b/vpi/Makefile.in index cf62786e2..a2ee88145 100644 --- a/vpi/Makefile.in +++ b/vpi/Makefile.in @@ -45,7 +45,7 @@ else INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/.. endif -CPPFLAGS = $(INCLUDE_PATH) @file64_support@ @CPPFLAGS@ @DEFS@ @PICFLAG@ +CPPFLAGS = $(INCLUDE_PATH) @file64_support@ @CPPFLAGS@ @DEFS@ -DICARUS_VPI_CONST=const @PICFLAG@ CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@ CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@ LDFLAGS = @LDFLAGS@ diff --git a/vvp/Makefile.in b/vvp/Makefile.in index faae3736a..d5a1c7f92 100644 --- a/vvp/Makefile.in +++ b/vvp/Makefile.in @@ -55,7 +55,7 @@ else INCLUDE_PATH = -I. -I.. -I$(srcdir) -I$(srcdir)/.. endif -CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ +CPPFLAGS = $(INCLUDE_PATH) @CPPFLAGS@ @DEFS@ -DICARUS_VPI_CONST=const CFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CC@ @CFLAGS@ CXXFLAGS = @WARNING_FLAGS@ @WARNING_FLAGS_CXX@ @CXXFLAGS@ LDFLAGS = @rdynamic@ @LDFLAGS@ From 78317a2799260c9a5baa227ff1768a12a47f181b Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 6 Oct 2018 17:15:31 +0100 Subject: [PATCH 577/595] Fix auto_ptr deprecated warnings when building with recent GCC. --- net_func_eval.cc | 8 ++++++-- pform_types.h | 22 +++++++++++++--------- vhdlpp/expression.h | 12 ++++++++---- 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/net_func_eval.cc b/net_func_eval.cc index 00790d692..f310af488 100644 --- a/net_func_eval.cc +++ b/net_func_eval.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2012-2018 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 @@ -23,6 +23,10 @@ # include # include "ivl_assert.h" +#if __cplusplus < 201103L +#define unique_ptr auto_ptr +#endif + using namespace std; /* @@ -1018,7 +1022,7 @@ NetExpr* NetESignal::evaluate_function(const LineInfo&loc, NetExpr* NetETernary::evaluate_function(const LineInfo&loc, map&context_map) const { - auto_ptr cval (cond_->evaluate_function(loc, context_map)); + unique_ptr cval (cond_->evaluate_function(loc, context_map)); switch (const_logical(cval.get())) { diff --git a/pform_types.h b/pform_types.h index 22dab4b46..0bd87d817 100644 --- a/pform_types.h +++ b/pform_types.h @@ -1,7 +1,7 @@ #ifndef IVL_pform_types_H #define IVL_pform_types_H /* - * Copyright (c) 2007-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2007-2018 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 @@ -33,6 +33,10 @@ # include # include +#if __cplusplus < 201103L +#define unique_ptr auto_ptr +#endif + /* * parse-form types. */ @@ -117,7 +121,7 @@ struct name_component_t { struct decl_assignment_t { perm_string name; std::listindex; - std::auto_ptr expr; + std::unique_ptr expr; }; struct pform_tf_port_t { @@ -170,14 +174,14 @@ struct enum_type_t : public data_type_t { ivl_variable_type_t base_type; bool signed_flag; bool integer_flag; // True if "integer" was used - std::auto_ptr< list > range; - std::auto_ptr< list > names; + std::unique_ptr< list > range; + std::unique_ptr< list > names; LineInfo li; }; struct struct_member_t : public LineInfo { - std::auto_ptr type; - std::auto_ptr< list > names; + std::unique_ptr type; + std::unique_ptr< list > names; void pform_dump(std::ostream&out, unsigned indent) const; }; @@ -188,7 +192,7 @@ struct struct_type_t : public data_type_t { bool packed_flag; bool union_flag; - std::auto_ptr< list > members; + std::unique_ptr< list > members; }; struct atom2_type_t : public data_type_t { @@ -234,7 +238,7 @@ struct vector_type_t : public data_type_t { bool reg_flag; // True if "reg" was used bool integer_flag; // True if "integer" was used bool implicit_flag; // True if this type is implicitly logic/reg - std::auto_ptr< list > pdims; + std::unique_ptr< list > pdims; }; struct array_base_t : public data_type_t { @@ -243,7 +247,7 @@ struct array_base_t : public data_type_t { : base_type(btype), dims(pd) { } data_type_t*base_type; - std::auto_ptr< list > dims; + std::unique_ptr< list > dims; }; /* diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index d31955a89..35f23e22c 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -1,7 +1,7 @@ #ifndef IVL_expression_H #define IVL_expression_H /* - * Copyright (c) 2011-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2011-2018 Stephen Williams (steve@icarus.com) * Copyright CERN 2015 / Stephen Williams (steve@icarus.com), * Copyright CERN 2016 * @author Maciej Suminski (maciej.suminski@cern.ch) @@ -39,6 +39,10 @@ class VTypeArray; class VTypePrimitive; class ExpName; +#if __cplusplus < 201103L +#define unique_ptr auto_ptr +#endif + /* * Helper class to recursively traverse an expression tree * (i.e. complex expressions). @@ -273,8 +277,8 @@ class ExpAggregate : public Expression { void dump(ostream&out, int indent) const; private: - std::auto_ptrexpr_; - std::auto_ptr range_; + std::unique_ptrexpr_; + std::unique_ptr range_; private: // not implemented choice_t& operator= (const choice_t&); }; @@ -778,7 +782,7 @@ class ExpName : public Expression { private: Expression*index(unsigned int number) const; - std::auto_ptr prefix_; + std::unique_ptr prefix_; perm_string name_; std::list*indices_; }; From 7fa6eaef0a523a9ccaa5064316a1d6f34ce3b9ee Mon Sep 17 00:00:00 2001 From: Cary R Date: Sat, 6 Oct 2018 09:24:31 -0700 Subject: [PATCH 578/595] Update to latest GTKWAve files --- vpi/fstapi.c | 280 +++++++++++++++++++++++------------------------ vpi/lxt2_write.c | 22 ++-- vpi/lxt2_write.h | 3 +- vpi/lz4.c | 3 + vpi/wavealloca.h | 23 +++- 5 files changed, 174 insertions(+), 157 deletions(-) diff --git a/vpi/fstapi.c b/vpi/fstapi.c index 386d6705e..13342fa7d 100644 --- a/vpi/fstapi.c +++ b/vpi/fstapi.c @@ -283,7 +283,7 @@ static char *fstRealpath(const char *path, char *resolved_path) #if (defined(__MACH__) && defined(__APPLE__)) if(!resolved_path) { - resolved_path = malloc(PATH_MAX+1); /* fixes bug on Leopard when resolved_path == NULL */ + resolved_path = (unsigned char *)malloc(PATH_MAX+1); /* fixes bug on Leopard when resolved_path == NULL */ } #endif @@ -293,7 +293,7 @@ return(realpath(path, resolved_path)); #ifdef __MINGW32__ if(!resolved_path) { - resolved_path = malloc(PATH_MAX+1); + resolved_path = (unsigned char *)malloc(PATH_MAX+1); } return(_fullpath(resolved_path, path, PATH_MAX)); #else @@ -317,7 +317,7 @@ static void *fstMmap2(size_t __len, int __fd, off_t __off) { (void)__off; -unsigned char *pnt = malloc(__len); +unsigned char *pnt = (unsigned char *)malloc(__len); off_t cur_offs = lseek(__fd, 0, SEEK_CUR); size_t i; @@ -804,7 +804,7 @@ if(rc<0) { xc->fseek_failed = 1; #ifdef FST_DEBUG - fprintf(stderr, FST_APIMESS"Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence); + fprintf(stderr, FST_APIMESS"Seek to #%" PRId64 " (whence = %d) failed!\n", offset, whence); perror("Why"); #endif } @@ -970,12 +970,12 @@ fflush(xc->handle); if(!xc->valpos_mem) { fflush(xc->valpos_handle); - xc->valpos_mem = fstMmap(NULL, xc->maxhandle * 4 * sizeof(uint32_t), PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->valpos_handle), 0); + xc->valpos_mem = (uint32_t *)fstMmap(NULL, xc->maxhandle * 4 * sizeof(uint32_t), PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->valpos_handle), 0); } if(!xc->curval_mem) { fflush(xc->curval_handle); - xc->curval_mem = fstMmap(NULL, xc->maxvalpos, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->curval_handle), 0); + xc->curval_mem = (unsigned char *)fstMmap(NULL, xc->maxvalpos, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->curval_handle), 0); } } @@ -1106,7 +1106,7 @@ xc->next_huge_break = FST_ACTIVATE_HUGE_BREAK; */ void *fstWriterCreate(const char *nam, int use_compressed_hier) { -struct fstWriterContext *xc = calloc(1, sizeof(struct fstWriterContext)); +struct fstWriterContext *xc = (struct fstWriterContext *)calloc(1, sizeof(struct fstWriterContext)); xc->compress_hier = use_compressed_hier; fstDetermineBreakSize(xc); @@ -1120,7 +1120,7 @@ if((!nam)|| else { int flen = strlen(nam); - char *hf = calloc(1, flen + 6); + char *hf = (char *)calloc(1, flen + 6); memcpy(hf, nam, flen); strcpy(hf + flen, ".hier"); @@ -1131,7 +1131,7 @@ if((!nam)|| xc->curval_handle = tmpfile_open(&xc->curval_handle_nam); /* .bits */ xc->tchn_handle = tmpfile_open(&xc->tchn_handle_nam); /* .tchn */ xc->vchg_alloc_siz = xc->fst_break_size + xc->fst_break_add_size; - xc->vchg_mem = malloc(xc->vchg_alloc_siz); + xc->vchg_mem = (unsigned char *)malloc(xc->vchg_alloc_siz); if(xc->hier_handle && xc->geom_handle && xc->valpos_handle && xc->curval_handle && xc->vchg_mem && xc->tchn_handle) { @@ -1180,7 +1180,7 @@ if(xc) int rc; destlen = xc->maxvalpos; - dmem = malloc(compressBound(destlen)); + dmem = (unsigned char *)malloc(compressBound(destlen)); rc = compress2(dmem, &destlen, xc->curval_mem, xc->maxvalpos, 4); /* was 9...which caused performance drag on traces with many signals */ fputc(FST_BL_SKIP, xc->handle); /* temporarily tag the section, use FST_BL_VCDATA on finalize */ @@ -1269,7 +1269,7 @@ if((xc->vchg_siz <= 1)||(xc->already_in_flush)) return; xc->already_in_flush = 1; /* should really do this with a semaphore */ xc->section_header_only = 0; -scratchpad = malloc(xc->vchg_siz); +scratchpad = (unsigned char *)malloc(xc->vchg_siz); vchg_mem = xc->vchg_mem; @@ -1279,7 +1279,7 @@ fputc(xc->fourpack ? '4' : (xc->fastpack ? 'F' : 'Z'), f); fpos = 1; packmemlen = 1024; /* maintain a running "longest" allocation to */ -packmem = malloc(packmemlen); /* prevent continual malloc...free every loop iter */ +packmem = (unsigned char *)malloc(packmemlen); /* prevent continual malloc...free every loop iter */ for(i=0;imaxhandle;i++) { @@ -1399,13 +1399,13 @@ for(i=0;imaxhandle;i++) idx = ((vm4ip[1]+7) & ~7); switch(vm4ip[1] & 7) { - case 0: do { acc = (pnt[idx+7-8] & 1) << 0; - case 7: acc |= (pnt[idx+6-8] & 1) << 1; - case 6: acc |= (pnt[idx+5-8] & 1) << 2; - case 5: acc |= (pnt[idx+4-8] & 1) << 3; - case 4: acc |= (pnt[idx+3-8] & 1) << 4; - case 3: acc |= (pnt[idx+2-8] & 1) << 5; - case 2: acc |= (pnt[idx+1-8] & 1) << 6; + case 0: do { acc = (pnt[idx+7-8] & 1) << 0; /* fallthrough */ + case 7: acc |= (pnt[idx+6-8] & 1) << 1; /* fallthrough */ + case 6: acc |= (pnt[idx+5-8] & 1) << 2; /* fallthrough */ + case 5: acc |= (pnt[idx+4-8] & 1) << 3; /* fallthrough */ + case 4: acc |= (pnt[idx+3-8] & 1) << 4; /* fallthrough */ + case 3: acc |= (pnt[idx+2-8] & 1) << 5; /* fallthrough */ + case 2: acc |= (pnt[idx+1-8] & 1) << 6; /* fallthrough */ case 1: acc |= (pnt[idx+0-8] & 1) << 7; *(--scratchpnt) = acc; idx -= 8; @@ -1441,7 +1441,7 @@ for(i=0;imaxhandle;i++) else { free(packmem); - dmem = packmem = malloc(compressBound(packmemlen = wrlen)); + dmem = packmem = (unsigned char *)malloc(compressBound(packmemlen = wrlen)); } rc = compress2(dmem, &destlen, scratchpnt, wrlen, 4); @@ -1496,7 +1496,7 @@ for(i=0;imaxhandle;i++) else { free(packmem); - dmem = packmem = malloc(packmemlen = (wrlen * 2) + 2); + dmem = packmem = (unsigned char *)malloc(packmemlen = (wrlen * 2) + 2); } rc = (xc->fourpack) ? LZ4_compress((char *)scratchpnt, (char *)dmem, wrlen) : fastlz_compress(scratchpnt, wrlen, dmem); @@ -1678,11 +1678,11 @@ fflush(xc->tchn_handle); tlen = ftello(xc->tchn_handle); fstWriterFseeko(xc, xc->tchn_handle, 0, SEEK_SET); -tmem = fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->tchn_handle), 0); +tmem = (unsigned char *)fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->tchn_handle), 0); if(tmem) { unsigned long destlen = tlen; - unsigned char *dmem = malloc(compressBound(destlen)); + unsigned char *dmem = (unsigned char *)malloc(compressBound(destlen)); int rc = compress2(dmem, &destlen, tmem, tlen, 9); if((rc == Z_OK) && (((off_t)destlen) < tlen)) @@ -1781,7 +1781,7 @@ struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc->parallel_enabled) { - struct fstWriterContext *xc2 = malloc(sizeof(struct fstWriterContext)); + struct fstWriterContext *xc2 = (struct fstWriterContext *)malloc(sizeof(struct fstWriterContext)); unsigned int i; pthread_mutex_lock(&xc->mutex); @@ -1790,16 +1790,16 @@ if(xc->parallel_enabled) xc->xc_parent = xc; memcpy(xc2, xc, sizeof(struct fstWriterContext)); - xc2->valpos_mem = malloc(xc->maxhandle * 4 * sizeof(uint32_t)); + xc2->valpos_mem = (uint32_t *)malloc(xc->maxhandle * 4 * sizeof(uint32_t)); memcpy(xc2->valpos_mem, xc->valpos_mem, xc->maxhandle * 4 * sizeof(uint32_t)); /* curval mem is updated in the thread */ #ifdef FST_REMOVE_DUPLICATE_VC - xc2->curval_mem = malloc(xc->maxvalpos); + xc2->curval_mem = (unsigned char *)malloc(xc->maxvalpos); memcpy(xc2->curval_mem, xc->curval_mem, xc->maxvalpos); #endif - xc->vchg_mem = malloc(xc->vchg_alloc_siz); + xc->vchg_mem = (unsigned char *)malloc(xc->vchg_alloc_siz); xc->vchg_mem[0] = '!'; xc->vchg_siz = 1; @@ -1908,11 +1908,11 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) /* write out geom section */ fflush(xc->geom_handle); tlen = ftello(xc->geom_handle); - tmem = fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->geom_handle), 0); + tmem = (unsigned char *)fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->geom_handle), 0); if(tmem) { unsigned long destlen = tlen; - unsigned char *dmem = malloc(compressBound(destlen)); + unsigned char *dmem = (unsigned char *)malloc(compressBound(destlen)); int rc = compress2(dmem, &destlen, tmem, tlen, 9); if((rc != Z_OK) || (((off_t)destlen) > tlen)) @@ -1980,7 +1980,7 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) int zfd; int fourpack_duo = 0; #ifndef __MINGW32__ - char *fnam = malloc(strlen(xc->filename) + 5 + 1); + char *fnam = (char *)malloc(strlen(xc->filename) + 5 + 1); #endif fixup_offs = ftello(xc->handle); @@ -1991,7 +1991,7 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) if(!xc->fourpack) { - unsigned char *mem = malloc(FST_GZIO_LEN); + unsigned char *mem = (unsigned char *)malloc(FST_GZIO_LEN); zfd = dup(fileno(xc->handle)); fflush(xc->handle); zhandle = gzdopen(zfd, "wb4"); @@ -2022,8 +2022,8 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) fflush(xc->handle); lz4_maxlen = LZ4_compressBound(xc->hier_file_len); - mem = malloc(lz4_maxlen); - hmem = fstMmap(NULL, xc->hier_file_len, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->hier_handle), 0); + mem = (unsigned char *)malloc(lz4_maxlen); + hmem = (unsigned char *)fstMmap(NULL, xc->hier_file_len, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->hier_handle), 0); packed_len = LZ4_compress((char *)hmem, (char *)mem, xc->hier_file_len); fstMunmap(hmem, xc->hier_file_len); @@ -2036,7 +2036,7 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) int packed_len_duo; lz4_maxlen_duo = LZ4_compressBound(packed_len); - mem_duo = malloc(lz4_maxlen_duo); + mem_duo = (unsigned char *)malloc(lz4_maxlen_duo); packed_len_duo = LZ4_compress((char *)mem, (char *)mem_duo, packed_len); fstWriterVarint(xc->handle, packed_len); /* 1st round compressed length */ @@ -2096,7 +2096,7 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) FILE *fp; off_t offpnt, uclen; int flen = strlen(xc->filename); - char *hf = calloc(1, flen + 5); + char *hf = (char *)calloc(1, flen + 5); strcpy(hf, xc->filename); strcpy(hf+flen, ".pak"); @@ -2104,7 +2104,7 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) if(fp) { - void *dsth; + gzFile dsth; int zfd; char gz_membuf[FST_GZIO_LEN]; @@ -2586,7 +2586,7 @@ if(xc && nam) xc->vchg_alloc_siz = xc->fst_break_size + xc->fst_break_add_size; if(xc->vchg_mem) { - xc->vchg_mem = realloc(xc->vchg_mem, xc->vchg_alloc_siz); + xc->vchg_mem = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz); } } } @@ -2758,7 +2758,7 @@ if((xc) && (handle <= xc->maxhandle)) if((fpos + len + 10) > xc->vchg_alloc_siz) { xc->vchg_alloc_siz += (xc->fst_break_add_size + len); /* +len added in the case of extremely long vectors and small break add sizes */ - xc->vchg_mem = realloc(xc->vchg_mem, xc->vchg_alloc_siz); + xc->vchg_mem = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz); if(!xc->vchg_mem) { fprintf(stderr, FST_APIMESS"Could not realloc() in fstWriterEmitValueChange, exiting.\n"); @@ -2872,7 +2872,7 @@ if((xc) && (handle <= xc->maxhandle)) if((fpos + len + 10 + 5) > xc->vchg_alloc_siz) { xc->vchg_alloc_siz += (xc->fst_break_add_size + len + 5); /* +len added in the case of extremely long vectors and small break add sizes */ - xc->vchg_mem = realloc(xc->vchg_mem, xc->vchg_alloc_siz); + xc->vchg_mem = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz); if(!xc->vchg_mem) { fprintf(stderr, FST_APIMESS"Could not realloc() in fstWriterEmitVariableLengthValueChange, exiting.\n"); @@ -2949,7 +2949,7 @@ struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) { - struct fstBlackoutChain *b = calloc(1, sizeof(struct fstBlackoutChain)); + struct fstBlackoutChain *b = (struct fstBlackoutChain *)calloc(1, sizeof(struct fstBlackoutChain)); b->tim = xc->curtime; b->active = (enable != 0); @@ -3120,7 +3120,7 @@ if(rc<0) { xc->fseek_failed = 1; #ifdef FST_DEBUG - fprintf(stderr, FST_APIMESS"Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence); + fprintf(stderr, FST_APIMESS"Seek to #%" PRId64 " (whence = %d) failed!\n", offset, whence); perror("Why"); #endif } @@ -3248,12 +3248,12 @@ const char *fstReaderPushScope(void *ctx, const char *nam, void *user_info) struct fstReaderContext *xc = (struct fstReaderContext *)ctx; if(xc) { - struct fstCurrHier *ch = malloc(sizeof(struct fstCurrHier)); + struct fstCurrHier *ch = (struct fstCurrHier *)malloc(sizeof(struct fstCurrHier)); int chl = xc->curr_hier ? xc->curr_hier->len : 0; int len = chl + 1 + strlen(nam); if(len >= xc->flat_hier_alloc_len) { - xc->curr_flat_hier_nam = xc->curr_flat_hier_nam ? realloc(xc->curr_flat_hier_nam, len+1) : malloc(len+1); + xc->curr_flat_hier_nam = xc->curr_flat_hier_nam ? (char *)realloc(xc->curr_flat_hier_nam, len+1) : (char *)malloc(len+1); } if(chl) @@ -3473,7 +3473,7 @@ return(xc ? xc->date : NULL); int fstReaderGetFileType(void *ctx) { struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -return(xc ? xc->filetype : FST_FT_VERILOG); +return(xc ? (int)xc->filetype : (int)FST_FT_VERILOG); } @@ -3606,8 +3606,8 @@ int pass_status = 1; if(!xc->fh) { off_t offs_cache = ftello(xc->f); - char *fnam = malloc(strlen(xc->filename) + 6 + 16 + 32 + 1); - unsigned char *mem = malloc(FST_GZIO_LEN); + char *fnam = (char *)malloc(strlen(xc->filename) + 6 + 16 + 32 + 1); + unsigned char *mem = (unsigned char *)malloc(FST_GZIO_LEN); off_t hl, uclen; off_t clen = 0; gzFile zhandle = NULL; @@ -3704,8 +3704,8 @@ if(!xc->fh) else if(htyp == FST_BL_HIER_LZ4DUO) { - unsigned char *lz4_cmem = malloc(clen); - unsigned char *lz4_ucmem = malloc(uclen); + unsigned char *lz4_cmem = (unsigned char *)malloc(clen); + unsigned char *lz4_ucmem = (unsigned char *)malloc(uclen); unsigned char *lz4_ucmem2; uint64_t uclen2; int skiplen2 = 0; @@ -3713,7 +3713,7 @@ if(!xc->fh) fstFread(lz4_cmem, clen, 1, xc->f); uclen2 = fstGetVarint64(lz4_cmem, &skiplen2); - lz4_ucmem2 = malloc(uclen2); + lz4_ucmem2 = (unsigned char *)malloc(uclen2); pass_status = (uclen2 == (uint64_t)LZ4_decompress_safe_partial ((char *)lz4_cmem + skiplen2, (char *)lz4_ucmem2, clen - skiplen2, uclen2, uclen2)); if(pass_status) { @@ -3732,8 +3732,8 @@ if(!xc->fh) else if(htyp == FST_BL_HIER_LZ4) { - unsigned char *lz4_cmem = malloc(clen); - unsigned char *lz4_ucmem = malloc(uclen); + unsigned char *lz4_cmem = (unsigned char *)malloc(clen); + unsigned char *lz4_ucmem = (unsigned char *)malloc(uclen); fstFread(lz4_cmem, clen, 1, xc->f); pass_status = (uclen == LZ4_decompress_safe_partial ((char *)lz4_cmem, (char *)lz4_ucmem, clen, uclen, uclen)); @@ -3970,7 +3970,7 @@ if(!xc->fh) } } -str = malloc(FST_ID_NAM_ATTR_SIZ+1); +str = (char *)malloc(FST_ID_NAM_ATTR_SIZ+1); if(fv) { @@ -3979,40 +3979,40 @@ if(fv) fprintf(fv, "$date\n\t%s\n$end\n", xc->date); fprintf(fv, "$version\n\t%s\n$end\n", xc->version); - if(xc->timezero) fprintf(fv, "$timezero\n\t%"PRId64"\n$end\n", xc->timezero); + if(xc->timezero) fprintf(fv, "$timezero\n\t%" PRId64 "\n$end\n", xc->timezero); switch(xc->timescale) { case 2: time_scale = 100; time_dimension[0] = 0; break; - case 1: time_scale = 10; + case 1: time_scale = 10; /* fallthrough */ case 0: time_dimension[0] = 0; break; case -1: time_scale = 100; time_dimension[0] = 'm'; break; - case -2: time_scale = 10; + case -2: time_scale = 10; /* fallthrough */ case -3: time_dimension[0] = 'm'; break; case -4: time_scale = 100; time_dimension[0] = 'u'; break; - case -5: time_scale = 10; + case -5: time_scale = 10; /* fallthrough */ case -6: time_dimension[0] = 'u'; break; case -10: time_scale = 100; time_dimension[0] = 'p'; break; - case -11: time_scale = 10; + case -11: time_scale = 10; /* fallthrough */ case -12: time_dimension[0] = 'p'; break; case -13: time_scale = 100; time_dimension[0] = 'f'; break; - case -14: time_scale = 10; + case -14: time_scale = 10; /* fallthrough */ case -15: time_dimension[0] = 'f'; break; case -16: time_scale = 100; time_dimension[0] = 'a'; break; - case -17: time_scale = 10; + case -17: time_scale = 10; /* fallthrough */ case -18: time_dimension[0] = 'a'; break; case -19: time_scale = 100; time_dimension[0] = 'z'; break; - case -20: time_scale = 10; + case -20: time_scale = 10; /* fallthrough */ case -21: time_dimension[0] = 'z'; break; case -7: time_scale = 100; time_dimension[0] = 'n'; break; - case -8: time_scale = 10; + case -8: time_scale = 10; /* fallthrough */ case -9: default: time_dimension[0] = 'n'; break; } @@ -4024,10 +4024,10 @@ xc->maxhandle = 0; xc->num_alias = 0; free(xc->signal_lens); -xc->signal_lens = malloc(num_signal_dyn*sizeof(uint32_t)); +xc->signal_lens = (uint32_t *)malloc(num_signal_dyn*sizeof(uint32_t)); free(xc->signal_typs); -xc->signal_typs = malloc(num_signal_dyn*sizeof(unsigned char)); +xc->signal_typs = (unsigned char *)malloc(num_signal_dyn*sizeof(unsigned char)); fstReaderFseeko(xc, xc->fh, 0, SEEK_SET); while(!feof(xc->fh)) @@ -4072,13 +4072,13 @@ while(!feof(xc->fh)) switch(attrtype) { case FST_AT_ARRAY: if((subtype < FST_AR_NONE) || (subtype > FST_AR_MAX)) subtype = FST_AR_NONE; - fprintf(fv, "$attrbegin %s %s %s %"PRId64" $end\n", attrtypes[attrtype], arraytypes[subtype], str, attrarg); + fprintf(fv, "$attrbegin %s %s %s %" PRId64 " $end\n", attrtypes[attrtype], arraytypes[subtype], str, attrarg); break; case FST_AT_ENUM: if((subtype < FST_EV_SV_INTEGER) || (subtype > FST_EV_MAX)) subtype = FST_EV_SV_INTEGER; - fprintf(fv, "$attrbegin %s %s %s %"PRId64" $end\n", attrtypes[attrtype], enumvaluetypes[subtype], str, attrarg); + fprintf(fv, "$attrbegin %s %s %s %" PRId64 " $end\n", attrtypes[attrtype], enumvaluetypes[subtype], str, attrarg); break; case FST_AT_PACK: if((subtype < FST_PT_NONE) || (subtype > FST_PT_MAX)) subtype = FST_PT_NONE; - fprintf(fv, "$attrbegin %s %s %s %"PRId64" $end\n", attrtypes[attrtype], packtypes[subtype], str, attrarg); + fprintf(fv, "$attrbegin %s %s %s %" PRId64 " $end\n", attrtypes[attrtype], packtypes[subtype], str, attrarg); break; case FST_AT_MISC: default: attrtype = FST_AT_MISC; @@ -4093,11 +4093,11 @@ while(!feof(xc->fh)) int sidx_skiplen_dummy = 0; uint64_t sidx = fstGetVarint64((unsigned char *)str, &sidx_skiplen_dummy); - fprintf(fv, "$attrbegin %s %02x %"PRId64" %"PRId64" $end\n", attrtypes[attrtype], subtype, sidx, attrarg); + fprintf(fv, "$attrbegin %s %02x %" PRId64 " %" PRId64 " $end\n", attrtypes[attrtype], subtype, sidx, attrarg); } else { - fprintf(fv, "$attrbegin %s %02x %s %"PRId64" $end\n", attrtypes[attrtype], subtype, str, attrarg); + fprintf(fv, "$attrbegin %s %02x %s %" PRId64 " $end\n", attrtypes[attrtype], subtype, str, attrarg); } } break; @@ -4155,8 +4155,8 @@ while(!feof(xc->fh)) if(xc->maxhandle == num_signal_dyn) { num_signal_dyn *= 2; - xc->signal_lens = realloc(xc->signal_lens, num_signal_dyn*sizeof(uint32_t)); - xc->signal_typs = realloc(xc->signal_typs, num_signal_dyn*sizeof(unsigned char)); + xc->signal_lens = (uint32_t *)realloc(xc->signal_lens, num_signal_dyn*sizeof(uint32_t)); + xc->signal_typs = (unsigned char *)realloc(xc->signal_typs, num_signal_dyn*sizeof(unsigned char)); } xc->signal_lens[xc->maxhandle] = len; xc->signal_typs[xc->maxhandle] = vartype; @@ -4177,7 +4177,7 @@ while(!feof(xc->fh)) char vcdid_buf[16]; uint32_t modlen = (vartype != FST_VT_VCD_PORT) ? len : ((len - 2) / 3); fstVcdID(vcdid_buf, xc->maxhandle+1); - fprintf(fv, "$var %s %"PRIu32" %s %s $end\n", vartypes[vartype], modlen, vcdid_buf, str); + fprintf(fv, "$var %s %" PRIu32 " %s %s $end\n", vartypes[vartype], modlen, vcdid_buf, str); } xc->maxhandle++; } @@ -4193,7 +4193,7 @@ while(!feof(xc->fh)) char vcdid_buf[16]; uint32_t modlen = (vartype != FST_VT_VCD_PORT) ? len : ((len - 2) / 3); fstVcdID(vcdid_buf, alias); - fprintf(fv, "$var %s %"PRIu32" %s %s $end\n", vartypes[vartype], modlen, vcdid_buf, str); + fprintf(fv, "$var %s %" PRIu32 " %s %s $end\n", vartypes[vartype], modlen, vcdid_buf, str); } xc->num_alias++; } @@ -4208,14 +4208,14 @@ if(fv) fprintf(fv, "$enddefinitions $end\n"); maxhandle_scanbuild = xc->maxhandle ? xc->maxhandle : 1; /*scan-build warning suppression, in reality we have at least one signal */ -xc->signal_lens = realloc(xc->signal_lens, maxhandle_scanbuild*sizeof(uint32_t)); -xc->signal_typs = realloc(xc->signal_typs, maxhandle_scanbuild*sizeof(unsigned char)); +xc->signal_lens = (uint32_t *)realloc(xc->signal_lens, maxhandle_scanbuild*sizeof(uint32_t)); +xc->signal_typs = (unsigned char *)realloc(xc->signal_typs, maxhandle_scanbuild*sizeof(unsigned char)); free(xc->process_mask); -xc->process_mask = calloc(1, (maxhandle_scanbuild+7)/8); +xc->process_mask = (unsigned char *)calloc(1, (maxhandle_scanbuild+7)/8); free(xc->temp_signal_value_buf); -xc->temp_signal_value_buf = malloc(xc->longest_signal_value_len + 1); +xc->temp_signal_value_buf = (unsigned char *)malloc(xc->longest_signal_value_len + 1); xc->var_count = xc->maxhandle + xc->num_alias; @@ -4244,7 +4244,7 @@ if(sectype == FST_BL_ZWRAPPER) FILE *fcomp; off_t offpnt, uclen; char gz_membuf[FST_GZIO_LEN]; - void *zhandle; + gzFile zhandle; int zfd; int flen = strlen(xc->filename); char *hf; @@ -4254,7 +4254,7 @@ if(sectype == FST_BL_ZWRAPPER) if(!seclen) return(0); /* not finished compressing, this is a failed read */ - hf = calloc(1, flen + 16 + 32 + 1); + hf = (char *)calloc(1, flen + 16 + 32 + 1); sprintf(hf, "%s.upk_%d_%p", xc->filename, getpid(), (void *)xc); fcomp = fopen(hf, "w+b"); @@ -4417,7 +4417,7 @@ if(gzread_pass_status) { uint64_t clen = seclen - 24; uint64_t uclen = fstReaderUint64(xc->f); - unsigned char *ucdata = malloc(uclen); + unsigned char *ucdata = (unsigned char *)malloc(uclen); unsigned char *pnt = ucdata; unsigned int i; @@ -4426,11 +4426,11 @@ if(gzread_pass_status) xc->longest_signal_value_len = 32; /* arbitrarily set at 32...this is much longer than an expanded double */ free(xc->process_mask); - xc->process_mask = calloc(1, (xc->maxhandle+7)/8); + xc->process_mask = (unsigned char *)calloc(1, (xc->maxhandle+7)/8); if(clen != uclen) { - unsigned char *cdata = malloc(clen); + unsigned char *cdata = (unsigned char *)malloc(clen); unsigned long destlen = uclen; unsigned long sourcelen = clen; int rc; @@ -4452,9 +4452,9 @@ if(gzread_pass_status) } free(xc->signal_lens); - xc->signal_lens = malloc(sizeof(uint32_t) * xc->maxhandle); + xc->signal_lens = (uint32_t *)malloc(sizeof(uint32_t) * xc->maxhandle); free(xc->signal_typs); - xc->signal_typs = malloc(sizeof(unsigned char) * xc->maxhandle); + xc->signal_typs = (unsigned char *)malloc(sizeof(unsigned char) * xc->maxhandle); for(i=0;imaxhandle;i++) { @@ -4481,7 +4481,7 @@ if(gzread_pass_status) } free(xc->temp_signal_value_buf); - xc->temp_signal_value_buf = malloc(xc->longest_signal_value_len + 1); + xc->temp_signal_value_buf = (unsigned char *)malloc(xc->longest_signal_value_len + 1); free(ucdata); } @@ -4510,9 +4510,9 @@ if(gzread_pass_status) xc->num_blackouts = fstReaderVarint32(xc->f); free(xc->blackout_times); - xc->blackout_times = calloc(xc->num_blackouts, sizeof(uint64_t)); + xc->blackout_times = (uint64_t *)calloc(xc->num_blackouts, sizeof(uint64_t)); free(xc->blackout_activity); - xc->blackout_activity = calloc(xc->num_blackouts, sizeof(unsigned char)); + xc->blackout_activity = (unsigned char *)calloc(xc->num_blackouts, sizeof(unsigned char)); for(i=0;inum_blackouts;i++) { @@ -4547,7 +4547,7 @@ return(hdr_seen); void *fstReaderOpenForUtilitiesOnly(void) { -struct fstReaderContext *xc = calloc(1, sizeof(struct fstReaderContext)); +struct fstReaderContext *xc = (struct fstReaderContext *)calloc(1, sizeof(struct fstReaderContext)); return(xc); } @@ -4555,7 +4555,7 @@ return(xc); void *fstReaderOpen(const char *nam) { -struct fstReaderContext *xc = calloc(1, sizeof(struct fstReaderContext)); +struct fstReaderContext *xc = (struct fstReaderContext *)calloc(1, sizeof(struct fstReaderContext)); if((!nam)||(!(xc->f=fopen(nam, "rb")))) { @@ -4565,7 +4565,7 @@ if((!nam)||(!(xc->f=fopen(nam, "rb")))) else { int flen = strlen(nam); - char *hf = calloc(1, flen + 6); + char *hf = (char *)calloc(1, flen + 6); int rc; #if defined(__MINGW32__) || defined(FST_MACOSX) @@ -4704,9 +4704,9 @@ uint32_t mc_mem_len; /* corresponds to largest value encountered in chain_table_ if(!xc) return(0); -scatterptr = calloc(xc->maxhandle, sizeof(uint32_t)); -headptr = calloc(xc->maxhandle, sizeof(uint32_t)); -length_remaining = calloc(xc->maxhandle, sizeof(uint32_t)); +scatterptr = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t)); +headptr = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t)); +length_remaining = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t)); if(fv) { @@ -4768,7 +4768,7 @@ for(;;) mem_required_for_traversal = fstReaderUint64(xc->f); - mem_for_traversal = malloc(mem_required_for_traversal + 66); /* add in potential fastlz overhead */ + mem_for_traversal = (unsigned char *)malloc(mem_required_for_traversal + 66); /* add in potential fastlz overhead */ #ifdef FST_DEBUG fprintf(stderr, FST_APIMESS"sec: %u seclen: %d begtim: %d endtim: %d\n", secnum, (int)seclen, (int)beg_tim, (int)end_tim); @@ -4794,7 +4794,7 @@ for(;;) (int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems); #endif if(tsec_clen > seclen) break; /* corrupted tsec_clen: by definition it can't be larger than size of section */ - ucdata = malloc(tsec_uclen); + ucdata = (unsigned char *)malloc(tsec_uclen); if(!ucdata) break; /* malloc fail as tsec_uclen out of range from corrupted file */ destlen = tsec_uclen; sourcelen = tsec_clen; @@ -4803,7 +4803,7 @@ for(;;) if(tsec_uclen != tsec_clen) { - cdata = malloc(tsec_clen); + cdata = (unsigned char *)malloc(tsec_clen); fstFread(cdata, tsec_clen, 1, xc->f); rc = uncompress(ucdata, &destlen, cdata, sourcelen); @@ -4822,7 +4822,7 @@ for(;;) } free(time_table); - time_table = calloc(tsec_nitems, sizeof(uint64_t)); + time_table = (uint64_t *)calloc(tsec_nitems, sizeof(uint64_t)); tpnt = ucdata; tpval = 0; for(ti=0;tinum_blackouts)&&(cur_blackout != xc->num_blackouts)) @@ -4876,7 +4876,7 @@ for(;;) } else { - unsigned char *mc = malloc(frame_clen); + unsigned char *mc = (unsigned char *)malloc(frame_clen); int rc; unsigned long destlen = frame_uclen; @@ -5061,7 +5061,7 @@ for(;;) #ifdef FST_DEBUG fprintf(stderr, FST_APIMESS"indx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen); #endif - chain_cmem = malloc(chain_clen); + chain_cmem = (unsigned char *)malloc(chain_clen); if(!chain_cmem) goto block_err; fstReaderFseeko(xc, xc->f, indx_pos, SEEK_SET); fstFread(chain_cmem, chain_clen, 1, xc->f); @@ -5072,8 +5072,8 @@ for(;;) free(chain_table_lengths); vc_maxhandle_largest = vc_maxhandle; - chain_table = calloc((vc_maxhandle+1), sizeof(off_t)); - chain_table_lengths = calloc((vc_maxhandle+1), sizeof(uint32_t)); + chain_table = (off_t *)calloc((vc_maxhandle+1), sizeof(off_t)); + chain_table_lengths = (uint32_t *)calloc((vc_maxhandle+1), sizeof(uint32_t)); } if(!chain_table || !chain_table_lengths) goto block_err; @@ -5178,11 +5178,11 @@ for(;;) } #ifdef FST_DEBUG - fprintf(stderr, FST_APIMESS"decompressed chain idx len: %"PRIu32"\n", idx); + fprintf(stderr, FST_APIMESS"decompressed chain idx len: %" PRIu32 "\n", idx); #endif mc_mem_len = 16384; - mc_mem = malloc(mc_mem_len); /* buffer for compressed reads */ + mc_mem = (unsigned char *)malloc(mc_mem_len); /* buffer for compressed reads */ /* check compressed VC data */ if(idx > xc->maxhandle) idx = xc->maxhandle; @@ -5212,7 +5212,7 @@ for(;;) if(mc_mem_len < chain_table_lengths[i]) { free(mc_mem); - mc_mem = malloc(mc_mem_len = chain_table_lengths[i]); + mc_mem = (unsigned char *)malloc(mc_mem_len = chain_table_lengths[i]); } mc = mc_mem; @@ -5291,7 +5291,7 @@ for(;;) } } - wx_len = sprintf(wx_buf, "#%"PRIu64"\n", time_table[i]); + wx_len = sprintf(wx_buf, "#%" PRIu64 "\n", time_table[i]); fstWritex(xc, wx_buf, wx_len); if((xc->num_blackouts)&&(cur_blackout != xc->num_blackouts)) @@ -5391,7 +5391,7 @@ for(;;) vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); { - unsigned char *vesc = malloc(len*4 + 1); + unsigned char *vesc = (unsigned char *)malloc(len*4 + 1); int vlen = fstUtilityBinToEsc(vesc, vdata, len); fstWritex(xc, vesc, vlen); free(vesc); @@ -5718,7 +5718,7 @@ if(!xc->rvat_sig_offs) { uint32_t cur_offs = 0; - xc->rvat_sig_offs = calloc(xc->maxhandle, sizeof(uint32_t)); + xc->rvat_sig_offs = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t)); for(i=0;imaxhandle;i++) { xc->rvat_sig_offs[i] = cur_offs; @@ -5822,14 +5822,14 @@ tsec_nitems = fstReaderUint64(xc->f); fprintf(stderr, FST_APIMESS"time section unc: %d, com: %d (%d items)\n", (int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems); #endif -ucdata = malloc(tsec_uclen); +ucdata = (unsigned char *)malloc(tsec_uclen); destlen = tsec_uclen; sourcelen = tsec_clen; fstReaderFseeko(xc, xc->f, -24 - ((off_t)tsec_clen), SEEK_CUR); if(tsec_uclen != tsec_clen) { - cdata = malloc(tsec_clen); + cdata = (unsigned char *)malloc(tsec_clen); fstFread(cdata, tsec_clen, 1, xc->f); rc = uncompress(ucdata, &destlen, cdata, sourcelen); @@ -5847,7 +5847,7 @@ if(tsec_uclen != tsec_clen) fstFread(ucdata, tsec_uclen, 1, xc->f); } -xc->rvat_time_table = calloc(tsec_nitems, sizeof(uint64_t)); +xc->rvat_time_table = (uint64_t *)calloc(tsec_nitems, sizeof(uint64_t)); tpnt = ucdata; tpval = 0; for(ti=0;tif, blkpos+32, SEEK_SET); frame_uclen = fstReaderVarint64(xc->f); frame_clen = fstReaderVarint64(xc->f); xc->rvat_frame_maxhandle = fstReaderVarint64(xc->f); -xc->rvat_frame_data = malloc(frame_uclen); +xc->rvat_frame_data = (unsigned char *)malloc(frame_uclen); if(frame_uclen == frame_clen) { @@ -5874,7 +5874,7 @@ if(frame_uclen == frame_clen) } else { - unsigned char *mc = malloc(frame_clen); + unsigned char *mc = (unsigned char *)malloc(frame_clen); int rc; unsigned long destlen = frame_uclen; @@ -5907,12 +5907,12 @@ indx_pos = indx_pntr - chain_clen; #ifdef FST_DEBUG fprintf(stderr, FST_APIMESS"indx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen); #endif -chain_cmem = malloc(chain_clen); +chain_cmem = (unsigned char *)malloc(chain_clen); fstReaderFseeko(xc, xc->f, indx_pos, SEEK_SET); fstFread(chain_cmem, chain_clen, 1, xc->f); -xc->rvat_chain_table = calloc((xc->rvat_vc_maxhandle+1), sizeof(off_t)); -xc->rvat_chain_table_lengths = calloc((xc->rvat_vc_maxhandle+1), sizeof(uint32_t)); +xc->rvat_chain_table = (off_t *)calloc((xc->rvat_vc_maxhandle+1), sizeof(off_t)); +xc->rvat_chain_table_lengths = (uint32_t *)calloc((xc->rvat_vc_maxhandle+1), sizeof(uint32_t)); pnt = chain_cmem; idx = 0; @@ -5921,10 +5921,10 @@ pval = 0; if(sectype == FST_BL_VCDATA_DYN_ALIAS2) { uint32_t prev_alias = 0; - + do { int skiplen; - + if(*pnt & 0x01) { int64_t shval = fstGetSVarint64(pnt, &skiplen) >> 1; @@ -5939,7 +5939,7 @@ if(sectype == FST_BL_VCDATA_DYN_ALIAS2) xc->rvat_chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */ xc->rvat_chain_table_lengths[idx] = prev_alias = shval; /* because during this loop iter would give stale data! */ idx++; - } + } else { xc->rvat_chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */ @@ -5950,14 +5950,14 @@ if(sectype == FST_BL_VCDATA_DYN_ALIAS2) else { uint64_t val = fstGetVarint32(pnt, &skiplen); - + fstHandle loopcnt = val >> 1; for(i=0;irvat_chain_table[idx++] = 0; } } - + pnt += skiplen; } while (pnt != (chain_cmem + chain_clen)); } @@ -5967,7 +5967,7 @@ if(sectype == FST_BL_VCDATA_DYN_ALIAS2) { int skiplen; uint64_t val = fstGetVarint32(pnt, &skiplen); - + if(!val) { pnt += skiplen; @@ -5991,7 +5991,7 @@ if(sectype == FST_BL_VCDATA_DYN_ALIAS2) xc->rvat_chain_table[idx++] = 0; } } - + pnt += skiplen; } while (pnt != (chain_cmem + chain_clen)); } @@ -6016,7 +6016,7 @@ for(i=0;irvat_data_valid = 1; @@ -6054,8 +6054,8 @@ if(!xc->rvat_chain_mem) xc->rvat_chain_len = fstReaderVarint32WithSkip(xc->f, &skiplen); if(xc->rvat_chain_len) { - unsigned char *mu = malloc(xc->rvat_chain_len); - unsigned char *mc = malloc(xc->rvat_chain_table_lengths[facidx]); + unsigned char *mu = (unsigned char *)malloc(xc->rvat_chain_len); + unsigned char *mc = (unsigned char *)malloc(xc->rvat_chain_table_lengths[facidx]); unsigned long destlen = xc->rvat_chain_len; unsigned long sourcelen = xc->rvat_chain_table_lengths[facidx]; int rc = Z_OK; @@ -6086,7 +6086,7 @@ if(!xc->rvat_chain_mem) else { int destlen = xc->rvat_chain_table_lengths[facidx] - skiplen; - unsigned char *mu = malloc(xc->rvat_chain_len = destlen); + unsigned char *mu = (unsigned char *)malloc(xc->rvat_chain_len = destlen); fstFread(mu, destlen, 1, xc->f); /* data to process is for(j=0;jrvat_chain_mem = mu; @@ -6387,17 +6387,17 @@ static uint32_t j_hash(const uint8_t *k, uint32_t length, uint32_t initval) c += length; switch(len) /* all the case statements fall through */ { - case 11: c+=((uint32_t)k[10]<<24); - case 10: c+=((uint32_t)k[9]<<16); - case 9 : c+=((uint32_t)k[8]<<8); + case 11: c+=((uint32_t)k[10]<<24); /* fallthrough */ + case 10: c+=((uint32_t)k[9]<<16); /* fallthrough */ + case 9 : c+=((uint32_t)k[8]<<8); /* fallthrough */ /* the first byte of c is reserved for the length */ - case 8 : b+=((uint32_t)k[7]<<24); - case 7 : b+=((uint32_t)k[6]<<16); - case 6 : b+=((uint32_t)k[5]<<8); - case 5 : b+=k[4]; - case 4 : a+=((uint32_t)k[3]<<24); - case 3 : a+=((uint32_t)k[2]<<16); - case 2 : a+=((uint32_t)k[1]<<8); + case 8 : b+=((uint32_t)k[7]<<24); /* fallthrough */ + case 7 : b+=((uint32_t)k[6]<<16); /* fallthrough */ + case 6 : b+=((uint32_t)k[5]<<8); /* fallthrough */ + case 5 : b+=k[4]; /* fallthrough */ + case 4 : a+=((uint32_t)k[3]<<24); /* fallthrough */ + case 3 : a+=((uint32_t)k[2]<<16); /* fallthrough */ + case 2 : a+=((uint32_t)k[1]<<8); /* fallthrough */ case 1 : a+=k[0]; /* case 0: nothing left to add */ } @@ -6432,7 +6432,7 @@ struct collchain_t *chain, *pchain; if(!*base) { - *base = calloc(1, (hashmask + 1) * sizeof(void *)); + *base = (struct collchain_t **)calloc(1, (hashmask + 1) * sizeof(void *)); } ar = *base; @@ -6455,7 +6455,7 @@ while(chain) chain = chain->next; } -chain = calloc(1, sizeof(struct collchain_t) + length - 1); +chain = (struct collchain_t *)calloc(1, sizeof(struct collchain_t) + length - 1); memcpy(chain->mem, mem, length); chain->fullhash = hf; chain->length = length; diff --git a/vpi/lxt2_write.c b/vpi/lxt2_write.c index 1ebf3e179..d51ad73a2 100644 --- a/vpi/lxt2_write.c +++ b/vpi/lxt2_write.c @@ -97,7 +97,7 @@ if (lonumfacs)) { struct lxt2_wr_symbol *s = lt->symchain; - struct lxt2_wr_symbol **aliascache = calloc(lt->numalias ? lt->numalias : 1, sizeof(struct lxt2_wr_symbol *)); + struct lxt2_wr_symbol **aliascache = (struct lxt2_wr_symbol**)calloc(lt->numalias ? lt->numalias : 1, sizeof(struct lxt2_wr_symbol *)); unsigned int aliases_encountered, facs_encountered; lt->sorted_facs = (struct lxt2_wr_symbol **)calloc(lt->numfacs, sizeof(struct lxt2_wr_symbol *)); @@ -920,7 +920,7 @@ if(flags&LXT2_WR_SYM_F_DOUBLE) s->len = 32; } - s->value = malloc(s->len + 1); + s->value = (char*)malloc(s->len + 1); memset(s->value, lt->initial_value, s->len); s->value[s->len]=0; @@ -1017,7 +1017,7 @@ static void lxt2_wr_emit_do_breakfile(struct lxt2_wr_trace *lt) { unsigned int len = strlen(lt->lxtname); int i; -char *tname = malloc(len + 30); +char *tname = (char*)malloc(len + 30); FILE *f2, *clone; off_t cnt, seg; char buf[32768]; @@ -1810,13 +1810,13 @@ while(s->aliased_to) /* find root alias if exists */ valuelen = strlen(value); /* ensure string is proper length */ if(valuelen == s->len) { - vfix = wave_alloca(s->len+1); + vfix = (char*)wave_alloca(s->len+1); strcpy(vfix, value); value = vfix; } else { - vfix = wave_alloca(s->len+1); + vfix = (char*)wave_alloca(s->len+1); if(valuelen < s->len) { @@ -2088,7 +2088,7 @@ if((lt)&&(lt->blackout)) else { free(s->value); - s->value = calloc(1, 1*sizeof(char)); + s->value = (char*)calloc(1, 1*sizeof(char)); } } } @@ -2101,9 +2101,11 @@ if((lt)&&(lt->blackout)) { if((!(s->flags&LXT2_WR_SYM_F_ALIAS))&&(s->rows<2)) { + char tmp[16]; /* To get rid of the warning */ if(!(s->flags&(LXT2_WR_SYM_F_DOUBLE|LXT2_WR_SYM_F_STRING))) { - lxt2_wr_emit_value_bit_string(lt, s, 0, "x"); + strcpy(tmp, "x"); + lxt2_wr_emit_value_bit_string(lt, s, 0, tmp); } else if (s->flags&LXT2_WR_SYM_F_DOUBLE) { @@ -2113,7 +2115,8 @@ if((lt)&&(lt->blackout)) } else if (s->flags&LXT2_WR_SYM_F_STRING) { - lxt2_wr_emit_value_string(lt, s, 0, "UNDEF"); + strcpy(tmp, "UNDEF"); + lxt2_wr_emit_value_string(lt, s, 0, tmp); } } s=s->symchain; @@ -2202,4 +2205,3 @@ if(lt) lt->timezero = timeval; } } - diff --git a/vpi/lxt2_write.h b/vpi/lxt2_write.h index 7f2c6d134..1a8a1adbb 100644 --- a/vpi/lxt2_write.h +++ b/vpi/lxt2_write.h @@ -43,7 +43,7 @@ extern "C" { #define ftello ftell #endif -#include +#include "wavealloca.h" #define LXT2_WR_HDRID (0x1380) #define LXT2_WR_VERSION (0x0001) @@ -314,4 +314,3 @@ int lxt2_wr_emit_value_bit_string(struct lxt2_wr_trace *lt, struct lxt2_wr_sy #endif #endif - diff --git a/vpi/lz4.c b/vpi/lz4.c index c050cf1e0..5ee034eea 100644 --- a/vpi/lz4.c +++ b/vpi/lz4.c @@ -228,6 +228,9 @@ static const int LZ4_minLength = (MFLIMIT+1); #define GB *(1U<<30) #define MAXD_LOG 16 +#ifdef MAX_DISTANCE +#undef MAX_DISTANCE +#endif #define MAX_DISTANCE ((1 << MAXD_LOG) - 1) #define ML_BITS 4 diff --git a/vpi/wavealloca.h b/vpi/wavealloca.h index 4be2e4937..86276648f 100644 --- a/vpi/wavealloca.h +++ b/vpi/wavealloca.h @@ -1,10 +1,23 @@ /* - * Copyright (c) Tony Bybell 1999. + * Copyright (c) 1999 Tony Bybell. * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. */ #ifndef WAVE_ALLOCA_H From f1608e163f664cf5900e09959609395a58f4ca97 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 6 Oct 2018 20:13:31 +0100 Subject: [PATCH 579/595] Fix implicit fallthrough warnings when building with recent GCC. --- elab_expr.cc | 1 + eval_tree.cc | 5 +++++ expr_synth.cc | 4 +++- main.cc | 6 ++++++ t-dll-api.cc | 3 ++- t-dll.cc | 3 ++- tgt-vhdl/stmt.cc | 4 +++- tgt-vlog95/expr.c | 6 ++++-- tgt-vlog95/logic_lpm.c | 10 +++++----- vpi/sys_countdrivers.c | 3 ++- vpi/sys_display.c | 2 +- vpi/sys_fileio.c | 4 ++-- vpi/sys_lxt.c | 3 ++- vpi/sys_lxt2.c | 3 ++- vpi/sys_queue.c | 3 ++- vpi/sys_readmem.c | 4 +++- vpi/sys_scanf.c | 3 ++- vpi/v2009_enum.c | 1 + vvp/stop.cc | 3 ++- vvp/vpi_callback.cc | 2 +- vvp/vpi_const.cc | 4 ++-- vvp/vpi_priv.cc | 9 +++++---- vvp/vpi_signal.cc | 3 ++- vvp/vpi_tasks.cc | 1 + vvp/vpi_time.cc | 3 ++- vvp/vpi_vthr_vector.cc | 3 +++ vvp/vpip_bin.cc | 1 + vvp/vpip_hex.cc | 3 ++- vvp/vpip_oct.cc | 2 +- 29 files changed, 70 insertions(+), 32 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index e5940801b..f2634efdc 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2775,6 +2775,7 @@ NetExpr* PEConcat::elaborate_expr(Design*, NetScope*, tmp->set_line(*this); return tmp; } + // fallthrough default: cerr << get_fileline() << ": internal error: " << "I don't know how to elaborate(ivl_type_t)" diff --git a/eval_tree.cc b/eval_tree.cc index 4a6c1c915..372a382cc 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -1074,6 +1074,7 @@ NetEConst* NetEBShift::eval_arguments_(const NetExpr*l, const NetExpr*r) const break; case 'r': lv.has_sign(false); + // fallthrough case 'R': val = cast_to_width(lv >> shift, wid); break; @@ -1525,6 +1526,7 @@ NetEConst* NetEUReduce::eval_arguments_(const NetExpr*ex) const case 'A': invert = true; + // fallthrough case '&': { res = verinum::V1; for (unsigned idx = 0 ; idx < val.len() ; idx += 1) @@ -1534,6 +1536,7 @@ NetEConst* NetEUReduce::eval_arguments_(const NetExpr*ex) const case 'N': invert = true; + // fallthrough case '|': { res = verinum::V0; for (unsigned idx = 0 ; idx < val.len() ; idx += 1) @@ -1543,6 +1546,7 @@ NetEConst* NetEUReduce::eval_arguments_(const NetExpr*ex) const case 'X': invert = true; + // fallthrough case '^': { /* Reduction XOR. */ unsigned ones = 0, unknown = 0; @@ -1594,6 +1598,7 @@ NetExpr* NetECast::eval_arguments_(const NetExpr*ex) const res_val = cast_to_width(res_val, expr_width()); res = new NetEConst(res_val); } + // fallthrough case 'v': if (const NetECReal*val = dynamic_cast(ex)) { verinum res_val(val->value().as_double(), false); diff --git a/expr_synth.cc b/expr_synth.cc index 5c28e1adb..86dd78dd4 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2018 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 @@ -346,6 +346,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root) des->errors += 1; return 0; } + // fallthrough case 'e': // == connect(dev->pin_AEB(), osig->pin(0)); break; @@ -364,6 +365,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root) des->errors += 1; return 0; } + // fallthrough case 'n': // != connect(dev->pin_ANEB(), osig->pin(0)); break; diff --git a/main.cc b/main.cc index 975e5abf9..290f766a7 100644 --- a/main.cc +++ b/main.cc @@ -1002,16 +1002,22 @@ int main(int argc, char*argv[]) switch (generation_flag) { case GN_VER2012: lexor_keyword_mask |= GN_KEYWORDS_1800_2012; + // fallthrough case GN_VER2009: lexor_keyword_mask |= GN_KEYWORDS_1800_2009; + // fallthrough case GN_VER2005_SV: lexor_keyword_mask |= GN_KEYWORDS_1800_2005; + // fallthrough case GN_VER2005: lexor_keyword_mask |= GN_KEYWORDS_1364_2005; + // fallthrough case GN_VER2001: lexor_keyword_mask |= GN_KEYWORDS_1364_2001_CONFIG; + // fallthrough case GN_VER2001_NOCONFIG: lexor_keyword_mask |= GN_KEYWORDS_1364_2001; + // fallthrough case GN_VER1995: lexor_keyword_mask |= GN_KEYWORDS_1364_1995; } diff --git a/t-dll-api.cc b/t-dll-api.cc index a32950437..89b0a5aa2 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2018 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * Copyright (c) 2016 CERN Michele Castellana (michele.castellana@cern.ch) * @@ -1520,6 +1520,7 @@ extern "C" unsigned ivl_lpm_selects(ivl_lpm_t net) case IVL_LPM_CONCATZ: cerr << "error: ivl_lpm_selects() is no longer supported for " "IVL_LPM_CONCAT, use ivl_lpm_size() instead." << endl; + // fallthrough default: assert(0); return 0; diff --git a/t-dll.cc b/t-dll.cc index 29e874154..ada97415f 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2018 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -2519,6 +2519,7 @@ void dll_target::scope(const NetScope*net) case NetScope::PACKAGE: cerr << "?:?" << ": internal error: " << "Package scopes should not have parents." << endl; + // fallthrough case NetScope::MODULE: scop->type_ = IVL_SCT_MODULE; scop->tname_ = net->module_name(); diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index 0da0d5e0b..6de800dec 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -1,7 +1,7 @@ /* * VHDL code generation for statements. * - * Copyright (C) 2008-2013 Nick Gasson (nick@nickg.me.uk) + * Copyright (C) 2008-2018 Nick Gasson (nick@nickg.me.uk) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -683,8 +683,10 @@ static void get_nexuses_from_expr(ivl_expr_t expr, set &out) break; case IVL_EX_TERNARY: get_nexuses_from_expr(ivl_expr_oper3(expr), out); + // fallthrough case IVL_EX_BINARY: get_nexuses_from_expr(ivl_expr_oper2(expr), out); + // fallthrough case IVL_EX_UNARY: get_nexuses_from_expr(ivl_expr_oper1(expr), out); break; diff --git a/tgt-vlog95/expr.c b/tgt-vlog95/expr.c index b47f6f4d4..c8c16c00d 100644 --- a/tgt-vlog95/expr.c +++ b/tgt-vlog95/expr.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2017 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2011-2018 Cary R. (cygcary@yahoo.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -451,6 +451,7 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid, ivl_expr_file(expr), ivl_expr_lineno(expr)); vlog_errors += 1; } + //fallthrough case '+': case '-': case '*': @@ -476,7 +477,7 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid, ivl_expr_file(expr), ivl_expr_lineno(expr)); vlog_errors += 1; - + // fallthrough case 'E': case 'e': case 'N': @@ -504,6 +505,7 @@ static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid, ivl_expr_file(expr), ivl_expr_lineno(expr)); vlog_errors += 1; } + // fallthrough case 'l': case 'r': emit_expr(scope, oper1, wid, 0, 0, 0); diff --git a/tgt-vlog95/logic_lpm.c b/tgt-vlog95/logic_lpm.c index 024325090..727b8cadd 100644 --- a/tgt-vlog95/logic_lpm.c +++ b/tgt-vlog95/logic_lpm.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2017 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2011-2018 Cary R. (cygcary@yahoo.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1276,6 +1276,7 @@ static void emit_lpm_as_ca(ivl_scope_t scope, ivl_lpm_t lpm, "should not be generated.\n", ivl_lpm_file(lpm), ivl_lpm_lineno(lpm)); vlog_errors += 1; + // falthrough case IVL_LPM_CONCAT: emit_lpm_concat(scope, lpm); break; @@ -2453,10 +2454,9 @@ void dump_nexus_information(ivl_scope_t scope, ivl_nexus_t nex) case IVL_VT_BOOL: fprintf(stderr, " bool"); break; case IVL_VT_LOGIC: fprintf(stderr, " logic"); break; case IVL_VT_STRING: fprintf(stderr, " string"); break; - case IVL_VT_DARRAY: fprintf(stderr, " dynamic array"); - case IVL_VT_CLASS: fprintf(stderr, " class"); - case IVL_VT_QUEUE: fprintf(stderr, " queue"); - break; + case IVL_VT_DARRAY: fprintf(stderr, " dynamic array"); break; + case IVL_VT_CLASS: fprintf(stderr, " class"); break; + case IVL_VT_QUEUE: fprintf(stderr, " queue"); break; } if (ivl_signal_signed(sig)) fprintf(stderr, " "); } else fprintf(stderr, "Error: No/missing information!"); diff --git a/vpi/sys_countdrivers.c b/vpi/sys_countdrivers.c index 3eedc431e..d4fbb8ea4 100644 --- a/vpi/sys_countdrivers.c +++ b/vpi/sys_countdrivers.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012-2014 Martin Whitaker. (icarus@martin-whitaker.me.uk) + * Copyright (C) 2012-2018 Martin Whitaker. (icarus@martin-whitaker.me.uk) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +33,7 @@ static void check_net_arg(vpiHandle arg, vpiHandle callh, const char *name) case vpiPartSelect: if (vpi_get(vpiType, vpi_handle(vpiParent, arg)) != vpiNet) break; + // fallthrough case vpiNet: if (vpi_get(vpiSize, arg) != 1) break; diff --git a/vpi/sys_display.c b/vpi/sys_display.c index 50d968b99..1f8df23ed 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -1169,7 +1169,7 @@ static int sys_check_args(vpiHandle callh, vpiHandle argv, const PLI_BYTE8*name, name, vpi_get_str(vpiType, arg)); ret = 1; } - + // fallthrough case vpiConstant: case vpiParameter: case vpiNet: diff --git a/vpi/sys_fileio.c b/vpi/sys_fileio.c index f63fd64e0..dbdecf5dc 100644 --- a/vpi/sys_fileio.c +++ b/vpi/sys_fileio.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2018 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 @@ -132,7 +132,7 @@ static PLI_INT32 sys_fopen_calltf(ICARUS_VPI_CONST PLI_BYTE8*name) } } if (! fail) break; - + // fallthrough default: vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), diff --git a/vpi/sys_lxt.c b/vpi/sys_lxt.c index b05c3dbfa..d0de6765d 100644 --- a/vpi/sys_lxt.c +++ b/vpi/sys_lxt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2018 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 @@ -550,6 +550,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) PLI_INT32 idx = vpi_get(vpiIndex, item); item = vpi_handle_by_index(array, idx); } + // fallthrough case vpiIntegerVar: case vpiBitVar: case vpiByteVar: diff --git a/vpi/sys_lxt2.c b/vpi/sys_lxt2.c index 1527efa09..3327264d1 100644 --- a/vpi/sys_lxt2.c +++ b/vpi/sys_lxt2.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2018 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 @@ -610,6 +610,7 @@ static void scan_item(unsigned depth, vpiHandle item, int skip) PLI_INT32 idx = vpi_get(vpiIndex, item); item = vpi_handle_by_index(array, idx); } + // fallthrough case vpiIntegerVar: case vpiBitVar: case vpiByteVar: diff --git a/vpi/sys_queue.c b/vpi/sys_queue.c index 3d34c7b4a..7eb7525c2 100644 --- a/vpi/sys_queue.c +++ b/vpi/sys_queue.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011-2014 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2011-2018 Cary R. (cygcary@yahoo.com) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -781,6 +781,7 @@ static PLI_INT32 fill_variable_with_scaled_time(vpiHandle var, uint64_t c_time) switch (words) { default: val_ptr[1].aval = (c_time >> 32) & 0xffffffff; + // fallthrough case 1: val_ptr[0].aval = c_time & 0xffffffff; } diff --git a/vpi/sys_readmem.c b/vpi/sys_readmem.c index a670a6317..0922214cf 100644 --- a/vpi/sys_readmem.c +++ b/vpi/sys_readmem.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 1999-2018 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 @@ -49,6 +49,7 @@ static void get_mem_params(vpiHandle argv, vpiHandle callh, const char *name, case vpiConstant: case vpiParameter: if (vpi_get(vpiConstType, *start_item) != vpiRealConst) break; + // fallthrough case vpiRealVar: vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); @@ -67,6 +68,7 @@ static void get_mem_params(vpiHandle argv, vpiHandle callh, const char *name, if (vpi_get(vpiConstType, *stop_item) != vpiRealConst) { break; } + // fallthrough case vpiRealVar: vpi_printf("WARNING: %s:%d: ", vpi_get_str(vpiFile, callh), diff --git a/vpi/sys_scanf.c b/vpi/sys_scanf.c index de567eba6..4768a72e8 100644 --- a/vpi/sys_scanf.c +++ b/vpi/sys_scanf.c @@ -1258,6 +1258,7 @@ static int is_assignable_obj(vpiHandle obj) break; case vpiPartSelect: if (! is_assignable_obj(vpi_handle(vpiParent, obj))) break; + // fallthrough case vpiIntegerVar: case vpiBitVar: case vpiByteVar: @@ -1403,7 +1404,7 @@ static PLI_INT32 sys_sscanf_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) case vpiConstant: case vpiParameter: if (vpi_get(vpiConstType, reg) == vpiStringConst) break; - + // fallthrough default: vpi_printf("ERROR: %s:%d: ", vpi_get_str(vpiFile, callh), (int)vpi_get(vpiLineNo, callh)); diff --git a/vpi/v2009_enum.c b/vpi/v2009_enum.c index a8983e28a..8c638ff22 100644 --- a/vpi/v2009_enum.c +++ b/vpi/v2009_enum.c @@ -108,6 +108,7 @@ static PLI_INT32 ivl_enum_method_next_prev_compiletf(ICARUS_VPI_CONST PLI_BYTE8* case vpiConstant: case vpiParameter: if (vpi_get(vpiConstType, arg_count) != vpiStringConst) break; + // fallthrough default: vpi_printf("%s:%d: compiler error: ", vpi_get_str(vpiFile, sys), diff --git a/vvp/stop.cc b/vvp/stop.cc index e77c9eba7..c82728188 100644 --- a/vvp/stop.cc +++ b/vvp/stop.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2015 Stephen Williams (steve@icarus.com) + * Copyright (c) 2003-2018 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 @@ -373,6 +373,7 @@ static void cmd_trace(unsigned argc, char*argv[]) break; default: printf("Only using the first argument to trace.\n"); + // fallthrough case 2: if ((strcmp(argv[1], "on") == 0) || (strcmp(argv[1], "1") == 0)) { show_file_line = true; diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index 45f4798af..e81a7ca2b 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -790,7 +790,7 @@ static void real_signal_value(struct t_vpi_value*vp, double rval) switch (vp->format) { case vpiObjTypeVal: vp->format = vpiRealVal; - + // fallthrough case vpiRealVal: vp->value.real = rval; break; diff --git a/vvp/vpi_const.cc b/vvp/vpi_const.cc index 4bd18ec8a..bc55cfe99 100644 --- a/vvp/vpi_const.cc +++ b/vvp/vpi_const.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2018 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 @@ -129,7 +129,7 @@ void __vpiStringConst::vpi_get_value(p_vpi_value vp) case vpiObjTypeVal: /* String parameters by default have vpiStringVal values. */ vp->format = vpiStringVal; - + // fallthrough case vpiStringVal: rbuf = (char *) need_result_buf(size + 1, RBUF_VAL); strcpy(rbuf, value_); diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index 0d72ea4ad..16122bc40 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2018 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 @@ -724,7 +724,7 @@ void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width, case vpiObjTypeVal: // Use the following case to actually set the value! vp->format = vpiVectorVal; - + // fallthrough case vpiVectorVal: { unsigned hwid = (width + 31)/32; @@ -784,6 +784,7 @@ void vpip_vec2_get_value(const vvp_vector2_t&word_val, unsigned width, case vpiObjTypeVal: vp->format = vpiIntVal; + // fallthrough case vpiIntVal: vector2_to_value(word_val, vp->value.integer, signed_flag); break; @@ -862,7 +863,7 @@ void vpip_real_get_value(double real, s_vpi_value*vp) case vpiObjTypeVal: // Use the following case to actually set the value! vp->format = vpiRealVal; - + // fallthrough case vpiRealVal: vp->value.real = real; break; @@ -944,7 +945,7 @@ void vpip_string_get_value(const string&val, s_vpi_value*vp) case vpiObjTypeVal: // Use the following case to actually set the value! vp->format = vpiStringVal; - + // fallthrough case vpiStringVal: rbuf = (char *) need_result_buf(val.size() + 1, RBUF_VAL); strcpy(rbuf, val.c_str()); diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index 5e63e77af..2002b15d2 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2016 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2018 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 @@ -1200,6 +1200,7 @@ static int PV_get(int code, vpiHandle ref) case vpiLeftRange: rval += rfp->width - 1; + // fallthrough case vpiRightRange: rval += vpi_get(vpiRightRange, rfp->parent) + PV_get_base(rfp); return rval; diff --git a/vvp/vpi_tasks.cc b/vvp/vpi_tasks.cc index b0aa19bfa..30e6eb18a 100644 --- a/vvp/vpi_tasks.cc +++ b/vvp/vpi_tasks.cc @@ -447,6 +447,7 @@ vpiHandle sysfunc_4net::vpi_put_value(p_vpi_value vp, int) (int)vp->value.scalar); assert(0); } + break; } case vpiIntVal: { diff --git a/vvp/vpi_time.cc b/vvp/vpi_time.cc index 2739523a2..1af7b5b50 100644 --- a/vvp/vpi_time.cc +++ b/vvp/vpi_time.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2018 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 @@ -131,6 +131,7 @@ static void timevar_get_value(vpiHandle ref, s_vpi_value*vp, bool is_int_func, case vpiObjTypeVal: /* The default format is vpiTimeVal. */ vp->format = vpiTimeVal; + // fallthrough case vpiTimeVal: vp->value.time = &time_value; vp->value.time->type = vpiSimTime; diff --git a/vvp/vpi_vthr_vector.cc b/vvp/vpi_vthr_vector.cc index ba553cf3e..6b98d59c5 100644 --- a/vvp/vpi_vthr_vector.cc +++ b/vvp/vpi_vthr_vector.cc @@ -108,6 +108,7 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp) case vpiObjTypeVal: vp->format = vpiRealVal; + // fallthrough case vpiRealVal: vp->value.real = val; break; @@ -258,6 +259,7 @@ void __vpiVThrStrStack::vpi_get_value(p_vpi_value vp) case vpiObjTypeVal: vp->format = vpiStringVal; + // fallthrough case vpiStringVal: rbuf = (char *) need_result_buf(val.size()+1, RBUF_VAL); strcpy(rbuf, val.c_str()); @@ -376,6 +378,7 @@ void __vpiVThrVec4Stack::vpi_get_value(p_vpi_value vp) break; case vpiObjTypeVal: vp->format = vpiVectorVal; + // fallthrough case vpiVectorVal: vpi_get_value_vector_(vp, val); break; diff --git a/vvp/vpip_bin.cc b/vvp/vpip_bin.cc index 991d00982..7ecf07dca 100644 --- a/vvp/vpip_bin.cc +++ b/vvp/vpip_bin.cc @@ -100,6 +100,7 @@ void vpip_bin_str_to_vec4(vvp_vector4_t&vec4, const char*buf) pad = BIT4_1; break; } + // fallthrough default: // Everything else gets '0' padded/ pad = BIT4_0; break; diff --git a/vvp/vpip_hex.cc b/vvp/vpip_hex.cc index e49468fab..fc0bf79fa 100644 --- a/vvp/vpip_hex.cc +++ b/vvp/vpip_hex.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2018 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 @@ -126,6 +126,7 @@ void vpip_hex_str_to_vec4(vvp_vector4_t&val, const char*str) pad = BIT4_1; break; } + // fallthrough default: // Everything else gets '0' padded. pad = BIT4_0; break; diff --git a/vvp/vpip_oct.cc b/vvp/vpip_oct.cc index a362a79d6..b60b0a85b 100644 --- a/vvp/vpip_oct.cc +++ b/vvp/vpip_oct.cc @@ -106,6 +106,7 @@ void vpip_oct_str_to_vec4(vvp_vector4_t&val, const char*str) pad = BIT4_1; break; } + // fallthrough default: // Everything else gets '0' padded. pad = BIT4_0; break; @@ -116,7 +117,6 @@ void vpip_oct_str_to_vec4(vvp_vector4_t&val, const char*str) if (idx < tval.size()) val.set_bit(idx, tval.value(idx)); else val.set_bit(idx, pad); } - } void vpip_vec4_to_oct_str(const vvp_vector4_t&bits, char*buf, unsigned nbuf) From 0d20c50de41e8359fee1999048baace33d2166ee Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 6 Oct 2018 20:22:12 +0100 Subject: [PATCH 580/595] Fix typo in last commit. --- tgt-vlog95/logic_lpm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tgt-vlog95/logic_lpm.c b/tgt-vlog95/logic_lpm.c index 727b8cadd..202f3ec39 100644 --- a/tgt-vlog95/logic_lpm.c +++ b/tgt-vlog95/logic_lpm.c @@ -1276,7 +1276,7 @@ static void emit_lpm_as_ca(ivl_scope_t scope, ivl_lpm_t lpm, "should not be generated.\n", ivl_lpm_file(lpm), ivl_lpm_lineno(lpm)); vlog_errors += 1; - // falthrough + // fallthrough case IVL_LPM_CONCAT: emit_lpm_concat(scope, lpm); break; From e71a76a1e288b07a3933e80a9e3b42620dc40bec Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 6 Oct 2018 20:40:54 +0100 Subject: [PATCH 581/595] Fix signed/unsigned comparison warning. --- elab_expr.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elab_expr.cc b/elab_expr.cc index f2634efdc..68b49f645 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2611,7 +2611,7 @@ NetExpr* PECastType::elaborate_expr(Design*des, NetScope*scope, // Find rounded up length that can fit the whole casted array of vectors int len = base->expr_width() + vector->packed_width() - 1; - if(base->expr_width() > vector->packed_width()) { + if(base->expr_width() > (unsigned)vector->packed_width()) { len /= vector->packed_width(); } else { len /= base->expr_width(); From 4ea18196c855e0e18fbcdf280989ac4062fa2256 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 6 Oct 2018 21:02:41 +0100 Subject: [PATCH 582/595] Fix deprecated dynamic exception specification warnings. --- tgt-vhdl/vhdl_element.cc | 3 +-- tgt-vhdl/vhdl_element.hh | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/tgt-vhdl/vhdl_element.cc b/tgt-vhdl/vhdl_element.cc index e7e0957b6..1b5c45191 100644 --- a/tgt-vhdl/vhdl_element.cc +++ b/tgt-vhdl/vhdl_element.cc @@ -108,7 +108,7 @@ void vhdl_element::print() const // Trap allocations of vhdl_element subclasses. // This records the pointer allocated in a static field of vhdl_element // so we can delete it just before the code generator exits. -void* vhdl_element::operator new(size_t size) throw (bad_alloc) +void* vhdl_element::operator new(size_t size) { // Let the default new handle the allocation void* ptr = ::operator new(size); @@ -171,4 +171,3 @@ int vhdl_element::free_all_objects() return freed; } - diff --git a/tgt-vhdl/vhdl_element.hh b/tgt-vhdl/vhdl_element.hh index a324e227d..8cf11d4cf 100644 --- a/tgt-vhdl/vhdl_element.hh +++ b/tgt-vhdl/vhdl_element.hh @@ -46,7 +46,7 @@ class vhdl_element { public: virtual ~vhdl_element() {} - void* operator new(size_t size) throw (std::bad_alloc); + void* operator new(size_t size); void operator delete(void* ptr); virtual void emit(std::ostream &of, int level=0) const = 0; @@ -74,4 +74,3 @@ std::string nl_string(int level); void blank_line(std::ostream &of, int level); #endif - From 3e25b0468534a78345581b2d9a3f5aa380d276db Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 6 Oct 2018 21:07:13 +0100 Subject: [PATCH 583/595] SIGHUP is not available in Windows. --- vvp/schedule.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/vvp/schedule.cc b/vvp/schedule.cc index 5b2244cc3..e2a49e126 100644 --- a/vvp/schedule.cc +++ b/vvp/schedule.cc @@ -626,14 +626,18 @@ extern "C" void signals_handler(int signum) static void signals_capture(void) { +#ifndef __MINGW32__ signal(SIGHUP, &signals_handler); +#endif signal(SIGINT, &signals_handler); signal(SIGTERM, &signals_handler); } static void signals_revert(void) { +#ifndef __MINGW32__ signal(SIGHUP, SIG_DFL); +#endif signal(SIGINT, SIG_DFL); signal(SIGTERM, SIG_DFL); } From 6415d84ed5bb6190d1a414b429756fd561a123ff Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 6 Oct 2018 22:56:04 +0100 Subject: [PATCH 584/595] Fix invalid cast of TF sizetf callback. --- libveriuser/veriusertfs.c | 29 ++++++++++++++++++++++++++++- veriuser.h | 3 ++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/libveriuser/veriusertfs.c b/libveriuser/veriusertfs.c index 3c455b800..8807f6649 100644 --- a/libveriuser/veriusertfs.c +++ b/libveriuser/veriusertfs.c @@ -44,6 +44,7 @@ typedef struct t_pli_data { static PLI_INT32 compiletf(ICARUS_VPI_CONST PLI_BYTE8 *); static PLI_INT32 calltf(ICARUS_VPI_CONST PLI_BYTE8 *); +static PLI_INT32 sizetf(ICARUS_VPI_CONST PLI_BYTE8 *); static PLI_INT32 callback(p_cb_data); /* @@ -150,7 +151,7 @@ void veriusertfs_register_table(p_tfcell vtable) tf_data.tfname = tf->tfname; tf_data.compiletf = compiletf; tf_data.calltf = calltf; - tf_data.sizetf = (PLI_INT32 (*)(ICARUS_VPI_CONST PLI_BYTE8 *))tf->sizetf; + tf_data.sizetf = sizetf; tf_data.user_data = (char *)data; if (pli_trace) { @@ -283,6 +284,32 @@ static PLI_INT32 calltf(ICARUS_VPI_CONST PLI_BYTE8*data) return rc; } +/* + * This function is the wrapper for the veriusertfs sizetf routine. + */ +static PLI_INT32 sizetf(ICARUS_VPI_CONST PLI_BYTE8*data) +{ + int rc = 32; + p_pli_data pli; + p_tfcell tf; + + /* cast back from opaque */ + pli = (p_pli_data)data; + tf = pli->tf; + + /* execute sizetf */ + if (tf->sizetf) { + if (pli_trace) { + fprintf(pli_trace, "Call %s->sizetf(%d, %d)\n", + tf->tfname, tf->data, reason_sizetf); + } + + rc = tf->sizetf(tf->data, reason_sizetf); + } + + return rc; +} + /* * This function is the wrapper for all the misctf callbacks */ diff --git a/veriuser.h b/veriuser.h index 7e061c16f..7614673db 100644 --- a/veriuser.h +++ b/veriuser.h @@ -1,7 +1,7 @@ #ifndef VERIUSER_H #define VERIUSER_H /* - * Copyright (c) 2002-2014 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2018 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 @@ -159,6 +159,7 @@ extern void veriusertfs_register_table(p_tfcell vtable); /* callback reasons */ #define reason_checktf 1 +#define reason_sizetf 2 #define reason_calltf 3 #define reason_paramvc 7 #define reason_synch 8 From 5cd0ba08b1c8dbc3174ee7b0e86654da721e1dd1 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 6 Oct 2018 23:25:13 +0100 Subject: [PATCH 585/595] Fix alloc size warning when building with recent GCC. --- tgt-vvp/vvp_scope.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 4c3194d98..3177e7976 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2018 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 @@ -860,6 +860,7 @@ static void draw_udp_in_scope(ivl_net_logic_t lptr) * (.resolv, etc.) can be built before we build the .udp call. * This matches what is done for the other primitives. */ + assert(ivl_logic_pins(lptr) > 0); ninp = ivl_logic_pins(lptr) - 1; input_strings = calloc(ninp, sizeof(char*)); for (pdx = 0 ; pdx < ninp ; pdx += 1) { @@ -922,7 +923,7 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr) ivl_drive_t str1 = ivl_logic_drive1(lptr); int level; - int ninp; + unsigned ninp; const char **input_strings; switch (ivl_logic_type(lptr)) { @@ -1055,8 +1056,8 @@ static void draw_logic_in_scope(ivl_net_logic_t lptr) /* Get all the input label that I will use for parameters to the functor that I create later. */ + assert(ivl_logic_pins(lptr) > 0); ninp = ivl_logic_pins(lptr) - 1; - assert(ninp >= 0); input_strings = calloc(ninp, sizeof(char*)); for (pdx = 0 ; pdx < (unsigned)ninp ; pdx += 1) input_strings[pdx] = draw_net_input(ivl_logic_pin(lptr, pdx+1)); From a03995b4da43f4347e23f6b85a139052b2b8ee9d Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 7 Oct 2018 11:23:40 +0100 Subject: [PATCH 586/595] Fix another implicit fallthrough warning. --- tgt-vhdl/stmt.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/tgt-vhdl/stmt.cc b/tgt-vhdl/stmt.cc index 6de800dec..51ac8bb20 100644 --- a/tgt-vhdl/stmt.cc +++ b/tgt-vhdl/stmt.cc @@ -1250,6 +1250,7 @@ static void process_number(vhdl_binop_expr *all, vhdl_var_ref *test, switch (bits[i]) { case 'x': if (is_casez) break; + // fallthrough case '?': case 'z': continue; // Ignore these. From 5aae9ea770181eea116195497c9d591261cb5e4a Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 7 Oct 2018 17:17:33 +0100 Subject: [PATCH 587/595] Fix bit width when converting real value to binary/hex string in VPI. --- vvp/vpi_callback.cc | 6 +++--- vvp/vpi_vthr_vector.cc | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index e81a7ca2b..e71005ee1 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -814,12 +814,12 @@ static void real_signal_value(struct t_vpi_value*vp, double rval) break; case vpiHexStrVal: - sprintf(rbuf, "%lx", (long)vlg_round(rval)); + sprintf(rbuf, "%" PRIx64, (uint64_t)vlg_round(rval)); vp->value.str = rbuf; break; case vpiBinStrVal: { - unsigned long val = (unsigned long)vlg_round(rval); + uint64_t val = (uint64_t)vlg_round(rval); unsigned len = 0; while (val > 0) { @@ -827,7 +827,7 @@ static void real_signal_value(struct t_vpi_value*vp, double rval) val /= 2; } - val = (unsigned long)vlg_round(rval); + val = (uint64_t)vlg_round(rval); for (unsigned idx = 0 ; idx < len ; idx += 1) { rbuf[len-idx-1] = (val & 1)? '1' : '0'; val /= 2; diff --git a/vvp/vpi_vthr_vector.cc b/vvp/vpi_vthr_vector.cc index 6b98d59c5..db279daad 100644 --- a/vvp/vpi_vthr_vector.cc +++ b/vvp/vpi_vthr_vector.cc @@ -132,17 +132,17 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp) break; case vpiOctStrVal: - sprintf(rbuf, "%lo", (long)vlg_round(val)); + sprintf(rbuf, "%" PRIo64, (uint64_t)vlg_round(val)); vp->value.str = rbuf; break; case vpiHexStrVal: - sprintf(rbuf, "%lx", (long)vlg_round(val)); + sprintf(rbuf, "%" PRIx64, (uint64_t)vlg_round(val)); vp->value.str = rbuf; break; case vpiBinStrVal: { - unsigned long vali = (unsigned long)vlg_round(val); + uint64_t vali = (uint64_t)vlg_round(val); unsigned len = 0; while (vali > 0) { @@ -150,7 +150,7 @@ static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp) vali /= 2; } - vali = (unsigned long)vlg_round(val); + vali = (uint64_t)vlg_round(val); for (unsigned idx = 0 ; idx < len ; idx += 1) { rbuf[len-idx-1] = (vali & 1)? '1' : '0'; vali /= 2; From 9d0d1938dc66b715b1ac6693913a9e79d3cb401c Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 7 Oct 2018 18:59:53 +0100 Subject: [PATCH 588/595] Fix bug in output of null character with %c format. --- vpi/sys_display.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/vpi/sys_display.c b/vpi/sys_display.c index 1f8df23ed..04cd66799 100644 --- a/vpi/sys_display.c +++ b/vpi/sys_display.c @@ -407,13 +407,13 @@ static unsigned int get_format_char(char **rtn, int ljust, int plus, vpi_printf("WARNING: %s:%d: missing argument for %s%s.\n", info->filename, info->lineno, info->name, fmtb); } else { - value.format = vpiStringVal; + value.format = vpiIntVal; vpi_get_value(info->items[*idx], &value); if (value.format == vpiSuppressVal) { vpi_printf("WARNING: %s:%d: incompatible value for %s%s.\n", info->filename, info->lineno, info->name, fmtb); } else { - char ch = value.value.str[strlen(value.value.str)-1]; + char ch = value.value.integer; /* If the width is less than one then use a width of one. */ if (width < 1) width = 1; From 2f142c485804ce2359a29dc020f665e01b79495c Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 7 Oct 2018 23:47:26 +0100 Subject: [PATCH 589/595] Revert "Fix x86_64-w64-mingw32 build: undefined ___strtod" This reverts commit bef04508f249925bb6e13f741d1ba03f612d7db1. --- aclocal.m4 | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/aclocal.m4 b/aclocal.m4 index 830553165..f44632fe2 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -223,10 +223,8 @@ AC_SUBST(strip_dynamic) # ------------- AC_DEFUN([AX_C99_STRTOD], [# On MinGW we need to jump through hoops to get a C99 compliant strtod(). + # mingw-w64 doesn't need this, and the 64-bit version doesn't support it. case "${host}" in - x86_64-w64-mingw32) - LDFLAGS+=" -Wl,--undefined=__strtod,--wrap,strtod,--defsym,___wrap_strtod=__strtod" - ;; *-*-mingw32) LDFLAGS+=" -Wl,--undefined=___strtod,--wrap,strtod,--defsym,___wrap_strtod=___strtod" ;; From fdf353af29be4f79198370978d12525c95c6ce87 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 7 Oct 2018 23:49:19 +0100 Subject: [PATCH 590/595] Don't use MinGW strtod workaround when building for MinGW-w64. The host triplet for MinGW-w64 has changed to more closely match that for MinGW, so we need to update the pattern in the test. --- aclocal.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aclocal.m4 b/aclocal.m4 index f44632fe2..7a113bf44 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -225,7 +225,7 @@ AC_DEFUN([AX_C99_STRTOD], [# On MinGW we need to jump through hoops to get a C99 compliant strtod(). # mingw-w64 doesn't need this, and the 64-bit version doesn't support it. case "${host}" in - *-*-mingw32) + *-pc-mingw32) LDFLAGS+=" -Wl,--undefined=___strtod,--wrap,strtod,--defsym,___wrap_strtod=___strtod" ;; esac From 844fa056f7f4c4d9ad94507c9e8e40aaac326567 Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 12 Oct 2018 21:29:29 -0700 Subject: [PATCH 591/595] Update fstapi files to the latest from GTKWave --- vpi/fstapi.c | 229 +++++++++++++++++++++++++++++++++++++++++++++++++-- vpi/fstapi.h | 32 +++++-- 2 files changed, 249 insertions(+), 12 deletions(-) diff --git a/vpi/fstapi.c b/vpi/fstapi.c index 13342fa7d..35f601191 100644 --- a/vpi/fstapi.c +++ b/vpi/fstapi.c @@ -283,7 +283,7 @@ static char *fstRealpath(const char *path, char *resolved_path) #if (defined(__MACH__) && defined(__APPLE__)) if(!resolved_path) { - resolved_path = (unsigned char *)malloc(PATH_MAX+1); /* fixes bug on Leopard when resolved_path == NULL */ + resolved_path = (char *)malloc(PATH_MAX+1); /* fixes bug on Leopard when resolved_path == NULL */ } #endif @@ -293,7 +293,7 @@ return(realpath(path, resolved_path)); #ifdef __MINGW32__ if(!resolved_path) { - resolved_path = (unsigned char *)malloc(PATH_MAX+1); + resolved_path = (char *)malloc(PATH_MAX+1); } return(_fullpath(resolved_path, path, PATH_MAX)); #else @@ -793,6 +793,8 @@ char *geom_handle_nam; char *valpos_handle_nam; char *curval_handle_nam; char *tchn_handle_nam; + +fstEnumHandle max_enumhandle; }; @@ -2160,7 +2162,7 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) #ifdef __MINGW32__ { int flen = strlen(xc->filename); - char *hf = calloc(1, flen + 6); + char *hf = (char *)calloc(1, flen + 6); strcpy(hf, xc->filename); if(xc->compress_hier) @@ -2303,7 +2305,7 @@ if(xc && path && path[0]) const unsigned char *path2 = (const unsigned char *)path; PPvoid_t pv; #else - char *path2 = alloca(slen + 1); /* judy lacks const qualifier in its JudyHSIns definition */ + char *path2 = (char *)alloca(slen + 1); /* judy lacks const qualifier in its JudyHSIns definition */ PPvoid_t pv; strcpy(path2, path); #endif @@ -2724,6 +2726,111 @@ if(xc) } +fstEnumHandle fstWriterCreateEnumTable(void *ctx, const char *name, uint32_t elem_count, unsigned int min_valbits, const char **literal_arr, const char **val_arr) +{ +fstEnumHandle handle = 0; +unsigned int *literal_lens = NULL; +unsigned int *val_lens = NULL; +int lit_len_tot = 0; +int val_len_tot = 0; +int name_len; +char elem_count_buf[16]; +int elem_count_len; +int total_len; +int pos = 0; +char *attr_str = NULL; + +if(ctx && name && literal_arr && val_arr && (elem_count != 0)) + { + struct fstWriterContext *xc = (struct fstWriterContext *)ctx; + + uint32_t i; + + name_len = strlen(name); + elem_count_len = sprintf(elem_count_buf, "%" PRIu32, elem_count); + + literal_lens = (unsigned int *)calloc(elem_count, sizeof(unsigned int)); + val_lens = (unsigned int *)calloc(elem_count, sizeof(unsigned int)); + + for(i=0;i 0) + { + if(val_lens[i] < min_valbits) + { + val_len_tot += (min_valbits - val_lens[i]); /* additional converted len is same for '0' character */ + } + } + } + + total_len = name_len + 1 + elem_count_len + 1 + lit_len_tot + elem_count + val_len_tot + elem_count; + + attr_str = (char*)malloc(total_len); + pos = 0; + + memcpy(attr_str+pos, name, name_len); + pos += name_len; + attr_str[pos++] = ' '; + + memcpy(attr_str+pos, elem_count_buf, elem_count_len); + pos += elem_count_len; + attr_str[pos++] = ' '; + + for(i=0;i 0) + { + if(val_lens[i] < min_valbits) + { + memset(attr_str+pos, '0', min_valbits - val_lens[i]); + pos += (min_valbits - val_lens[i]); + } + } + + pos += fstUtilityBinToEsc((unsigned char*)attr_str+pos, (unsigned char*)val_arr[i], val_lens[i]); + attr_str[pos++] = ' '; + } + + attr_str[pos-1] = 0; + +#ifdef FST_DEBUG + fprintf(stderr, FST_APIMESS"fstWriterCreateEnumTable() total_len: %d, pos: %d\n", total_len, pos); + fprintf(stderr, FST_APIMESS"*%s*\n", attr_str); +#endif + + fstWriterSetAttrBegin(xc, FST_AT_MISC, FST_MT_ENUMTABLE, attr_str, handle = ++xc->max_enumhandle); + + free(attr_str); + free(val_lens); + free(literal_lens); + } + +return(handle); +} + + +void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle) +{ +struct fstWriterContext *xc = (struct fstWriterContext *)ctx; +if(xc && handle) + { + fstWriterSetAttrBegin(xc, FST_AT_MISC, FST_MT_ENUMTABLE, NULL, handle); + } +} + + /* * value and time change emission */ @@ -6501,9 +6608,46 @@ if(base && *base) /*** ***/ /************************/ -int fstUtilityBinToEsc(unsigned char *d, unsigned char *s, int len) +int fstUtilityBinToEscConvertedLen(const unsigned char *s, int len) { -unsigned char *src = s; +const unsigned char *src = s; +int dlen = 0; +int i; + +for(i=0;i ' ') && (src[i] <= '~')) /* no white spaces in output */ + { + dlen++; + } + else + { + dlen += 4; + } + break; + } + } + +return(dlen); +} + + +int fstUtilityBinToEsc(unsigned char *d, const unsigned char *s, int len) +{ +const unsigned char *src = s; unsigned char *dst = d; unsigned char val; int i; @@ -6602,3 +6746,76 @@ for(i=0;ielem_count = cnt; + et->name = strdup(s); + et->literal_arr = (char**)calloc(cnt, sizeof(char *)); + et->val_arr = (char**)calloc(cnt, sizeof(char *)); + + sp = strchr(et->name, ' '); + *sp = 0; + + sp = strchr(sp+1, ' '); + + for(i=0;iliteral_arr[i] = sp+1; + sp = sp2; + + newlen = fstUtilityEscToBin(NULL, (unsigned char*)et->literal_arr[i], strlen(et->literal_arr[i])); + et->literal_arr[i][newlen] = 0; + } + + for(i=0;ival_arr[i] = sp+1; + sp = sp2; + + newlen = fstUtilityEscToBin(NULL, (unsigned char*)et->val_arr[i], strlen(et->val_arr[i])); + et->val_arr[i][newlen] = 0; + } + } + } + +return(et); +} + + +void fstUtilityFreeEnumTable(struct fstETab *etab) +{ +if(etab) + { + free(etab->literal_arr); + free(etab->val_arr); + free(etab->name); + free(etab); + } +} diff --git a/vpi/fstapi.h b/vpi/fstapi.h index e66c20467..aef6de23b 100644 --- a/vpi/fstapi.h +++ b/vpi/fstapi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2017 Tony Bybell. + * Copyright (c) 2009-2018 Tony Bybell. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -39,6 +39,7 @@ extern "C" { #define FST_RDLOAD "FSTLOAD | " typedef uint32_t fstHandle; +typedef uint32_t fstEnumHandle; enum fstWriterPackType { FST_WR_PT_ZLIB = 0, @@ -196,9 +197,10 @@ enum fstMiscType { FST_MT_SOURCESTEM = 4, /* use fstWriterSetSourceStem() to emit */ FST_MT_SOURCEISTEM = 5, /* use fstWriterSetSourceInstantiationStem() to emit */ FST_MT_VALUELIST = 6, /* use fstWriterSetValueList() to emit, followed by fstWriterCreateVar*() */ - FST_MT_UNKNOWN = 7, + FST_MT_ENUMTABLE = 7, /* use fstWriterCreateEnumTable() and fstWriterEmitEnumTableRef() to emit */ + FST_MT_UNKNOWN = 8, - FST_MT_MAX = 7 + FST_MT_MAX = 8 }; enum fstArrayType { @@ -228,7 +230,10 @@ enum fstEnumValueType { FST_EV_SV_UNSIGNED_LONGINT = 12, FST_EV_SV_UNSIGNED_BYTE = 13, - FST_EV_MAX = 13 + FST_EV_REG = 14, + FST_EV_TIME = 15, + + FST_EV_MAX = 15 }; enum fstPackType { @@ -324,11 +329,21 @@ union { }; +struct fstETab +{ +char *name; +uint32_t elem_count; +char **literal_arr; +char **val_arr; +}; + + /* * writer functions */ void fstWriterClose(void *ctx); void * fstWriterCreate(const char *nam, int use_compressed_hier); +fstEnumHandle fstWriterCreateEnumTable(void *ctx, const char *name, uint32_t elem_count, unsigned int min_valbits, const char **literal_arr, const char **val_arr); /* used for Verilog/SV */ fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir vd, uint32_t len, const char *nam, fstHandle aliasHandle); @@ -337,9 +352,10 @@ fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir fstHandle fstWriterCreateVar2(void *ctx, enum fstVarType vt, enum fstVarDir vd, uint32_t len, const char *nam, fstHandle aliasHandle, const char *type, enum fstSupplementalVarType svt, enum fstSupplementalDataType sdt); +void fstWriterEmitDumpActive(void *ctx, int enable); +void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle); void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val); void fstWriterEmitVariableLengthValueChange(void *ctx, fstHandle handle, const void *val, uint32_t len); -void fstWriterEmitDumpActive(void *ctx, int enable); void fstWriterEmitTimeChange(void *ctx, uint64_t tim); void fstWriterFlushContext(void *ctx); int fstWriterGetDumpSizeLimitReached(void *ctx); @@ -422,8 +438,12 @@ void fstReaderSetVcdExtensions(void *ctx, int enable); /* * utility functions */ -int fstUtilityBinToEsc(unsigned char *d, unsigned char *s, int len); +int fstUtilityBinToEscConvertedLen(const unsigned char *s, int len); /* used for mallocs for fstUtilityBinToEsc() */ +int fstUtilityBinToEsc(unsigned char *d, const unsigned char *s, int len); int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len); +struct fstETab *fstUtilityExtractEnumTableFromString(const char *s); +void fstUtilityFreeEnumTable(struct fstETab *etab); /* must use to free fstETab properly */ + #ifdef __cplusplus } From a638d1eed0f04486fc8857b03e1fc84a9726ea2f Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Sun, 28 Oct 2018 12:43:40 -0700 Subject: [PATCH 592/595] Check for too many paths specified and fix path priority so paths specified on command line supersede built-in paths --- vvp/main.cc | 96 ++++++++++++++++++++++++++++------------------ vvp/vpi_modules.cc | 19 +-------- vvp/vpi_priv.h | 2 +- 3 files changed, 62 insertions(+), 55 deletions(-) diff --git a/vvp/main.cc b/vvp/main.cc index e095a0d5d..acde2cb88 100644 --- a/vvp/main.cc +++ b/vvp/main.cc @@ -262,43 +262,6 @@ int main(int argc, char*argv[]) extern bool stop_is_finish; extern int stop_is_finish_exit_code; -#ifdef __MINGW32__ - /* Calculate the module path from the path to the command. - This is necessary because of the installation process on - Windows. Mostly, it is those darn drive letters, but oh - well. We know the command path is formed like this: - - D:\iverilog\bin\iverilog.exe - - The IVL_ROOT in a Windows installation is the path: - - D:\iverilog\lib\ivl$(suffix) - - so we chop the file name and the last directory by - turning the last two \ characters to null. Then we append - the lib\ivl$(suffix) to finish. */ - char *s; - char basepath[4096], tmp[4096]; - GetModuleFileName(NULL, tmp, sizeof tmp); - /* Convert to a short name to remove any embedded spaces. */ - GetShortPathName(tmp, basepath, sizeof basepath); - s = strrchr(basepath, '\\'); - if (s) *s = 0; - else { - fprintf(stderr, "%s: Missing first \\ in exe path!\n", argv[0]); - exit(1); - } - s = strrchr(basepath, '\\'); - if (s) *s = 0; - else { - fprintf(stderr, "%s: Missing second \\ in exe path!\n", argv[0]); - exit(1); - } - strcat(s, "\\lib\\ivl" IVL_SUFFIX); - vpip_module_path[0] = strdup(basepath); -#endif - - if( ::getenv("VVP_WAIT_FOR_DEBUGGER") != 0 ) { fprintf( stderr, "Waiting for debugger...\n"); bool debugger_release = false; @@ -343,6 +306,10 @@ int main(int argc, char*argv[]) vpip_module_path_cnt = 0; vpip_module_path[0] = 0; } else { + if (vpip_module_path_cnt >= VPIP_MODULE_PATH_MAX) { + fprintf(stderr, "Too many paths specified\n"); + return -1; + } vpip_module_path[vpip_module_path_cnt++] = optarg; } break; @@ -369,6 +336,61 @@ int main(int argc, char*argv[]) flag_errors += 1; } +#ifdef __MINGW32__ + /* Calculate the module path from the path to the command. + This is necessary because of the installation process on + Windows. Mostly, it is those darn drive letters, but oh + well. We know the command path is formed like this: + + D:\iverilog\bin\iverilog.exe + + The IVL_ROOT in a Windows installation is the path: + + D:\iverilog\lib\ivl$(suffix) + + so we chop the file name and the last directory by + turning the last two \ characters to null. Then we append + the lib\ivl$(suffix) to finish. */ + char *s; + char basepath[4096], tmp[4096]; + GetModuleFileName(NULL, tmp, sizeof tmp); + /* Convert to a short name to remove any embedded spaces. */ + GetShortPathName(tmp, basepath, sizeof basepath); + s = strrchr(basepath, '\\'); + if (s) *s = 0; + else { + fprintf(stderr, "%s: Missing first \\ in exe path!\n", argv[0]); + exit(1); + } + s = strrchr(basepath, '\\'); + if (s) *s = 0; + else { + fprintf(stderr, "%s: Missing second \\ in exe path!\n", argv[0]); + exit(1); + } + strcat(s, "\\lib\\ivl" IVL_SUFFIX); + if (vpip_module_path_cnt >= VPIP_MODULE_PATH_MAX) { + fprintf(stderr, "Too many paths specified\n"); + return -1; + } + vpip_module_path[vpip_module_path_cnt++] = strdup(basepath); +#else +#ifdef MODULE_DIR1 + if (vpip_module_path_cnt >= VPIP_MODULE_PATH_MAX) { + fprintf(stderr, "Too many paths specified\n"); + return -1; + } + vpip_module_path[vpip_module_path_cnt++] = MODULE_DIR1; +#endif +#endif +#ifdef MODULE_DIR2 + if (vpip_module_path_cnt >= VPIP_MODULE_PATH_MAX) { + fprintf(stderr, "Too many paths specified\n"); + return -1; + } + vpip_module_path[vpip_module_path_cnt++] = MODULE_DIR2; +#endif + if (flag_errors) return flag_errors; diff --git a/vvp/vpi_modules.cc b/vvp/vpi_modules.cc index 6a9a515b1..6a8012473 100644 --- a/vvp/vpi_modules.cc +++ b/vvp/vpi_modules.cc @@ -33,24 +33,9 @@ static unsigned dll_list_cnt = 0; typedef void (*vlog_startup_routines_t)(void); -const char* vpip_module_path[64] = { -#ifdef MODULE_DIR1 - MODULE_DIR1, -#endif -#ifdef MODULE_DIR2 - MODULE_DIR2, -#endif - 0 -}; +const char* vpip_module_path[VPIP_MODULE_PATH_MAX] = {0}; -unsigned vpip_module_path_cnt = 0 -#ifdef MODULE_DIR1 - + 1 -#endif -#ifdef MODULE_DIR2 - + 1 -#endif -; +unsigned vpip_module_path_cnt = 0; void load_module_delete(void) { diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 9fa811e3f..51b1bf4b3 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -874,7 +874,7 @@ vpiHandle vpip_make_vthr_APV(char*label, unsigned index, unsigned bit, unsigned extern void vpip_load_module(const char*name); # define VPIP_MODULE_PATH_MAX 64 -extern const char* vpip_module_path[64]; +extern const char* vpip_module_path[VPIP_MODULE_PATH_MAX]; extern unsigned vpip_module_path_cnt; /* From a1ad6d4b51a5e505ce938c4a3a58a202b4f94831 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Sun, 28 Oct 2018 12:44:09 -0700 Subject: [PATCH 593/595] Support IVERILOG_VPI_MODULE_PATH environment variable --- vvp/main.cc | 22 ++++++++++++++++++++++ vvp/vvp.man.in | 7 +++++++ 2 files changed, 29 insertions(+) diff --git a/vvp/main.cc b/vvp/main.cc index acde2cb88..b0a5bb633 100644 --- a/vvp/main.cc +++ b/vvp/main.cc @@ -336,6 +336,28 @@ int main(int argc, char*argv[]) flag_errors += 1; } + if (char *var = ::getenv("IVERILOG_VPI_MODULE_PATH")) { + char *ptr = var; + char *end = var+strlen(var); + int len = 0; + while (ptr <= end) { + if (*ptr == 0 || *ptr == ':' || *ptr == ';') { + if (len > 0) { + if (vpip_module_path_cnt >= VPIP_MODULE_PATH_MAX) { + fprintf(stderr, "Too many paths specified\n"); + return -1; + } + vpip_module_path[vpip_module_path_cnt++] = strndup(var, len); + } + len = 0; + var = ptr+1; + } else { + len++; + } + ptr++; + } + } + #ifdef __MINGW32__ /* Calculate the module path from the path to the command. This is necessary because of the installation process on diff --git a/vvp/vvp.man.in b/vvp/vvp.man.in index d08b937d0..add5faf4e 100644 --- a/vvp/vvp.man.in +++ b/vvp/vvp.man.in @@ -166,6 +166,13 @@ select lxt format, which is far more compact, though limited to GTKWave or compatible viewers. It can also be used to suppress VCD output, a time-saver for regression tests. +.TP 8 +.B IVERILOG_VPI_MODULE_PATH=\fI/some/path:/some/other/path\fP +This adds additional components to the VPI module search path. Paths +specified in this way are searched after paths specified with \-M, but +before the default search path. Multiple paths can be separated with +colons or semicolons. + .SH INTERACTIVE MODE .PP The simulation engine supports an interactive mode. The user may From 6887c31d8ce139b9cbf46e5ac8cc0840e8a89522 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 29 Oct 2018 20:33:52 +0000 Subject: [PATCH 594/595] Refactor vpi module path code. Also restore the original behaviour of the '-M -' option, although it's probably not needed now we add the default path last. --- vvp/main.cc | 88 ++------------------------------------------ vvp/vpi_modules.cc | 92 ++++++++++++++++++++++++++++++++++++++++++++-- vvp/vpi_priv.h | 8 ++-- 3 files changed, 97 insertions(+), 91 deletions(-) diff --git a/vvp/main.cc b/vvp/main.cc index b0a5bb633..5b598e4d1 100644 --- a/vvp/main.cc +++ b/vvp/main.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2015 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2018 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 @@ -303,14 +303,9 @@ int main(int argc, char*argv[]) break; case 'M': if (strcmp(optarg,"-") == 0) { - vpip_module_path_cnt = 0; - vpip_module_path[0] = 0; + vpip_clear_module_paths(); } else { - if (vpip_module_path_cnt >= VPIP_MODULE_PATH_MAX) { - fprintf(stderr, "Too many paths specified\n"); - return -1; - } - vpip_module_path[vpip_module_path_cnt++] = optarg; + vpip_add_module_path(optarg); } break; case 'm': @@ -336,82 +331,7 @@ int main(int argc, char*argv[]) flag_errors += 1; } - if (char *var = ::getenv("IVERILOG_VPI_MODULE_PATH")) { - char *ptr = var; - char *end = var+strlen(var); - int len = 0; - while (ptr <= end) { - if (*ptr == 0 || *ptr == ':' || *ptr == ';') { - if (len > 0) { - if (vpip_module_path_cnt >= VPIP_MODULE_PATH_MAX) { - fprintf(stderr, "Too many paths specified\n"); - return -1; - } - vpip_module_path[vpip_module_path_cnt++] = strndup(var, len); - } - len = 0; - var = ptr+1; - } else { - len++; - } - ptr++; - } - } - -#ifdef __MINGW32__ - /* Calculate the module path from the path to the command. - This is necessary because of the installation process on - Windows. Mostly, it is those darn drive letters, but oh - well. We know the command path is formed like this: - - D:\iverilog\bin\iverilog.exe - - The IVL_ROOT in a Windows installation is the path: - - D:\iverilog\lib\ivl$(suffix) - - so we chop the file name and the last directory by - turning the last two \ characters to null. Then we append - the lib\ivl$(suffix) to finish. */ - char *s; - char basepath[4096], tmp[4096]; - GetModuleFileName(NULL, tmp, sizeof tmp); - /* Convert to a short name to remove any embedded spaces. */ - GetShortPathName(tmp, basepath, sizeof basepath); - s = strrchr(basepath, '\\'); - if (s) *s = 0; - else { - fprintf(stderr, "%s: Missing first \\ in exe path!\n", argv[0]); - exit(1); - } - s = strrchr(basepath, '\\'); - if (s) *s = 0; - else { - fprintf(stderr, "%s: Missing second \\ in exe path!\n", argv[0]); - exit(1); - } - strcat(s, "\\lib\\ivl" IVL_SUFFIX); - if (vpip_module_path_cnt >= VPIP_MODULE_PATH_MAX) { - fprintf(stderr, "Too many paths specified\n"); - return -1; - } - vpip_module_path[vpip_module_path_cnt++] = strdup(basepath); -#else -#ifdef MODULE_DIR1 - if (vpip_module_path_cnt >= VPIP_MODULE_PATH_MAX) { - fprintf(stderr, "Too many paths specified\n"); - return -1; - } - vpip_module_path[vpip_module_path_cnt++] = MODULE_DIR1; -#endif -#endif -#ifdef MODULE_DIR2 - if (vpip_module_path_cnt >= VPIP_MODULE_PATH_MAX) { - fprintf(stderr, "Too many paths specified\n"); - return -1; - } - vpip_module_path[vpip_module_path_cnt++] = MODULE_DIR2; -#endif + vpip_add_env_and_default_module_paths(); if (flag_errors) return flag_errors; diff --git a/vvp/vpi_modules.cc b/vvp/vpi_modules.cc index 6a8012473..24fa2a309 100644 --- a/vvp/vpi_modules.cc +++ b/vvp/vpi_modules.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2018 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 @@ -32,10 +32,96 @@ static unsigned dll_list_cnt = 0; typedef void (*vlog_startup_routines_t)(void); +# define VPIP_MODULE_PATH_MAX 64 -const char* vpip_module_path[VPIP_MODULE_PATH_MAX] = {0}; +static const char* vpip_module_path[VPIP_MODULE_PATH_MAX] = {0}; -unsigned vpip_module_path_cnt = 0; +static unsigned vpip_module_path_cnt = 0; + +static bool disable_default_paths = false; + +void vpip_clear_module_paths() +{ + vpip_module_path_cnt = 0; + vpip_module_path[0] = 0; + disable_default_paths = true; +} + +void vpip_add_module_path(const char*path) +{ + if (vpip_module_path_cnt >= VPIP_MODULE_PATH_MAX) { + fprintf(stderr, "Too many module paths specified\n"); + exit(1); + } + vpip_module_path[vpip_module_path_cnt++] = path; +} + +void vpip_add_env_and_default_module_paths() +{ + if (disable_default_paths) + return; + + if (char *var = ::getenv("IVERILOG_VPI_MODULE_PATH")) { + char *ptr = var; + char *end = var+strlen(var); + int len = 0; + while (ptr <= end) { + if (*ptr == 0 || *ptr == ':' || *ptr == ';') { + if (len > 0) { + vpip_add_module_path(strndup(var, len)); + } + len = 0; + var = ptr+1; + } else { + len++; + } + ptr++; + } + } + +#ifdef __MINGW32__ + /* Calculate the module path from the path to the command. + This is necessary because of the installation process on + Windows. Mostly, it is those darn drive letters, but oh + well. We know the command path is formed like this: + + D:\iverilog\bin\iverilog.exe + + The IVL_ROOT in a Windows installation is the path: + + D:\iverilog\lib\ivl$(suffix) + + so we chop the file name and the last directory by + turning the last two \ characters to null. Then we append + the lib\ivl$(suffix) to finish. */ + char *s; + char basepath[4096], tmp[4096]; + GetModuleFileName(NULL, tmp, sizeof tmp); + /* Convert to a short name to remove any embedded spaces. */ + GetShortPathName(tmp, basepath, sizeof basepath); + s = strrchr(basepath, '\\'); + if (s) *s = 0; + else { + fprintf(stderr, "%s: Missing first \\ in exe path!\n", argv[0]); + exit(1); + } + s = strrchr(basepath, '\\'); + if (s) *s = 0; + else { + fprintf(stderr, "%s: Missing second \\ in exe path!\n", argv[0]); + exit(1); + } + strcat(s, "\\lib\\ivl" IVL_SUFFIX); + vpip_add_module_path(strdup(basepath)); +#else +#ifdef MODULE_DIR1 + vpip_add_module_path(MODULE_DIR1); +#endif +#endif +#ifdef MODULE_DIR2 + vpip_add_module_path(MODULE_DIR2); +#endif +} void load_module_delete(void) { diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 51b1bf4b3..3a841f3a0 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -1,7 +1,7 @@ #ifndef IVL_vpi_priv_H #define IVL_vpi_priv_H /* - * Copyright (c) 2001-2017 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2018 Stephen Williams (steve@icarus.com) * Copyright (c) 2016 CERN Michele Castellana (michele.castellana@cern.ch) * * This source code is free software; you can redistribute it @@ -873,9 +873,9 @@ vpiHandle vpip_make_vthr_APV(char*label, unsigned index, unsigned bit, unsigned */ extern void vpip_load_module(const char*name); -# define VPIP_MODULE_PATH_MAX 64 -extern const char* vpip_module_path[VPIP_MODULE_PATH_MAX]; -extern unsigned vpip_module_path_cnt; +extern void vpip_clear_module_paths(); +extern void vpip_add_module_path(const char *path); +extern void vpip_add_env_and_default_module_paths(); /* * The vpip_build_vpi_call function creates a __vpiSysTaskCall object From 36120769432577e3abd12a182b97d605bd4572a6 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Fri, 2 Nov 2018 21:22:10 +0000 Subject: [PATCH 595/595] Undo redefinition of unique_ptr at end of header files. It seems that clang both defines __cplusplus < 201103L and provides unique_ptr (GitHub issue #215). --- pform_types.h | 4 ++++ vhdlpp/expression.h | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/pform_types.h b/pform_types.h index 0bd87d817..92061527e 100644 --- a/pform_types.h +++ b/pform_types.h @@ -380,4 +380,8 @@ extern std::ostream& operator<< (std::ostream&out, const pform_name_t&); extern std::ostream& operator<< (std::ostream&out, const name_component_t&that); extern std::ostream& operator<< (std::ostream&out, const index_component_t&that); +#if __cplusplus < 201103L +#undef unique_ptr +#endif + #endif /* IVL_pform_types_H */ diff --git a/vhdlpp/expression.h b/vhdlpp/expression.h index 35f23e22c..3ae6c2bb9 100644 --- a/vhdlpp/expression.h +++ b/vhdlpp/expression.h @@ -1097,4 +1097,8 @@ private: Expression*delay_; }; +#if __cplusplus < 201103L +#undef unique_ptr +#endif + #endif /* IVL_expression_H */