From bc9382eea39b65119c5496a54675d55a1162416d Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Thu, 6 Mar 2014 19:35:25 +0000 Subject: [PATCH 001/245] Fix for GitHub issue 20 : confused about signed/unsigned in strange ?: example. The root cause was that NetESignal::dup_exr() was not copying the calculated type (signed/unsigned) of the expression. In passing, found and fixed a similar issue when calculating a blended value for a constant ternary expression. --- dup_expr.cc | 1 + eval_tree.cc | 1 + 2 files changed, 2 insertions(+) diff --git a/dup_expr.cc b/dup_expr.cc index 93c509270..08da1bb27 100644 --- a/dup_expr.cc +++ b/dup_expr.cc @@ -249,6 +249,7 @@ NetESignal* NetESignal::dup_expr() const NetESignal*tmp = new NetESignal(net_, word_); ivl_assert(*this, tmp); tmp->expr_width(expr_width()); + tmp->cast_signed(has_sign()); tmp->set_line(*this); return tmp; } diff --git a/eval_tree.cc b/eval_tree.cc index ff224d909..1faa36a43 100644 --- a/eval_tree.cc +++ b/eval_tree.cc @@ -1384,6 +1384,7 @@ NetExpr*NetETernary::blended_arguments_(const NetExpr*te, const NetExpr*fe) cons if (tv == fv) val.set(idx, tv); else val.set(idx, verinum::Vx); } + val.has_sign(has_sign()); if (debug_eval_tree) { cerr << get_fileline() << ": debug: Evaluate ternary with " From bb182cf3ce882c85f6257701221edb7d09358af2 Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 20 Mar 2014 18:25:37 -0700 Subject: [PATCH 002/245] Update cppcheck suppression file. --- vpi/cppcheck.sup | 47 ++++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 23 deletions(-) diff --git a/vpi/cppcheck.sup b/vpi/cppcheck.sup index caf92d8d5..276a3eeac 100644 --- a/vpi/cppcheck.sup +++ b/vpi/cppcheck.sup @@ -3,29 +3,30 @@ // problems will not be fixed. // fstapi.c from GTKWave -obsoleteFunctionsasctime:fstapi.c:672 -unreadVariable:fstapi.c:1317 -variableScope:fstapi.c:771 -variableScope:fstapi.c:1727 -variableScope:fstapi.c:2029 -variableScope:fstapi.c:2221 -variableScope:fstapi.c:2380 -variableScope:fstapi.c:2381 -variableScope:fstapi.c:2989 -variableScope:fstapi.c:3014 -variableScope:fstapi.c:3137 -variableScope:fstapi.c:3550 -variableScope:fstapi.c:3559 -variableScope:fstapi.c:4066 -variableScope:fstapi.c:4069 -variableScope:fstapi.c:4636 -variableScope:fstapi.c:4690 -variableScope:fstapi.c:4994 -variableScope:fstapi.c:4997 -variableScope:fstapi.c:5233 -variableScope:fstapi.c:5338 -variableScope:fstapi.c:5339 -variableScope:fstapi.c:5370 +obsoleteFunctionsasctime:fstapi.c:740 +obsoleteFunctionsalloca:fstapi.c:1994 +unreadVariable:fstapi.c:1388 +variableScope:fstapi.c:842 +variableScope:fstapi.c:1798 +variableScope:fstapi.c:2222 +variableScope:fstapi.c:2414 +variableScope:fstapi.c:2573 +variableScope:fstapi.c:2574 +variableScope:fstapi.c:3193 +variableScope:fstapi.c:3218 +variableScope:fstapi.c:3341 +variableScope:fstapi.c:3777 +variableScope:fstapi.c:3786 +variableScope:fstapi.c:4297 +variableScope:fstapi.c:4300 +variableScope:fstapi.c:4867 +variableScope:fstapi.c:4921 +variableScope:fstapi.c:5225 +variableScope:fstapi.c:5228 +variableScope:fstapi.c:5464 +variableScope:fstapi.c:5569 +variableScope:fstapi.c:5570 +variableScope:fstapi.c:5601 // lxt2_write.c from GTKWave obsoleteFunctionsalloca:lxt2_write.c:1813 From 849ba64cf7fd9c9ea42c5ecc259e8311c0e3b47e Mon Sep 17 00:00:00 2001 From: "Todd Strader (todd.strader@gmail.com)" Date: Thu, 3 Apr 2014 20:11:57 -0400 Subject: [PATCH 003/245] package imports in module headers See IEEE 1800-2012 A.1.2 module_nonansi_header and module_ansi_header --- parse.y | 31 +++++++++++++++++++++---------- 1 file changed, 21 insertions(+), 10 deletions(-) diff --git a/parse.y b/parse.y index d9b8f0166..3d5bd8c3d 100644 --- a/parse.y +++ b/parse.y @@ -1495,6 +1495,16 @@ package_declaration /* IEEE1800-2005 A.1.2 */ } ; +module_package_import_list_opt + : + | package_import_list + ; + +package_import_list + : package_import_declaration + | package_import_list package_import_declaration + ; + package_import_declaration /* IEEE1800-2005 A.2.1.3 */ : K_import package_import_item_list ';' { } @@ -4097,10 +4107,11 @@ local_timeunit_prec_decl2 module : attribute_list_opt module_start IDENTIFIER { pform_startmodule(@2, $3, $2==K_program, $1); } + module_package_import_list_opt module_parameter_port_list_opt module_port_list_opt module_attribute_foreign ';' - { pform_module_set_ports($6); } + { pform_module_set_ports($7); } local_timeunit_prec_decl_opt { have_timeunit_decl = true; // Every thing past here is have_timeprec_decl = true; // a check! @@ -4126,13 +4137,13 @@ module } // Check that program/endprogram and module/endmodule // keywords match. - if ($2 != $13) { + if ($2 != $14) { switch ($2) { case K_module: - yyerror(@13, "error: module not closed by endmodule."); + yyerror(@14, "error: module not closed by endmodule."); break; case K_program: - yyerror(@13, "error: program not closed by endprogram."); + yyerror(@14, "error: program not closed by endprogram."); break; default: break; @@ -4148,15 +4159,15 @@ module // endlabel_opt but still have the pform_endmodule() called // early enough that the lexor can know we are outside the // module. - if ($15) { - if (strcmp($3,$15) != 0) { + if ($16) { + if (strcmp($3,$16) != 0) { switch ($2) { case K_module: - yyerror(@15, "error: End label doesn't match " + yyerror(@16, "error: End label doesn't match " "module name."); break; case K_program: - yyerror(@15, "error: End label doesn't match " + yyerror(@16, "error: End label doesn't match " "program name."); break; default: @@ -4164,10 +4175,10 @@ module } } if (($2 == K_module) && (! gn_system_verilog())) { - yyerror(@7, "error: Module end labels require " + yyerror(@8, "error: Module end labels require " "System Verilog."); } - delete[]$15; + delete[]$16; } delete[]$3; } From a849249a86f8d0800c699b53701e1c2e81159602 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Fri, 21 Feb 2014 20:48:34 -0800 Subject: [PATCH 004/245] Allow typedefs to override inherited type names. --- lexor.lex | 12 ++++++------ parse.y | 51 +++++++++++++++++++++++++++++++++++++-------------- parse_misc.h | 2 ++ pform.cc | 25 +++++++++++++++++++++++++ 4 files changed, 70 insertions(+), 20 deletions(-) diff --git a/lexor.lex b/lexor.lex index 68435444c..dbcb6a251 100644 --- a/lexor.lex +++ b/lexor.lex @@ -325,8 +325,8 @@ TU [munpf] if (in_package_scope) { if (rc == IDENTIFIER) { if (data_type_t*type = pform_test_type_identifier(in_package_scope, yylval.text)) { - delete[]yylval.text; - yylval.data_type = type; + yylval.type_identifier.text = yylval.text; + yylval.type_identifier.type = type; rc = TYPE_IDENTIFIER; } } @@ -361,8 +361,8 @@ TU [munpf] return this as a TYPE_IDENTIFIER instead. */ if (rc == IDENTIFIER && gn_system_verilog()) { if (data_type_t*type = pform_test_type_identifier(yylval.text)) { - delete[]yylval.text; - yylval.data_type = type; + yylval.type_identifier.text = yylval.text; + yylval.type_identifier.type = type; rc = TYPE_IDENTIFIER; } } @@ -382,8 +382,8 @@ TU [munpf] } if (gn_system_verilog()) { if (data_type_t*type = pform_test_type_identifier(yylval.text)) { - delete[]yylval.text; - yylval.data_type = type; + yylval.type_identifier.text = yylval.text; + yylval.type_identifier.type = type; return TYPE_IDENTIFIER; } } diff --git a/parse.y b/parse.y index d9b8f0166..667c792fc 100644 --- a/parse.y +++ b/parse.y @@ -417,6 +417,11 @@ static void current_function_set_statement(const YYLTYPE&loc, vector property_qualifier_t property_qualifier; PPackage*package; + struct { + char*text; + data_type_t*type; + } type_identifier; + struct { data_type_t*type; list*exprs; @@ -431,7 +436,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector }; %token IDENTIFIER SYSTEM_IDENTIFIER STRING TIME_LITERAL -%token TYPE_IDENTIFIER +%token TYPE_IDENTIFIER %token PACKAGE_IDENTIFIER %token DISCIPLINE_IDENTIFIER %token PATHPULSE_IDENTIFIER @@ -730,10 +735,11 @@ class_identifier $$ = tmp; } | TYPE_IDENTIFIER - { class_type_t*tmp = dynamic_cast($1); + { class_type_t*tmp = dynamic_cast($1.type); if (tmp == 0) { - yyerror(@1, "Type name is not a predeclared class name."); + yyerror(@1, "Type name \"%s\"is not a predeclared class name.", $1.text); } + delete[]$1.text; $$ = tmp; } ; @@ -743,13 +749,14 @@ class_identifier does indeed match a name. */ class_declaration_endlabel_opt : ':' TYPE_IDENTIFIER - { class_type_t*tmp = dynamic_cast ($2); + { class_type_t*tmp = dynamic_cast ($2.type); if (tmp == 0) { - yyerror(@2, "error: class declaration endlabel is not a class name\n"); + yyerror(@2, "error: class declaration endlabel \"%s\" is not a class name\n", $2.text); $$ = 0; } else { $$ = strdupnew(tmp->name.str()); } + delete[]$2.text; } | ':' IDENTIFIER { $$ = $2; } @@ -767,12 +774,14 @@ class_declaration_endlabel_opt class_declaration_extends_opt /* IEEE1800-2005: A.1.2 */ : K_extends TYPE_IDENTIFIER - { $$.type = $2; + { $$.type = $2.type; $$.exprs= 0; + delete[]$2.text; } | K_extends TYPE_IDENTIFIER '(' expression_list_with_nuls ')' - { $$.type = $2; + { $$.type = $2.type; $$.exprs = $4; + delete[]$2.text; } | { $$.type = 0; $$.exprs = 0; } @@ -1013,14 +1022,16 @@ data_type /* IEEE1800-2005: A.2.2.1 */ $$ = tmp; } | TYPE_IDENTIFIER dimensions_opt - { if ($2) $$ = new parray_type_t($1, $2); - else $$ = $1; + { if ($2) $$ = new parray_type_t($1.type, $2); + else $$ = $1.type; + delete[]$1.text; } | PACKAGE_IDENTIFIER K_SCOPE_RES { lex_in_package_scope($1); } TYPE_IDENTIFIER { lex_in_package_scope(0); - $$ = $4; + $$ = $4.type; + delete[]$4.text; } | K_string { string_type_t*tmp = new string_type_t; @@ -2143,6 +2154,20 @@ type_declaration delete[]$3; } + /* If the IDENTIFIER already is a typedef, it is possible for this + code to override the definition, but only if the typedef is + inherited from a different scope. */ + | K_typedef data_type TYPE_IDENTIFIER ';' + { perm_string name = lex_strings.make($3.text); + if (pform_test_type_identifier_local(name)) { + yyerror(@3, "error: Typedef identifier \"%s\" is already a type name.", $3.text); + + } else { + pform_set_typedef(name, $2); + } + delete[]$3.text; + } + /* These are forward declarations... */ | K_typedef K_class IDENTIFIER ';' @@ -2170,9 +2195,6 @@ type_declaration delete[]$2; } - | K_typedef data_type TYPE_IDENTIFIER ';' - { yyerror(@3, "error: Typedef identifier is already a type name."); } - | K_typedef error ';' { yyerror(@2, "error: Syntax error in typedef clause."); yyerrok; @@ -3108,9 +3130,10 @@ expr_primary /* There are a few special cases (notably $bits argument) where the expression may be a type name. Let the elaborator sort this out. */ | TYPE_IDENTIFIER - { PETypename*tmp = new PETypename($1); + { PETypename*tmp = new PETypename($1.type); FILE_NAME(tmp,@1); $$ = tmp; + delete[]$1.text; } /* The hierarchy_identifier rule matches simple identifiers as well as diff --git a/parse_misc.h b/parse_misc.h index 7887818c0..46a937042 100644 --- a/parse_misc.h +++ b/parse_misc.h @@ -96,6 +96,8 @@ extern void lex_in_package_scope(PPackage*pkg); extern data_type_t* pform_test_type_identifier(const char*txt); extern data_type_t* pform_test_type_identifier(PPackage*pkg, const char*txt); +extern bool pform_test_type_identifier_local(perm_string txt); + /* * Test if this identifier is a package name. The pform needs to help * the lexor here because the parser detects packages and saves them. diff --git a/pform.cc b/pform.cc index f2d360521..8d62ddf40 100644 --- a/pform.cc +++ b/pform.cc @@ -584,6 +584,31 @@ data_type_t* pform_test_type_identifier(const char*txt) return 0; } +/* + * The parser uses this function to test if the name is a typedef in + * the current scope. We use this to know if we can override the + * definition because it shadows a containing scope. + */ +bool pform_test_type_identifier_local(perm_string name) +{ + if (lexical_scope == 0) { + if (test_type_identifier_in_root(name)) + return true; + else + return false; + } + + LexicalScope*cur_scope = lexical_scope; + + map::iterator cur; + + cur = cur_scope->typedefs.find(name); + if (cur != cur_scope->typedefs.end()) + return true; + + return false; +} + PECallFunction* pform_make_call_function(const struct vlltype&loc, const pform_name_t&name, const list&parms) From aaee9989c29e9c6a26e80f721aa1cf546ebab483 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 23 Feb 2014 10:31:21 -0800 Subject: [PATCH 005/245] Handle for_variable_declaration This can be handled entirely in the parser, where we rewrite the syntax to me a begin/end block that contains the index variable declaration and the for loop. --- parse.y | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/parse.y b/parse.y index 667c792fc..5afb0a070 100644 --- a/parse.y +++ b/parse.y @@ -1318,10 +1318,42 @@ loop_statement /* IEEE1800-2005: A.6.8 */ $$ = tmp; } + // Handle for_variable_declaration syntax by wrapping the for(...) + // statement in a synthetic named block. We can name the block + // after the variable that we are creating, that identifier is + // safe in the controlling scope. | K_for '(' data_type IDENTIFIER '=' expression ';' expression ';' for_step ')' + { static unsigned for_counter = 0; + char for_block_name [64]; + snprintf(for_block_name, sizeof for_block_name, "$ivl_for_loop%u", for_counter); + for_counter += 1; + PBlock*tmp = pform_push_block_scope(for_block_name, PBlock::BL_SEQ); + FILE_NAME(tmp, @1); + current_block_stack.push(tmp); + + listassign_list; + decl_assignment_t*tmp_assign = new decl_assignment_t; + tmp_assign->name = lex_strings.make($4); + assign_list.push_back(tmp_assign); + pform_makewire(@4, 0, str_strength, &assign_list, NetNet::REG, $3); + } statement_or_null - { $$ = 0; - yyerror(@3, "sorry: for_variable_declaration not supported"); + { pform_name_t tmp_hident; + tmp_hident.push_back(name_component_t(lex_strings.make($4))); + + PEIdent*tmp_ident = pform_new_ident(tmp_hident); + FILE_NAME(tmp_ident, @4); + + PForStatement*tmp_for = new PForStatement(tmp_ident, $6, $8, $10, $13); + FILE_NAME(tmp_for, @1); + + pform_pop_scope(); + vectortmp_for_list (1); + tmp_for_list[0] = tmp_for; + PBlock*tmp_blk = current_block_stack.top(); + tmp_blk->set_statement(tmp_for_list); + $$ = tmp_blk; + delete[]$4; } | K_forever statement_or_null From f8e33b12cd4048ef124a2bd7a6842453a14bc32b Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 9 Mar 2014 19:22:13 -0700 Subject: [PATCH 006/245] Clean up pform_module_define_port in preparation for new tricks. Get rid of the data_type, signed_flag, and range arguments to the pform_module_define_port because they add no value within the parse.y parser. Cleaning these out will hopefully ease the addition of new functionality. --- parse.y | 90 +++++++++++++++----------------------------------------- pform.cc | 14 ++++----- pform.h | 3 -- 3 files changed, 28 insertions(+), 79 deletions(-) diff --git a/parse.y b/parse.y index 5afb0a070..02f697b17 100644 --- a/parse.y +++ b/parse.y @@ -46,12 +46,8 @@ static ivl_variable_type_t param_active_type = IVL_VT_LOGIC; static struct { NetNet::Type port_net_type; NetNet::PortType port_type; - ivl_variable_type_t var_type; - bool sign_flag; data_type_t* data_type; - list* range; -} port_declaration_context = {NetNet::NONE, NetNet::NOT_A_PORT, - IVL_VT_NO_TYPE, false, 0, 0}; +} port_declaration_context = {NetNet::NONE, NetNet::NOT_A_PORT, 0}; /* The task and function rules need to briefly hold the pointer to the task/function that is currently in progress. */ @@ -1900,27 +1896,16 @@ tf_port_item /* IEEE1800-2005: A.2.7 */ if ($4 != 0) { yyerror(@4, "internal error: How can there be an unpacked range here?\n"); } - if (port_declaration_context.var_type == IVL_VT_NO_TYPE) { - tmp = pform_make_task_ports(@3, use_port_type, - port_declaration_context.data_type, - ilist); - } else { - tmp = pform_make_task_ports(@3, use_port_type, - port_declaration_context.var_type, - port_declaration_context.sign_flag, - copy_range(port_declaration_context.range), - ilist); - } + tmp = pform_make_task_ports(@3, use_port_type, + port_declaration_context.data_type, + ilist); + } else { // Otherwise, the decorations for this identifier // indicate the type. Save the type for any right // context thta may come later. port_declaration_context.port_type = use_port_type; - port_declaration_context.var_type = IVL_VT_NO_TYPE; - port_declaration_context.sign_flag = false; - delete port_declaration_context.range; - port_declaration_context.range = 0; if ($2 == 0) { $2 = new vector_type_t(IVL_VT_LOGIC, false, 0); FILE_NAME($2, @3); @@ -3817,10 +3802,7 @@ list_of_port_declarations pform_module_define_port(@3, name, port_declaration_context.port_type, port_declaration_context.port_net_type, - port_declaration_context.var_type, - port_declaration_context.sign_flag, - port_declaration_context.data_type, - port_declaration_context.range, 0); + port_declaration_context.data_type, 0); delete[]$3; $$ = tmp; } @@ -3841,14 +3823,9 @@ port_declaration { Module::port_t*ptmp; perm_string name = lex_strings.make($5); ptmp = pform_module_port_reference(name, @2.text, @2.first_line); - pform_module_define_port(@2, name, NetNet::PINPUT, $3, IVL_VT_NO_TYPE, - false, $4, 0, $1); + pform_module_define_port(@2, name, NetNet::PINPUT, $3, $4, $1); port_declaration_context.port_type = NetNet::PINPUT; port_declaration_context.port_net_type = $3; - port_declaration_context.var_type = IVL_VT_NO_TYPE; - port_declaration_context.sign_flag = false; - delete port_declaration_context.range; - port_declaration_context.range = 0; port_declaration_context.data_type = $4; delete[]$5; if ($6) { @@ -3863,15 +3840,13 @@ port_declaration perm_string name = lex_strings.make($4); ptmp = pform_module_port_reference(name, @2.text, @2.first_line); - pform_module_define_port(@2, name, NetNet::PINPUT, - NetNet::WIRE, IVL_VT_REAL, true, 0, 0, $1); + real_type_t*real_type = new real_type_t(real_type_t::REAL); + FILE_NAME(real_type, @3); + pform_module_define_port(@2, name, NetNet::PINPUT, + NetNet::WIRE, real_type, $1); port_declaration_context.port_type = NetNet::PINPUT; port_declaration_context.port_net_type = NetNet::WIRE; - port_declaration_context.var_type = IVL_VT_REAL; - port_declaration_context.sign_flag = true; - delete port_declaration_context.range; - port_declaration_context.range = 0; - port_declaration_context.data_type = 0; + port_declaration_context.data_type = real_type; delete[]$4; $$ = ptmp; } @@ -3879,14 +3854,9 @@ port_declaration { Module::port_t*ptmp; perm_string name = lex_strings.make($5); ptmp = pform_module_port_reference(name, @2.text, @2.first_line); - pform_module_define_port(@2, name, NetNet::PINOUT, $3, IVL_VT_NO_TYPE, - false, $4, 0, $1); + pform_module_define_port(@2, name, NetNet::PINOUT, $3, $4, $1); port_declaration_context.port_type = NetNet::PINOUT; port_declaration_context.port_net_type = $3; - port_declaration_context.var_type = IVL_VT_NO_TYPE; - port_declaration_context.sign_flag = false; - delete port_declaration_context.range; - port_declaration_context.range = 0; port_declaration_context.data_type = $4; delete[]$5; if ($6) { @@ -3901,15 +3871,13 @@ port_declaration perm_string name = lex_strings.make($4); ptmp = pform_module_port_reference(name, @2.text, @2.first_line); + real_type_t*real_type = new real_type_t(real_type_t::REAL); + FILE_NAME(real_type, @3); pform_module_define_port(@2, name, NetNet::PINOUT, - NetNet::WIRE, IVL_VT_REAL, true, 0, 0, $1); + NetNet::WIRE, real_type, $1); port_declaration_context.port_type = NetNet::PINOUT; port_declaration_context.port_net_type = NetNet::WIRE; - port_declaration_context.var_type = IVL_VT_REAL; - port_declaration_context.sign_flag = true; - delete port_declaration_context.range; - port_declaration_context.range = 0; - port_declaration_context.data_type = 0; + port_declaration_context.data_type = real_type; delete[]$4; $$ = ptmp; } @@ -3937,14 +3905,9 @@ port_declaration } } ptmp = pform_module_port_reference(name, @2.text, @2.first_line); - pform_module_define_port(@2, name, NetNet::POUTPUT, use_type, IVL_VT_NO_TYPE, - false, $4, 0, $1); + pform_module_define_port(@2, name, NetNet::POUTPUT, use_type, $4, $1); port_declaration_context.port_type = NetNet::POUTPUT; port_declaration_context.port_net_type = use_type; - port_declaration_context.var_type = IVL_VT_NO_TYPE; - port_declaration_context.sign_flag = false; - delete port_declaration_context.range; - port_declaration_context.range = 0; port_declaration_context.data_type = $4; delete[]$5; if ($6) { @@ -3959,15 +3922,13 @@ port_declaration perm_string name = lex_strings.make($4); ptmp = pform_module_port_reference(name, @2.text, @2.first_line); + real_type_t*real_type = new real_type_t(real_type_t::REAL); + FILE_NAME(real_type, @3); pform_module_define_port(@2, name, NetNet::POUTPUT, - NetNet::WIRE, IVL_VT_REAL, true, 0, 0, $1); + NetNet::WIRE, real_type, $1); port_declaration_context.port_type = NetNet::POUTPUT; port_declaration_context.port_net_type = NetNet::WIRE; - port_declaration_context.var_type = IVL_VT_REAL; - port_declaration_context.sign_flag = true; - delete port_declaration_context.range; - port_declaration_context.range = 0; - port_declaration_context.data_type = 0; + port_declaration_context.data_type = real_type; delete[]$4; $$ = ptmp; } @@ -3986,14 +3947,9 @@ port_declaration } } ptmp = pform_module_port_reference(name, @2.text, @2.first_line); - pform_module_define_port(@2, name, NetNet::POUTPUT, use_type, IVL_VT_NO_TYPE, - false, $4, 0, $1); + pform_module_define_port(@2, name, NetNet::POUTPUT, use_type, $4, $1); port_declaration_context.port_type = NetNet::PINOUT; port_declaration_context.port_net_type = use_type; - port_declaration_context.var_type = IVL_VT_NO_TYPE; - port_declaration_context.sign_flag = false; - delete port_declaration_context.range; - port_declaration_context.range = 0; port_declaration_context.data_type = $4; pform_make_reginit(@5, name, $7); diff --git a/pform.cc b/pform.cc index 8d62ddf40..ce50148b3 100644 --- a/pform.cc +++ b/pform.cc @@ -2154,15 +2154,14 @@ void pform_make_reginit(const struct vlltype&li, */ void pform_module_define_port(const struct vlltype&li, perm_string name, - NetNet::PortType port_type, + NetNet::PortType port_kind, NetNet::Type type, - ivl_variable_type_t data_type, - bool signed_flag, data_type_t*vtype, - list*range, list*attr) { struct_type_t*struct_type = 0; + ivl_variable_type_t data_type = IVL_VT_NO_TYPE; + bool signed_flag = false; PWire*cur = pform_get_wire_in_scope(name); if (cur) { @@ -2174,10 +2173,7 @@ void pform_module_define_port(const struct vlltype&li, return; } - if (vtype) { - ivl_assert(li, data_type == IVL_VT_NO_TYPE); - ivl_assert(li, range == 0); - } + list*range = 0; if (vector_type_t*vec_type = dynamic_cast (vtype)) { data_type = vec_type->base_type; @@ -2216,7 +2212,7 @@ void pform_module_define_port(const struct vlltype&li, if (data_type == IVL_VT_NO_TYPE) data_type = IVL_VT_LOGIC; - cur = new PWire(name, type, port_type, data_type); + cur = new PWire(name, type, port_kind, data_type); FILE_NAME(cur, li); cur->set_signed(signed_flag); diff --git a/pform.h b/pform.h index 420f437bd..ebe38395d 100644 --- a/pform.h +++ b/pform.h @@ -168,10 +168,7 @@ extern void pform_module_define_port(const struct vlltype&li, perm_string name, NetNet::PortType, NetNet::Type type, - ivl_variable_type_t data_type, - bool signed_flag, data_type_t*vtype, - list*range, list*attr); extern Module::port_t* pform_module_port_reference(perm_string name, From 751f19cc46758107f36ec41a769fefc431e58d61 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sat, 15 Mar 2014 17:16:39 -0700 Subject: [PATCH 007/245] Symbolic printout of PortType enumeration values. --- design_dump.cc | 29 +++++++++++++++++++++++++++++ netlist.h | 1 + 2 files changed, 30 insertions(+) diff --git a/design_dump.cc b/design_dump.cc index e42347bcb..52627302f 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -145,6 +145,35 @@ ostream& operator << (ostream&o, ivl_switch_type_t val) return o; } +ostream& operator << (ostream&fd, PortType::Enum val) +{ + switch (val) { + case PortType::NOT_A_PORT: + fd << "NOT_A_PORT"; + break; + case PortType::PIMPLICIT: + fd << "PIMPLICIT"; + break; + case PortType::PINPUT: + fd << "PINPUT"; + break; + case PortType::POUTPUT: + fd << "POUTPUT"; + break; + case PortType::PINOUT: + fd << "PINOUT"; + break; + case PortType::PREF: + fd << "PREF"; + break; + default: + fd << "PortType::Enum::?"; + break; + } + + return fd; +} + ostream& ivl_type_s::debug_dump(ostream&o) const { o << typeid(*this).name(); diff --git a/netlist.h b/netlist.h index 6cefc4c15..a373ff018 100644 --- a/netlist.h +++ b/netlist.h @@ -610,6 +610,7 @@ public: static Enum merged( Enum lhs, Enum rhs ); }; +extern std::ostream& operator << (std::ostream&, PortType::Enum); /* * Information on actual ports (rather than port-connected signals) of From 6caa41cc93d892a6f2e58536552b8b1875f1d061 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 16 Mar 2014 17:08:38 -0700 Subject: [PATCH 008/245] First pass at support for continuous assign of unpacked net arrays. --- PExpr.h | 5 ++++ PGate.h | 1 + elab_expr.cc | 1 + elab_net.cc | 64 ++++++++++++++++++++++++++++++++++++++++++++++++++-- elaborate.cc | 32 ++++++++++++++++++++++++-- parse.y | 8 +++---- pform.cc | 28 +++++++++++++++++------ 7 files changed, 123 insertions(+), 16 deletions(-) diff --git a/PExpr.h b/PExpr.h index 5b014de8a..556dd3491 100644 --- a/PExpr.h +++ b/PExpr.h @@ -366,6 +366,11 @@ class PEIdent : public PExpr { // only applies to Ident expressions. NetNet* elaborate_subport(Design*des, NetScope*sc) const; + // Elaborate the identifier allowing for unpacked arrays. This + // method only applies to Ident expressions because only Ident + // expressions can can be unpacked arrays. + NetNet* elaborate_unpacked_net(Design*des, NetScope*sc) const; + verinum* eval_const(Design*des, NetScope*sc) const; virtual bool is_collapsible_net(Design*des, NetScope*scope) const; diff --git a/PGate.h b/PGate.h index 85ea1194b..7b726fa68 100644 --- a/PGate.h +++ b/PGate.h @@ -124,6 +124,7 @@ class PGAssign : public PGate { virtual bool elaborate_sig(Design*des, NetScope*scope) const; private: + void elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval) const; }; diff --git a/elab_expr.cc b/elab_expr.cc index bee085511..0d9b82847 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2585,6 +2585,7 @@ bool PEIdent::calculate_packed_indices_(Design*des, NetScope*scope, NetNet*net, { list index; index = path_.back().index; + ivl_assert(*this, index.size() >= net->unpacked_dimensions()); for (size_t idx = 0 ; idx < net->unpacked_dimensions() ; idx += 1) index.pop_front(); diff --git a/elab_net.cc b/elab_net.cc index 1cad8de9c..ad7adf138 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -501,6 +501,10 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, unsigned midx = sig->vector_width()-1, lidx = 0; // The default word select is the first. long widx = 0; + // Set this to true if we calculate the word index. This is + // used to distinguish between unpacked array assignment and + // array word assignment. + bool widx_flag = false; list unpacked_indices_const; @@ -590,13 +594,31 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, midx = lidx + tmp_wid - 1; } + } else if (gn_system_verilog() && sig->unpacked_dimensions() > 0 && path_tail.index.size() == 0) { + + // In this case, we are doing a continuous assignment to + // an unpacked array. The NetNet representation is a + // NetNet with a pin for each array element, so there is + // nothing more needed here. + // + // This can come up from code like this: + // logic [...] data [0:3]; + // assign data = ...; + // In this case, "sig" is "data", and sig->pin_count() + // is 4 to account for the unpacked size. + if (debug_elaborate) { + cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: " + << "Net assign to unpacked array \"" << sig->name() + << "\" with " << sig->pin_count() << " elements." << endl; + } + } else if (sig->unpacked_dimensions() > 0) { // Make sure there are enough indices to address an array element. if (path_tail.index.size() < sig->unpacked_dimensions()) { cerr << get_fileline() << ": error: Array " << path() << " needs " << sig->unpacked_dimensions() << " indices," - << " but got only " << path_tail.index.size() << "." << endl; + << " but got only " << path_tail.index.size() << ". (net)" << endl; des->errors += 1; return 0; } @@ -627,6 +649,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, << sig->name() << as_indices(unpacked_indices) << "." << endl; widx = -1; + widx_flag = true; } else { NetExpr*canon_index = 0; @@ -639,12 +662,14 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, << sig->name() << as_indices(unpacked_indices_const) << "." << endl; widx = -1; + widx_flag = true; } else { NetEConst*canon_const = dynamic_cast(canon_index); ivl_assert(*this, canon_const); widx = canon_const->value().as_long(); + widx_flag = true; delete canon_index; } } @@ -717,7 +742,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, return 0; } - if (sig->pin_count() > 1) { + if (sig->pin_count() > 1 && widx_flag) { if (widx < 0 || widx >= (long) sig->pin_count()) return 0; @@ -729,6 +754,13 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, tmp->local_flag(true); connect(sig->pin(widx), tmp->pin(0)); sig = tmp; + + } else if (sig->pin_count() > 1) { + + // If this turns out to be an l-value unpacked array, + // then let the caller handle it. It will probably be + // converted into an array of assignments. + return sig; } /* If the desired l-value vector is narrower than the @@ -851,6 +883,20 @@ NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const long midx; long lidx; + if (debug_elaborate) { + cerr << get_fileline() << ": PEIdent::elaborate_subport: " + << "path_ = \"" << path_ + << "\", unpacked_dimensions=" << sig->unpacked_dimensions() + << ", port_type()=" << sig->port_type() << endl; + } + + if (sig->unpacked_dimensions()) { + cerr << get_fileline() << ": sorry: " + << "Don't know now to elaborate unpacked array ports." << endl; + des->errors += 1; + return 0; + } + /* Evaluate the part/bit select expressions, to get the part select of the signal that attaches to the port. Also handle range and direction checking here. */ @@ -912,6 +958,20 @@ NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const return sig; } +NetNet*PEIdent::elaborate_unpacked_net(Design*des, NetScope*scope) const +{ + NetNet* sig = 0; + const NetExpr*par = 0; + NetEvent* eve = 0; + perm_string method_name; + + symbol_search(this, des, scope, path_, sig, par, eve); + + ivl_assert(*this, sig); + + return sig; +} + bool PEIdent::is_collapsible_net(Design*des, NetScope*scope) const { assert(scope); diff --git a/elaborate.cc b/elaborate.cc index 66f346853..64925639e 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -77,11 +77,19 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const return; } + // If this turns out to be an assignment to an unpacked array, + // then handle that special case elsewhere. + if (lval->pin_count() > 1) { + elaborate_unpacked_array_(des, scope, lval); + return; + } + ivl_assert(*this, lval->pin_count() == 1); if (debug_elaborate) { - cerr << get_fileline() << ": debug: PGAssign: elaborated l-value" - << " width=" << lval->vector_width() << endl; + cerr << get_fileline() << ": PGAssign::elaborate: elaborated l-value" + << " width=" << lval->vector_width() + << ", pin_count=" << lval->pin_count() << endl; } NetExpr*rval_expr = elaborate_rval_expr(des, scope, lval->net_type(), @@ -211,6 +219,26 @@ void PGAssign::elaborate(Design*des, NetScope*scope) const } +void PGAssign::elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval) const +{ + PEIdent*rval_pident = dynamic_cast (pin(1)); + ivl_assert(*this, rval_pident); + + NetNet*rval_net = rval_pident->elaborate_unpacked_net(des, scope); + + ivl_assert(*this, rval_net->pin_count() == lval->pin_count()); + + for (unsigned idx = 0 ; idx < lval->pin_count() ; idx += 1) { + NetBUFZ*driver = new NetBUFZ(scope, scope->local_symbol(), + lval->vector_width(), false); + driver->set_line(*this); + des->add_node(driver); + + connect(lval->pin(idx), driver->pin(0)); + connect(driver->pin(1), rval_net->pin(idx)); + } +} + unsigned PGBuiltin::calculate_array_count_(Design*des, NetScope*scope, long&high, long&low) const { diff --git a/parse.y b/parse.y index 02f697b17..3fdcdd6f6 100644 --- a/parse.y +++ b/parse.y @@ -3822,16 +3822,14 @@ port_declaration : attribute_list_opt K_input net_type_opt data_type_or_implicit IDENTIFIER dimensions_opt { Module::port_t*ptmp; perm_string name = lex_strings.make($5); + data_type_t*use_type = $4; + if ($6) use_type = new uarray_type_t(use_type, $6); ptmp = pform_module_port_reference(name, @2.text, @2.first_line); - pform_module_define_port(@2, name, NetNet::PINPUT, $3, $4, $1); + pform_module_define_port(@2, name, NetNet::PINPUT, $3, use_type, $1); port_declaration_context.port_type = NetNet::PINPUT; port_declaration_context.port_net_type = $3; port_declaration_context.data_type = $4; delete[]$5; - if ($6) { - yyerror(@6, "sorry: Input ports with unpacked dimensions not supported."); - delete $6; - } $$ = ptmp; } | attribute_list_opt diff --git a/pform.cc b/pform.cc index ce50148b3..b8a408b86 100644 --- a/pform.cc +++ b/pform.cc @@ -2173,24 +2173,34 @@ void pform_module_define_port(const struct vlltype&li, return; } - list*range = 0; + // Packed ranges + list*prange = 0; + // Unpacked dimensions + list*urange = 0; + + // If this is an unpacked array, then split out the parts that + // we can send to the PWire object that we create. + if (uarray_type_t*uarr_type = dynamic_cast (vtype)) { + urange = uarr_type->dims.get(); + vtype = uarr_type->base_type; + } if (vector_type_t*vec_type = dynamic_cast (vtype)) { data_type = vec_type->base_type; signed_flag = vec_type->signed_flag; - range = vec_type->pdims.get(); + prange = vec_type->pdims.get(); if (vec_type->reg_flag) type = NetNet::REG; } else if (atom2_type_t*atype = dynamic_cast(vtype)) { data_type = IVL_VT_BOOL; signed_flag = atype->signed_flag; - range = make_range_from_width(atype->type_code); + prange = make_range_from_width(atype->type_code); } else if (real_type_t*rtype = dynamic_cast(vtype)) { data_type = IVL_VT_REAL; signed_flag = true; - range = 0; + prange = 0; if (rtype->type_code != real_type_t::REAL) { VLerror(li, "sorry: Only real (not shortreal) supported here (%s:%d).", @@ -2200,7 +2210,7 @@ void pform_module_define_port(const struct vlltype&li, } else if ((struct_type = dynamic_cast(vtype))) { data_type = struct_type->figure_packed_base_type(); signed_flag = false; - range = 0; + prange = 0; } else if (vtype) { VLerror(li, "sorry: Given type %s not supported here (%s:%d).", @@ -2220,11 +2230,15 @@ void pform_module_define_port(const struct vlltype&li, if (struct_type) { cur->set_data_type(struct_type); - } else if (range == 0) { + } else if (prange == 0) { cur->set_range_scalar((type == NetNet::IMPLICIT) ? SR_PORT : SR_BOTH); } else { - cur->set_range(*range, (type == NetNet::IMPLICIT) ? SR_PORT : SR_BOTH); + cur->set_range(*prange, (type == NetNet::IMPLICIT) ? SR_PORT : SR_BOTH); + } + + if (urange) { + cur->set_unpacked_idx(*urange); } pform_bind_attributes(cur->attributes, attr); From fc1f9ac6a54079822ea2f58a4dd932b570c62ef7 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sat, 22 Mar 2014 20:50:47 -0700 Subject: [PATCH 009/245] Handle unpacked arrays as module input ports. --- elab_expr.cc | 2 +- elab_net.cc | 19 ++++++++++++++++--- elaborate.cc | 50 +++++++++++++++++++++++++++++++++++--------------- netmisc.cc | 18 ++++++++++++++++++ netmisc.h | 4 ++++ 5 files changed, 74 insertions(+), 19 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 0d9b82847..179ec1bce 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -3970,7 +3970,7 @@ NetExpr* PEIdent::elaborate_expr_net_word_(Design*des, NetScope*scope, if (name_tail.index.empty()) { cerr << get_fileline() << ": error: Array " << path() - << " Needs an array index here." << endl; + << " needs an array index here." << endl; des->errors += 1; return 0; } diff --git a/elab_net.cc b/elab_net.cc index ad7adf138..7270a8aff 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -890,13 +890,26 @@ NetNet* PEIdent::elaborate_subport(Design*des, NetScope*scope) const << ", port_type()=" << sig->port_type() << endl; } - if (sig->unpacked_dimensions()) { - cerr << get_fileline() << ": sorry: " - << "Don't know now to elaborate unpacked array ports." << endl; + if (sig->unpacked_dimensions() && !gn_system_verilog()) { + cerr << get_fileline() << ": error: " + << "Ports cannot be unpacked arrays. Try enabling SystemVerilog support." << endl; des->errors += 1; return 0; } + // There cannot be parts to an unpacked array, so process this + // simply as an unpacked array. + if (sig->unpacked_dimensions()) { + if (debug_elaborate) { + cerr << get_fileline() << ": PEIdent::elaborate_subport: " + << "path_=\"" << path_ + << "\" is an unpacked array with " << sig->pin_count() + << " elements." << endl; + } + scope->add_module_port_net(sig); + return sig; + } + /* Evaluate the part/bit select expressions, to get the part select of the signal that attaches to the port. Also handle range and direction checking here. */ diff --git a/elaborate.cc b/elaborate.cc index 64925639e..9ed0d089b 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -228,15 +228,7 @@ void PGAssign::elaborate_unpacked_array_(Design*des, NetScope*scope, NetNet*lval ivl_assert(*this, rval_net->pin_count() == lval->pin_count()); - for (unsigned idx = 0 ; idx < lval->pin_count() ; idx += 1) { - NetBUFZ*driver = new NetBUFZ(scope, scope->local_symbol(), - lval->vector_width(), false); - driver->set_line(*this); - des->add_node(driver); - - connect(lval->pin(idx), driver->pin(0)); - connect(driver->pin(1), rval_net->pin(idx)); - } + assign_unpacked_with_bufz(des, scope, this, lval, rval_net); } unsigned PGBuiltin::calculate_array_count_(Design*des, NetScope*scope, @@ -1378,18 +1370,22 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const unsigned int prt_vector_width = 0; PortType::Enum ptype = PortType::PIMPLICIT; // Scan the module sub-ports for this instance... + // (Sub-ports are concatenated ports that form the + // single port for the instance. This is not a + // commonly used feature.) for (unsigned ldx = 0 ; ldx < mport.size() ; ldx += 1) { unsigned lbase = inst * mport.size(); PEIdent*pport = mport[ldx]; - assert(pport); + ivl_assert(*this, pport); NetNet *netnet = pport->elaborate_subport(des, inst_scope); prts[lbase + ldx] = netnet; if (netnet == 0) continue; - assert(netnet); - prts_vector_width += netnet->vector_width(); - prt_vector_width += netnet->vector_width(); + ivl_assert(*this, netnet); + unsigned port_width = netnet->vector_width() * netnet->pin_count(); + prts_vector_width += port_width; + prt_vector_width += port_width; ptype = PortType::merged(netnet->port_type(), ptype); } inst_scope->add_module_port_info(idx, rmod->get_port_name(idx), ptype, prt_vector_width ); @@ -1420,9 +1416,25 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const // module[s] port. sig is the thing outside the module // that connects to the port. - NetNet*sig; + NetNet*sig = 0; if (prts.empty() || (prts[0]->port_type() == NetNet::PINPUT)) { + // Special case: If the input port is an unpacked + // array, then there should be no sub-ports and + // the r-value expression is processed + // differently. + if (prts.size() >= 1 && prts[0]->pin_count()>1) { + ivl_assert(*this, prts.size()==1); + + PEIdent*rval_pident = dynamic_cast (pins[idx]); + ivl_assert(*this, rval_pident); + + NetNet*rval_net = rval_pident->elaborate_unpacked_net(des, scope); + ivl_assert(*this, rval_net->pin_count() == prts[0]->pin_count()); + assign_unpacked_with_bufz(des, scope, this, prts[0], rval_net); + continue; + } + /* Input to module. elaborate the expression to the desired width. If this in an instance array, then let the net determine its own @@ -1499,6 +1511,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const } else if (prts[0]->port_type() == NetNet::PINOUT) { + // For now, do not support unpacked array outputs. + ivl_assert(*this, prts[0]->unpacked_dimensions()==0); + /* Inout to/from module. This is a more complicated case, where the expression must be an lnet, but also an r-value net. @@ -1555,6 +1570,9 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const } else { + // For now, do not support unpacked array outputs. + ivl_assert(*this, prts[0]->unpacked_dimensions()==0); + /* Port type must be OUTPUT here. */ ivl_assert(*this, prts[0]->port_type() == NetNet::POUTPUT); @@ -5840,7 +5858,9 @@ Design* elaborate(listroots) // stuff to the design that should be cleaned later. NetNet *netnet = mport[pin]->elaborate_subport(des, scope); if (netnet != 0) { - // Elaboration may actually fail with erroneous input source + // Elaboration may actually fail with + // erroneous input source + ivl_assert(*mport[pin], netnet->pin_count()==1); prt_vector_width += netnet->vector_width(); ptype = PortType::merged(netnet->port_type(), ptype); } diff --git a/netmisc.cc b/netmisc.cc index 91c974184..2beb1aa5f 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -1338,3 +1338,21 @@ NetExpr*collapse_array_indices(Design*des, NetScope*scope, NetNet*net, eval_expr(res, -1); return res; } + +void assign_unpacked_with_bufz(Design*des, NetScope*scope, + const LineInfo*loc, + NetNet*lval, NetNet*rval) +{ + ivl_assert(*loc, lval->pin_count()==rval->pin_count()); + + for (unsigned idx = 0 ; idx < lval->pin_count() ; idx += 1) { + NetBUFZ*driver = new NetBUFZ(scope, scope->local_symbol(), + lval->vector_width(), false); + driver->set_line(*loc); + des->add_node(driver); + + connect(lval->pin(idx), driver->pin(0)); + connect(driver->pin(1), rval->pin(idx)); + } +} + diff --git a/netmisc.h b/netmisc.h index 90d73cb9c..1eb6ad717 100644 --- a/netmisc.h +++ b/netmisc.h @@ -349,4 +349,8 @@ extern NetExpr*collapse_array_exprs(Design*des, NetScope*scope, const LineInfo*loc, NetNet*net, const list&indices); +extern void assign_unpacked_with_bufz(Design*des, NetScope*scope, + const LineInfo*loc, + NetNet*lval, NetNet*rval); + #endif From e55e832ea0e197c2351ad7ea61efb0947753fc8f Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 23 Mar 2014 16:53:38 -0700 Subject: [PATCH 010/245] Handle unpacked arrays as output ports. --- elaborate.cc | 25 ++++++++++++++++++++++--- parse.y | 8 +++----- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/elaborate.cc b/elaborate.cc index 9ed0d089b..4c203db17 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -1570,12 +1570,31 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const } else { - // For now, do not support unpacked array outputs. - ivl_assert(*this, prts[0]->unpacked_dimensions()==0); - /* Port type must be OUTPUT here. */ ivl_assert(*this, prts[0]->port_type() == NetNet::POUTPUT); + // Special case: If the output port is an unpacked + // array, then there should be no sub-ports and + // the passed pexxpression 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. + if (prts[0]->pin_count() > 1) { + ivl_assert(*this, prts.size()==1); + + PEIdent*rval_pident = dynamic_cast(pins[idx]); + ivl_assert(*this, rval_pident); + + NetNet*rval_net = rval_pident->elaborate_unpacked_net(des, scope); + ivl_assert(*this, rval_net->pin_count() == prts[0]->pin_count()); + + assign_unpacked_with_bufz(des, scope, this, rval_net, prts[0]); + continue; + } + + // At this point, arrays are handled. + ivl_assert(*this, prts[0]->unpacked_dimensions()==0); + /* Output from module. Elaborate the port expression as the l-value of a continuous assignment, as the port will continuous assign diff --git a/parse.y b/parse.y index 3fdcdd6f6..59e526e4e 100644 --- a/parse.y +++ b/parse.y @@ -3882,6 +3882,8 @@ port_declaration | attribute_list_opt K_output net_type_opt data_type_or_implicit IDENTIFIER dimensions_opt { Module::port_t*ptmp; perm_string name = lex_strings.make($5); + data_type_t*use_dtype = $4; + if ($6) use_dtype = new uarray_type_t(use_dtype, $6); NetNet::Type use_type = $3; if (use_type == NetNet::IMPLICIT) { if (vector_type_t*dtype = dynamic_cast ($4)) { @@ -3903,15 +3905,11 @@ port_declaration } } ptmp = pform_module_port_reference(name, @2.text, @2.first_line); - pform_module_define_port(@2, name, NetNet::POUTPUT, use_type, $4, $1); + pform_module_define_port(@2, name, NetNet::POUTPUT, use_type, use_dtype, $1); port_declaration_context.port_type = NetNet::POUTPUT; port_declaration_context.port_net_type = use_type; port_declaration_context.data_type = $4; delete[]$5; - if ($6) { - yyerror(@6, "sorry: Output ports with unpacked dimensions not supported."); - delete $6; - } $$ = ptmp; } | attribute_list_opt From 0accab6ec4d56874865ecdba663f23a038305caa Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Fri, 28 Mar 2014 20:51:30 -0700 Subject: [PATCH 011/245] Handle non-overlapping assignments to unpacked arrays. --- elab_net.cc | 2 +- netlist.cc | 16 ++++++++++++---- netlist.h | 6 ++++-- 3 files changed, 17 insertions(+), 7 deletions(-) diff --git a/elab_net.cc b/elab_net.cc index 7270a8aff..0f5deabfb 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -735,7 +735,7 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, unsigned subnet_wid = midx-lidx+1; /* Check if the l-value bits are double-driven. */ - if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->test_and_set_part_driver(midx,lidx)) { + if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->test_and_set_part_driver(midx,lidx, widx_flag? widx : 0)) { cerr << get_fileline() << ": error: Unresolved net/uwire " << sig->name() << " cannot have multiple drivers." << endl; des->errors += 1; diff --git a/netlist.cc b/netlist.cc index e66c9c7c9..e43c52046 100644 --- a/netlist.cc +++ b/netlist.cc @@ -868,17 +868,25 @@ unsigned NetNet::peek_eref() const * Test each of the bits in the range, and set them. If any bits are * already set then return true. */ -bool NetNet::test_and_set_part_driver(unsigned pmsb, unsigned plsb) +bool NetNet::test_and_set_part_driver(unsigned pmsb, unsigned plsb, int widx) { if (lref_mask_.empty()) - lref_mask_.resize(vector_width()); + lref_mask_.resize(vector_width() * pin_count()); + + // If indexing a word that doesn't exist, then pretend this is + // never driven. + if (widx < 0) + return false; + if (widx >= (int)pin_count()) + return false; bool rc = false; + unsigned word_base = vector_width() * widx; for (unsigned idx = plsb ; idx <= pmsb ; idx += 1) { - if (lref_mask_[idx]) + if (lref_mask_[idx+word_base]) rc = true; else - lref_mask_[idx] = true; + lref_mask_[idx+word_base] = true; } return rc; diff --git a/netlist.h b/netlist.h index a373ff018..58d2e5d7f 100644 --- a/netlist.h +++ b/netlist.h @@ -750,8 +750,10 @@ class NetNet : public NetObj, public PortType { // Treating this node as a uwire, this function tests whether // any bits in the canonical part are already driven. This is - // only useful for UNRESOLVED_WIRE objects. - bool test_and_set_part_driver(unsigned msb, unsigned lsb); + // only useful for UNRESOLVED_WIRE objects. The msb and lsb + // are the part select of the signal, and the widx is the word + // index if this is an unpacked array. + bool test_and_set_part_driver(unsigned msb, unsigned lsb, int widx =0); unsigned get_refs() const; From e2bad56a5c811d543529a46716f89d9ea285bd44 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sat, 29 Mar 2014 11:23:16 -0700 Subject: [PATCH 012/245] Fix overflow calculating packed offset in certain cases. --- elab_net.cc | 5 +++-- netmisc.cc | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/elab_net.cc b/elab_net.cc index 0f5deabfb..2495b9d6c 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -559,8 +559,9 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, packed_base = collapse_array_indices(des, scope, sig, tmp_index); if (debug_elaborate) { - cerr << get_fileline() << ": debug: " - << "packed_base expression = " << *packed_base << endl; + cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: " + << "packed_base=" << *packed_base + << ", member_off=" << member_off << endl; } } diff --git a/netmisc.cc b/netmisc.cc index 2beb1aa5f..4271720a7 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -309,7 +309,7 @@ NetExpr *normalize_variable_base(NetExpr *base, long msb, long lsb, if (min_wid < base->expr_width()) min_wid = base->expr_width(); /* Now that we have the minimum needed width increase it by * one to make room for the normalization calculation. */ - min_wid += 1; + min_wid += 2; /* Pad the base expression to the correct width. */ base = pad_to_width(base, min_wid, *base); /* If the base expression is unsigned and either the lsb @@ -344,7 +344,7 @@ NetExpr *normalize_variable_base(NetExpr *base, long msb, long lsb, if (min_wid < base->expr_width()) min_wid = base->expr_width(); /* Now that we have the minimum needed width increase it by * one to make room for the normalization calculation. */ - min_wid += 1; + min_wid += 2; /* Pad the base expression to the correct width. */ base = pad_to_width(base, min_wid, *base); /* If the offset is greater than zero then we need to do From 2e2317b7c7f4d97ae18d94e05794f71e49542bd4 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 30 Mar 2014 17:20:42 -0700 Subject: [PATCH 013/245] Generalize the hname_t to handle n-dimensional scope arrays. ... Not that they actually exist yet. But this fixes some symbol search issues and makes room for this support in the future. --- HName.cc | 68 ++++++++++++++++++++++++++++++++++-------------- HName.h | 34 ++++++++++++------------ design_dump.cc | 4 +-- elab_scope.cc | 6 +++-- elab_sig.cc | 2 +- net_scope.cc | 15 +++++++++++ netlist.h | 6 +++++ netmisc.cc | 70 ++++++++++++++++++++++++-------------------------- t-dll.cc | 15 ++++++++--- 9 files changed, 140 insertions(+), 80 deletions(-) diff --git a/HName.cc b/HName.cc index 709528489..c783d57bb 100644 --- a/HName.cc +++ b/HName.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2012 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -22,22 +22,26 @@ # include # include # include -# include +using namespace std; hname_t::hname_t() { - number_ = INT_MIN; } hname_t::hname_t(perm_string text) : name_(text) { - number_ = INT_MIN; } hname_t::hname_t(perm_string text, int num) -: name_(text), number_(num) +: name_(text), number_(1) +{ + number_[0] = num; +} + +hname_t::hname_t(perm_string text, vector&nums) +: name_(text), number_(nums) { } @@ -53,24 +57,50 @@ hname_t& hname_t::operator = (const hname_t&that) return *this; } -bool operator < (const hname_t&l, const hname_t&r) +bool hname_t::operator < (const hname_t&r) const { - int cmp = strcmp(l.peek_name(), r.peek_name()); + int cmp = strcmp(name_, r.name_); if (cmp < 0) return true; if (cmp > 0) return false; - if (l.has_number() && r.has_number()) - return l.peek_number() < r.peek_number(); - else - return false; + + // The text parts are equal, so compare then number + // parts. Finish as soon as we find one to be less or more + // than the other. + size_t idx = 0; + while (number_.size() > idx || r.number_.size() > idx) { + + // Ran out of l numbers, so less. + if (number_.size() <= idx) + return true; + + // Ran out of r numbers, so greater. + if (r.number_.size() <= idx) + return false; + + if (number_[idx] < r.number_[idx]) + return true; + + if (number_[idx] > r.number_[idx]) + return false; + + idx += 1; + } + + // Fall-through means that we are equal, including all the + // number parts, so not less. + return false; } -bool operator == (const hname_t&l, const hname_t&r) +bool hname_t::operator == (const hname_t&r) const { - if (l.peek_name() == r.peek_name()) { - if (l.has_number() && r.has_number()) - return l.peek_number() == r.peek_number(); - else - return true; + if (name_ == r.name_) { + if (number_.size() != r.number_.size()) + return false; + + for (size_t idx = 0 ; idx < number_.size() ; idx += 1) + if (number_[idx] != r.number_[idx]) return false; + + return true; } return false; @@ -84,8 +114,8 @@ ostream& operator<< (ostream&out, const hname_t&that) } out << that.peek_name(); - if (that.has_number()) - out << "[" << that.peek_number() << "]"; + for (size_t idx = 0 ; idx < that.number_.size() ; idx += 1) + out << "[" << that.number_[idx] << "]"; return out; } diff --git a/HName.h b/HName.h index ce561f8f0..6d1f3ccb7 100644 --- a/HName.h +++ b/HName.h @@ -1,7 +1,7 @@ #ifndef __HName_H #define __HName_H /* - * Copyright (c) 2001-2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -21,13 +21,10 @@ # include # include +# include # include "StringHeap.h" -# include -#ifdef __GNUC__ -#if __GNUC__ > 2 -using namespace std; -#endif -#endif + +# include /* * This class represents a component of a Verilog hierarchical name. A @@ -39,27 +36,33 @@ using namespace std; class hname_t { + friend ostream& operator<< (ostream&out, const hname_t&that); + public: hname_t (); explicit hname_t (perm_string text); explicit hname_t (perm_string text, int num); + explicit hname_t (perm_string text, std::vector&nums); hname_t (const hname_t&that); ~hname_t(); hname_t& operator= (const hname_t&); + bool operator == (const hname_t&that) const; + bool operator < (const hname_t&that) const; + // Return the string part of the hname_t. perm_string peek_name(void) const; - bool has_number() const; - int peek_number() const; + size_t has_numbers() const; + int peek_number(size_t idx) const; private: perm_string name_; // If the number is anything other than INT_MIN, then this is // the numeric part of the name. Otherwise, it is not part of // the name at all. - int number_; + std::vector number_; private: // not implemented }; @@ -73,18 +76,17 @@ inline perm_string hname_t::peek_name(void) const return name_; } -inline int hname_t::peek_number() const +inline int hname_t::peek_number(size_t idx) const { - return number_; + assert(number_.size() > idx); + return number_[idx]; } -inline bool hname_t::has_number() const +inline size_t hname_t::has_numbers() const { - return number_ != INT_MIN; + return number_.size(); } -extern bool operator < (const hname_t&, const hname_t&); -extern bool operator == (const hname_t&, const hname_t&); extern ostream& operator<< (ostream&, const hname_t&); inline bool operator != (const hname_t&l, const hname_t&r) diff --git a/design_dump.cc b/design_dump.cc index 52627302f..9a8a256d7 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -200,9 +200,7 @@ static inline void dump_scope_path(ostream&o, const NetScope*scope) o << "."; } const hname_t name = scope->fullname(); - o << name.peek_name(); - if (name.has_number()) - o << "[" << name.peek_number() << "]"; + o << name; } ostream& operator <<(ostream&o, struct __ScopePathManip marg) diff --git a/elab_scope.cc b/elab_scope.cc index 1b78ac894..2d70d938b 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -883,8 +883,10 @@ bool PGenerate::generate_scope_loop_(Design*des, NetScope*container) // Check the generate block name. - // A generate "loop" can not have the same name as another scope object. - const NetScope *child = container->child(hname_t(scope_name)); + // A generate "loop" can not have the same name as another + // scope object. Find any scope with this name, not just an + // exact match scope. + const NetScope *child = container->child_byname(scope_name); if (child) { cerr << get_fileline() << ": error: generate \"loop\" and "; child->print_type(cerr); diff --git a/elab_sig.cc b/elab_sig.cc index 4b8b0ec36..2d6fdcf9b 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -949,7 +949,7 @@ NetNet* PWire::elaborate_sig(Design*des, NetScope*scope) const des->errors += error_cnt_; // A signal can not have the same name as a scope object. - const NetScope *child = scope->child(hname_t(name_)); + const NetScope *child = scope->child_byname(name_); if (child) { cerr << get_fileline() << ": error: signal and "; child->print_type(cerr); diff --git a/net_scope.cc b/net_scope.cc index e72a31133..ba9782a56 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -668,6 +668,21 @@ const NetScope* NetScope::child(const hname_t&name) const return cur->second; } +const NetScope* NetScope::child_byname(perm_string name) const +{ + hname_t hname (name); + map::const_iterator cur = children_.lower_bound(hname); + + if (cur == children_.end()) + return 0; + + if (cur->first.peek_name() == name) + return cur->second; + + return 0; +} + + perm_string NetScope::local_symbol() { ostringstream res; diff --git a/netlist.h b/netlist.h index 58d2e5d7f..4f49bf9b2 100644 --- a/netlist.h +++ b/netlist.h @@ -966,6 +966,12 @@ class NetScope : public Definitions, public Attrib { const NetScope* parent() const { return up_; } const NetScope* child(const hname_t&name) const; + // Look for a child scope by name. This ignores the number + // part of the child scope name, so there may be multiple + // matches. Only return one. This function is only really + // useful for some elaboration error checking. + const NetScope* child_byname(perm_string name) const; + // Nested modules have slightly different scope search rules. inline bool nested_module() const { return nested_module_; } // Program blocks have elaboration constraints. diff --git a/netmisc.cc b/netmisc.cc index 4271720a7..ec08cffdf 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -950,50 +950,48 @@ hname_t eval_path_component(Design*des, NetScope*scope, if (comp.index.empty()) return hname_t(comp.name); - // The parser will assure that path components will have only - // one index. For example, foo[N] is one index, foo[n][m] is two. - assert(comp.index.size() == 1); + vector index_values; - const index_component_t&index = comp.index.front(); + for (list::const_iterator cur = comp.index.begin() + ; cur != comp.index.end() ; ++cur) { + const index_component_t&index = *cur; - if (index.sel != index_component_t::SEL_BIT) { - cerr << index.msb->get_fileline() << ": error: " - << "Part select is not valid for this kind of object." << endl; - des->errors += 1; - return hname_t(comp.name, 0); - } + if (index.sel != index_component_t::SEL_BIT) { + cerr << index.msb->get_fileline() << ": error: " + << "Part select is not valid for this kind of object." << endl; + des->errors += 1; + return hname_t(comp.name, 0); + } - // The parser will assure that path components will have only - // bit select index expressions. For example, "foo[n]" is OK, - // but "foo[n:m]" is not. - assert(index.sel == index_component_t::SEL_BIT); + // The parser will assure that path components will have only + // bit select index expressions. For example, "foo[n]" is OK, + // but "foo[n:m]" is not. + assert(index.sel == index_component_t::SEL_BIT); - // Evaluate the bit select to get a number. - NetExpr*tmp = elab_and_eval(des, scope, index.msb, -1); - ivl_assert(*index.msb, tmp); - - // Now we should have a constant value for the bit select - // expression, and we can use it to make the final hname_t - // value, for example "foo[5]". - if (NetEConst*ctmp = dynamic_cast(tmp)) { - hname_t res(comp.name, ctmp->value().as_long()); - delete ctmp; - return res; - } + // Evaluate the bit select to get a number. + NetExpr*tmp = elab_and_eval(des, scope, index.msb, -1); + ivl_assert(*index.msb, tmp); + if (NetEConst*ctmp = dynamic_cast(tmp)) { + index_values.push_back(ctmp->value().as_long()); + delete ctmp; + continue; + } #if 1 - // Darn, the expression doesn't evaluate to a constant. That's - // an error to be reported. And make up a fake index value to - // return to the caller. - cerr << index.msb->get_fileline() << ": error: " - << "Scope index expression is not constant: " - << *index.msb << endl; - des->errors += 1; + // Darn, the expression doesn't evaluate to a constant. That's + // an error to be reported. And make up a fake index value to + // return to the caller. + cerr << index.msb->get_fileline() << ": error: " + << "Scope index expression is not constant: " + << *index.msb << endl; + des->errors += 1; #endif - error_flag = true; + error_flag = true; - delete tmp; - return hname_t (comp.name, 0); + delete tmp; + } + + return hname_t(comp.name, index_values); } std::list eval_scope_path(Design*des, NetScope*scope, diff --git a/t-dll.cc b/t-dll.cc index d28d44c48..a068bb59b 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -160,12 +160,21 @@ inline static const char *basename(ivl_scope_t scope, const char *inst) static perm_string make_scope_name(const hname_t&name) { - if (! name.has_number()) + if (! name.has_numbers()) return name.peek_name(); char buf[1024]; - snprintf(buf, sizeof buf, "%s[%d]", - name.peek_name().str(), name.peek_number()); + snprintf(buf, sizeof buf, "%s", name.peek_name().str()); + + char*cp = buf + strlen(buf); + size_t ncp = sizeof buf - (cp-buf); + + for (size_t idx = 0 ; idx < name.has_numbers() ; idx += 1) { + int len = snprintf(cp, ncp, "[%d]", name.peek_number(idx)); + cp += len; + ncp -= len; + } + return lex_strings.make(buf); } From df4889ba3d0e401c755ee209a2a91d6bb7008174 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 30 Mar 2014 17:37:27 -0700 Subject: [PATCH 014/245] Handle SEL_IDX_UP is some situations. --- elab_expr.cc | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/elab_expr.cc b/elab_expr.cc index 179ec1bce..02cf08fb8 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -1790,6 +1790,11 @@ bool calculate_part(const LineInfo*li, Design*des, NetScope*scope, } return true; + case index_component_t::SEL_IDX_UP: + wid = lsb; + off = msb; + break; + default: ivl_assert(*li, 0); break; From 40b36337e2c89a4bf6b858cc2cd3fa7ce93da1db Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sat, 5 Apr 2014 20:57:22 -0700 Subject: [PATCH 015/245] Fix some bugs with packed array dimensions. The netparray_t::slice_dimensions bug was the most insidious and caused all manner of confusion. Also fix some other packed array and unpacked array (and mixed) indexing calculations. --- elab_expr.cc | 52 +++++++++++++++++++++++++++++++++++++++++++++++++--- elab_net.cc | 17 +++++++++++++++++ netlist.cc | 3 +++ netparray.cc | 2 +- nettypes.cc | 24 ++++++++++++++++++++---- 5 files changed, 90 insertions(+), 8 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 02cf08fb8..481430024 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2832,7 +2832,10 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) const index_component_t&index_tail = name_tail.index.back(); ivl_assert(*this, index_tail.msb); } - use_width = 1; + // If we have a net in hand, then we can predict what + // the slice width will be. If not, then just guess. + if (net == 0) + use_width = 1; break; default: ivl_assert(*this, 0); @@ -2864,15 +2867,35 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) // The width of a signal expression is the width of the signal. if (net != 0) { + size_t use_depth = name_tail.index.size(); + // Account for unpacked dimensions by assuming that the + // unpacked dimensions are consumed first, so subtract + // the unpacked dimensions from the dimension depth + // useable for making the slice. + if (use_depth >= net->unpacked_dimensions()) { + use_depth -= net->unpacked_dimensions(); + + } else { + // In this case, we have a slice of an unpacked + // array. This likely handled as an array instead + // of a slice. Hmm... + use_depth = 0; + } + expr_type_ = net->data_type(); - expr_width_ = net->vector_width(); + expr_width_ = net->slice_width(use_depth); min_width_ = expr_width_; signed_flag_ = net->get_signed(); if (debug_elaborate) { cerr << get_fileline() << ": PEIdent::test_width: " << net->name() << " is a net, " << "type=" << expr_type_ - << ", width=" << expr_width_ << endl; + << ", width=" << expr_width_ + << ", signed_=" << (signed_flag_?"true":"false") + << ", use_depth=" << use_depth + << ", packed_dimensions=" << net->packed_dimensions() + << ", unpacked_dimensions=" << net->unpacked_dimensions() + << endl; } return expr_width_; } @@ -3228,6 +3251,13 @@ NetExpr* PEIdent::elaborate_expr(Design*des, NetScope*scope, if (!tmp) return 0; + if (debug_elaborate) { + cerr << get_fileline() << ": PEIdent::elaborate_expr: " + << "Expression as net. expr_wid=" << expr_wid + << ", tmp->expr_width()=" << tmp->expr_width() + << ", tmp=" << *tmp << endl; + } + tmp = pad_to_width(tmp, expr_wid, *this); tmp->cast_signed(signed_flag_); @@ -4445,6 +4475,15 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope, // making a mux part in the netlist. if (NetEConst*msc = dynamic_cast (mux)) { + if (debug_elaborate) { + cerr << get_fileline() << ": PEIdent::elaborate_expr_net_bit_: " + << "mux is constant=" << *msc + << ", packed_dims()=" << net->sig()->packed_dims() + << ", packed_dims().size()=" << net->sig()->packed_dims().size() + << ", prefix_indices.size()=" << prefix_indices.size() + << endl; + } + // Special case: The bit select expression is constant // x/z. The result of the expression is 1'bx. if (! msc->value().is_defined()) { @@ -4462,6 +4501,7 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope, << endl; } + // FIXME: Should I be using slice_width() here? NetEConst*tmp = make_const_x(1); tmp->set_line(*this); delete mux; @@ -4553,6 +4593,12 @@ NetExpr* PEIdent::elaborate_expr_net_bit_(Design*des, NetScope*scope, if (net->vector_width() == 1) return net; + if (debug_elaborate) { + cerr << get_fileline() << ": PEIdent::elaborate_expr_net_bit_: " + << "Make bit select idx=" << idx + << endl; + } + // Make an expression out of the index NetEConst*idx_c = new NetEConst(verinum(idx)); idx_c->set_line(*net); diff --git a/elab_net.cc b/elab_net.cc index 2495b9d6c..cbaf15202 100644 --- a/elab_net.cc +++ b/elab_net.cc @@ -708,6 +708,16 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, } } else if (!path_tail.index.empty()) { + if (debug_elaborate) { + cerr << get_fileline() << ": PEIdent::elaborate_lnet_common_: " + << "path_tail.index.size()=" << path_tail.index.size() + << endl; + } + + // There are index expressions on the name, so this is a + // bit/slice select of the name. Calculate a canonical + // part select. + if (sig->get_scalar()) { cerr << get_fileline() << ": error: " << "can not select part of "; @@ -739,6 +749,13 @@ NetNet* PEIdent::elaborate_lnet_common_(Design*des, NetScope*scope, if (sig->type() == NetNet::UNRESOLVED_WIRE && sig->test_and_set_part_driver(midx,lidx, widx_flag? widx : 0)) { cerr << get_fileline() << ": error: Unresolved net/uwire " << sig->name() << " cannot have multiple drivers." << endl; + if (debug_elaborate) { + cerr << get_fileline() << ": : Overlap in " + << "[" << midx << ":" << lidx << "] (canonical)" + << ", widx=" << (widx_flag? widx : 0) + << ", vector width=" << sig->vector_width() + << endl; + } des->errors += 1; return 0; } diff --git a/netlist.cc b/netlist.cc index e43c52046..4d184dc51 100644 --- a/netlist.cc +++ b/netlist.cc @@ -762,6 +762,9 @@ const netclass_t* NetNet::class_type(void) const * In this case, slice_width(2) == 1 (slice_width(N) where N is the * number of dimensions will always be 1.) and represents * $bits(foo[a][b]). Then, slice_width(1)==4 ($bits(foo[a]) and slice_width(0)==24. + * + * NOTE: The caller should already have accounted for unpacked + * dimensions. The "depth" is only for the packed dimensions. */ unsigned long NetNet::slice_width(size_t depth) const { diff --git a/netparray.cc b/netparray.cc index d8779a92d..326b549fc 100644 --- a/netparray.cc +++ b/netparray.cc @@ -49,7 +49,7 @@ vector netparray_t::slice_dimensions() const vector res (packed_dims_.size() + elem_dims.size()); for (size_t idx = 0 ; idx < packed_dims_.size() ; idx += 1) - res[idx] = packed_dims_[0]; + res[idx] = packed_dims_[idx]; for (size_t idx = 0 ; idx < elem_dims.size() ; idx += 1) res[idx+packed_dims_.size()] = elem_dims[idx]; diff --git a/nettypes.cc b/nettypes.cc index 1a36b177a..4a01d4d8a 100644 --- a/nettypes.cc +++ b/nettypes.cc @@ -18,6 +18,7 @@ */ # include "nettypes.h" +# include # include using namespace std; @@ -101,6 +102,12 @@ bool prefix_to_slice(const std::vector&dims, { assert(prefix.size() < dims.size()); + // Figure out the width of the slice, given the number of + // prefix numbers there are. We don't need to look at the + // actual values yet, but we do need to know how many there + // are compared to the actual dimensions of the target. So do + // this by multiplying the widths of the dims that are NOT + // accounted for by the prefix or sb indices. size_t acc_wid = 1; vector::const_iterator pcur = dims.end(); for (size_t idx = prefix.size()+1 ; idx < dims.size() ; idx += 1) { @@ -108,8 +115,12 @@ bool prefix_to_slice(const std::vector&dims, acc_wid *= pcur->width(); } - lwid = acc_wid; + lwid = acc_wid; // lwid is now the final slice width. + // pcur is pointing to the dimension AFTER the dimension that + // we have an index for, so step back one, then this will be + // used with the sb index. Start accumulating in the acc_off + // the offset into the n-dimensional vector. -- pcur; if (sb < pcur->get_msb() && sb < pcur->get_lsb()) return false; @@ -122,16 +133,18 @@ bool prefix_to_slice(const std::vector&dims, else acc_off += (pcur->get_lsb() - sb) * acc_wid; + // If there are no more prefix items, we are done. if (prefix.empty()) { loff = acc_off; return true; } - lwid *= pcur->width(); - + // 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 offset (acc_off). list::const_iterator icur = prefix.end(); do { - -- pcur; -- icur; acc_wid *= pcur->width(); if (pcur->get_msb() >= pcur->get_lsb()) @@ -139,8 +152,11 @@ bool prefix_to_slice(const std::vector&dims, else acc_off += (pcur->get_lsb() - *icur) * acc_wid; + -- pcur; + } while (icur != prefix.begin()); + // Got our final offset. loff = acc_off; return true; From f752007e9c0541fd0fab64fdc65b91fd0c3fdd3c Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 6 Apr 2014 15:54:05 -0700 Subject: [PATCH 016/245] Add some minor VPI/ACC fixes and updates These were submitted. --- libveriuser/a_configure.c | 6 +++++- libveriuser/a_fetch_type_str.c | 8 ++++++++ libveriuser/a_vcl.c | 1 + vpi_user.h | 2 ++ vvp/vpi_signal.cc | 5 +++++ 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/libveriuser/a_configure.c b/libveriuser/a_configure.c index c6d242e5d..cd79ca1e5 100644 --- a/libveriuser/a_configure.c +++ b/libveriuser/a_configure.c @@ -69,9 +69,13 @@ int acc_configure(PLI_INT32 config_param, const char*value) fprintf(pli_trace, "acc_configure(config=%d, %s)\n", (int)config_param, value); } - +#if 0 vpi_printf("XXXX acc_configure(%d, %s)\n", (int)config_param, value); +#else + /* Parameter is not necessarily a string. */ + vpi_printf("XXXX acc_configure(%d, ...)\n", (int)config_param); +#endif rc = 0; break; } diff --git a/libveriuser/a_fetch_type_str.c b/libveriuser/a_fetch_type_str.c index e8cefae4d..5250f1384 100644 --- a/libveriuser/a_fetch_type_str.c +++ b/libveriuser/a_fetch_type_str.c @@ -40,3 +40,11 @@ const char* acc_fetch_type_str(PLI_INT32 type) vpi_printf("acc_fetch_type_str: type %d is what accType?\n", (int)type); return "acc_fetch_type_str(unknown)"; } + +/* + * FIXME: What does this do? How should it be declared in acc_user.h? + */ +PLI_INT32 acc_fetch_paramtype(PLI_INT32 type) +{ + return 0; +} diff --git a/libveriuser/a_vcl.c b/libveriuser/a_vcl.c index e4f4d7725..e7bec8b93 100644 --- a/libveriuser/a_vcl.c +++ b/libveriuser/a_vcl.c @@ -162,6 +162,7 @@ void acc_vcl_add(handle obj, PLI_INT32(*consumer)(p_vc_record), switch (vpi_get(vpiType, obj)) { case vpiNet: + case vpiReg: cur = malloc(sizeof (struct vcl_record)); cur->obj = obj; cur->consumer = consumer; diff --git a/vpi_user.h b/vpi_user.h index 4b17ae2f0..6b80c31c7 100644 --- a/vpi_user.h +++ b/vpi_user.h @@ -334,6 +334,8 @@ typedef struct t_vpi_delay { #define vpiTimePrecision 12 #define vpiDefFile 15 #define vpiDefLineNo 16 +#define vpiScalar 17 +#define vpiVector 18 #define vpiDirection 20 /* direction of port: */ # define vpiInput 1 diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index 30fc9f11d..edd39adf9 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -567,6 +567,11 @@ static int signal_get(int code, vpiHandle ref) case vpiRightRange: return rfp->lsb; + case vpiScalar: + return (rfp->msb == 0 && rfp->lsb == 0); + case vpiVector: + return (rfp->msb != rfp->lsb); + case vpiAutomatic: return (int) vpip_scope(rfp)->is_automatic; From e6b394f825510fb35224a8135f9badacf70d8aa1 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Mon, 7 Apr 2014 09:24:30 -0700 Subject: [PATCH 017/245] Fix declaration of acc_fetch_paramtype --- acc_user.h | 1 + libveriuser/a_fetch_type_str.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/acc_user.h b/acc_user.h index 48eac2e69..078cfe65b 100644 --- a/acc_user.h +++ b/acc_user.h @@ -228,6 +228,7 @@ extern PLI_INT32 acc_fetch_size(handle obj); extern PLI_INT32 acc_fetch_type(handle obj); extern PLI_INT32 acc_fetch_fulltype(handle obj); +extern PLI_INT32 acc_fetch_paramtype(handle obj); extern PLI_INT32 acc_fetch_range(handle object, int *msb, int *lsb); extern const char* acc_fetch_type_str(PLI_INT32 type); diff --git a/libveriuser/a_fetch_type_str.c b/libveriuser/a_fetch_type_str.c index 5250f1384..d74a2714e 100644 --- a/libveriuser/a_fetch_type_str.c +++ b/libveriuser/a_fetch_type_str.c @@ -44,7 +44,7 @@ const char* acc_fetch_type_str(PLI_INT32 type) /* * FIXME: What does this do? How should it be declared in acc_user.h? */ -PLI_INT32 acc_fetch_paramtype(PLI_INT32 type) +PLI_INT32 acc_fetch_paramtype(handle obj) { return 0; } From 3a77537ed8eeb0e2eca3b6151b5c96dc209dbcd7 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Tue, 8 Apr 2014 11:11:49 -0700 Subject: [PATCH 018/245] Handle scaled time is acc functions for non-scope objects The tf_igetlongtime function may pass in any kind of object, so the scale() function may need to convert an object handle to the handle for the objects parent scope. --- libveriuser/getsimtime.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/libveriuser/getsimtime.c b/libveriuser/getsimtime.c index 646cbf491..d833cf38b 100644 --- a/libveriuser/getsimtime.c +++ b/libveriuser/getsimtime.c @@ -43,10 +43,31 @@ scale(int high, int low, void*obj) { vpiHandle hand = vpi_handle(vpiScope, vpi_handle(vpiSysTfCall,0)); ivl_u64_t scaled; + vpiHandle use_obj = obj; + if (use_obj == 0) { + /* If object is not passed in, then use current scope. */ + use_obj = hand; + } else { + /* If object IS passed in, make sure it is a scope. If + it is not, then get the scope of the object. We need + a scope handle to go on. */ + switch (vpi_get(vpiType,use_obj)) { + case vpiModule: + case vpiGenScope: + case vpiFunction: + case vpiTask: + case vpiNamedBegin: + case vpiNamedFork: + break; + default: + use_obj = vpi_handle(vpiScope, use_obj); + break; + } + } + scaled = high; scaled = (scaled << 32) | low; - scaled /= pow10u(vpi_get(vpiTimeUnit,obj ? (vpiHandle)obj : hand) - - vpi_get(vpiTimePrecision,0)); + scaled /= pow10u(vpi_get(vpiTimeUnit, use_obj) - vpi_get(vpiTimePrecision,0)); return scaled; } From e336eca00f1f2a8778e7ad9501aff321cc4d31ec Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 10 Apr 2014 14:17:50 -0700 Subject: [PATCH 019/245] vlog95: Report that array ports are not supported. --- tgt-vlog95/scope.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tgt-vlog95/scope.c b/tgt-vlog95/scope.c index 59657e7b2..43640d497 100644 --- a/tgt-vlog95/scope.c +++ b/tgt-vlog95/scope.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2013 Cary R. (cygcary@yahoo.com) + * Copyright (C) 2010-2014 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 @@ -414,7 +414,14 @@ static ivl_signal_t get_port_from_nexus(ivl_scope_t scope, ivl_nexus_t nex, static void emit_sig_type(ivl_signal_t sig) { ivl_signal_type_t type = ivl_signal_type(sig); - assert(ivl_signal_dimensions(sig) == 0); + if (ivl_signal_dimensions(sig) != 0) { + fprintf(stderr, "%s:%u: vlog95 error: Array ports (%s) are not " + "supported.\n", + ivl_signal_file(sig), + ivl_signal_lineno(sig), + ivl_signal_basename(sig)); + vlog_errors += 1; + } /* Check to see if we have a variable (reg) or a net. */ if (type == IVL_SIT_REG) { if (ivl_signal_integer(sig)) { From a5423ce5ce62969d3ff20f9dd21d888a59e5585a Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 10 Apr 2014 14:33:12 -0700 Subject: [PATCH 020/245] Update FST and related files to match the latest from GTKWave --- vpi/Makefile.in | 2 +- vpi/cppcheck.sup | 51 +-- vpi/fastlz.c | 2 +- vpi/fstapi.c | 996 +++++++++++++++++++++++++++++++++++------------ vpi/fstapi.h | 14 +- vpi/lz4.c | 877 +++++++++++++++++++++++++++++++++++++++++ vpi/lz4.h | 252 ++++++++++++ 7 files changed, 1907 insertions(+), 287 deletions(-) create mode 100644 vpi/lz4.c create mode 100644 vpi/lz4.h diff --git a/vpi/Makefile.in b/vpi/Makefile.in index 278be1f43..a6b1c1416 100644 --- a/vpi/Makefile.in +++ b/vpi/Makefile.in @@ -64,7 +64,7 @@ ifeq (@HAVE_LIBBZ2@,yes) O += sys_lxt.o lxt_write.o endif O += sys_lxt2.o lxt2_write.o -O += sys_fst.o fstapi.o fastlz.o +O += sys_fst.o fstapi.o fastlz.o lz4.o endif # Object files for v2005_math.vpi diff --git a/vpi/cppcheck.sup b/vpi/cppcheck.sup index 276a3eeac..833f1b7dc 100644 --- a/vpi/cppcheck.sup +++ b/vpi/cppcheck.sup @@ -3,30 +3,33 @@ // problems will not be fixed. // fstapi.c from GTKWave -obsoleteFunctionsasctime:fstapi.c:740 -obsoleteFunctionsalloca:fstapi.c:1994 -unreadVariable:fstapi.c:1388 -variableScope:fstapi.c:842 -variableScope:fstapi.c:1798 -variableScope:fstapi.c:2222 -variableScope:fstapi.c:2414 -variableScope:fstapi.c:2573 -variableScope:fstapi.c:2574 -variableScope:fstapi.c:3193 -variableScope:fstapi.c:3218 -variableScope:fstapi.c:3341 -variableScope:fstapi.c:3777 -variableScope:fstapi.c:3786 -variableScope:fstapi.c:4297 -variableScope:fstapi.c:4300 -variableScope:fstapi.c:4867 -variableScope:fstapi.c:4921 -variableScope:fstapi.c:5225 -variableScope:fstapi.c:5228 -variableScope:fstapi.c:5464 -variableScope:fstapi.c:5569 -variableScope:fstapi.c:5570 -variableScope:fstapi.c:5601 +obsoleteFunctionsasctime:fstapi.c:840 +obsoleteFunctionsalloca:fstapi.c:2225 +unreadVariable:fstapi.c:1569 +variableScope:fstapi.c:581 +variableScope:fstapi.c:1301 +variableScope:fstapi.c:1900 +variableScope:fstapi.c:2029 +variableScope:fstapi.c:2454 +variableScope:fstapi.c:2646 +variableScope:fstapi.c:2805 +variableScope:fstapi.c:2806 +variableScope:fstapi.c:3521 +variableScope:fstapi.c:3692 +variableScope:fstapi.c:4135 +variableScope:fstapi.c:4144 +variableScope:fstapi.c:4676 +variableScope:fstapi.c:4679 +variableScope:fstapi.c:5177 +variableScope:fstapi.c:5178 +variableScope:fstapi.c:5334 +variableScope:fstapi.c:5392 +variableScope:fstapi.c:5705 +variableScope:fstapi.c:5708 +variableScope:fstapi.c:5944 +variableScope:fstapi.c:6049 +variableScope:fstapi.c:6050 +variableScope:fstapi.c:6081 // lxt2_write.c from GTKWave obsoleteFunctionsalloca:lxt2_write.c:1813 diff --git a/vpi/fastlz.c b/vpi/fastlz.c index 8e14ecfc0..aa2f8bfda 100644 --- a/vpi/fastlz.c +++ b/vpi/fastlz.c @@ -215,7 +215,7 @@ static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1)) { distance = 1; - ip += 3; + /* ip += 3; */ /* scan-build, never used */ ref = anchor - 1 + 3; goto match; } diff --git a/vpi/fstapi.c b/vpi/fstapi.c index a2d00454b..7f1ee1cd7 100644 --- a/vpi/fstapi.c +++ b/vpi/fstapi.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Tony Bybell. + * Copyright (c) 2009-2014 Tony Bybell. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -20,10 +20,29 @@ * DEALINGS IN THE SOFTWARE. */ +/* + * possible disables: + * + * FST_DYNAMIC_ALIAS_DISABLE : dynamic aliases are not processed + * FST_DYNAMIC_ALIAS2_DISABLE : new encoding for dynamic aliases is not generated + * FST_WRITEX_DISABLE : fast write I/O routines are disabled + * FST_DISABLE_DUFFS_DEVICE : only if indirect branches are incredibly bad on host arch + * + * possible enables: + * + * FST_DEBUG : not for production use, only enable for development + * FST_REMOVE_DUPLICATE_VC : glitch removal (has writer performance impact) + * HAVE_LIBPTHREAD -> FST_WRITER_PARALLEL : enables inclusion of parallel writer code + * FST_DO_MISALIGNED_OPS (defined automatically for x86 and some others) : CPU architecture can handle misaligned loads/stores + * _WAVE_HAVE_JUDY : use Judy arrays instead of Jenkins (undefine if LGPL is not acceptable) + * + */ + #include #include "fstapi.h" #include "fastlz.h" +#include "lz4.h" #ifndef HAVE_LIBPTHREAD #undef FST_WRITER_PARALLEL @@ -69,13 +88,22 @@ void JenkinsFree(void *base_i, uint32_t hashmask); void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint32_t hashmask); #endif -#undef FST_DEBUG +#ifndef FST_WRITEX_DISABLE +#define FST_WRITEX_MAX (64 * 1024) +#else +#define fstWritex(a,b,c) fstFwrite((b), (c), 1, fv) +#endif + + +/* these defines have a large impact on writer speed when a model has a */ +/* huge number of symbols. as a default, use 128MB and increment when */ +/* every 1M signals are defined. */ #define FST_BREAK_SIZE (1UL << 27) #define FST_BREAK_ADD_SIZE (1UL << 22) #define FST_BREAK_SIZE_MAX (1UL << 31) -#define FST_ACTIVATE_HUGE_BREAK (2000000) -#define FST_ACTIVATE_HUGE_INC (2000000) +#define FST_ACTIVATE_HUGE_BREAK (1000000) +#define FST_ACTIVATE_HUGE_INC (1000000) #define FST_WRITER_STR "fstWriter" #define FST_ID_NAM_SIZ (512) @@ -86,6 +114,7 @@ void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint3 #define FST_HDR_FILETYPE_SIZE (1) #define FST_HDR_TIMEZERO_SIZE (8) #define FST_GZIO_LEN (32768) +#define FST_HDR_FOURPACK_DUO_SIZE (4*1024*1024) #if defined(__i386__) || defined(__x86_64__) || defined(_AIX) #define FST_DO_MISALIGNED_OPS @@ -93,6 +122,7 @@ void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint3 #if defined(__APPLE__) && defined(__MACH__) #define FST_MACOSX +#include #endif @@ -110,8 +140,14 @@ void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint3 #endif #endif - -/* the recoded "extra" values... */ +/* + * the recoded "extra" values... + * note that FST_RCV_Q is currently unused and is for future expansion. + * its intended use is as another level of escape such that any arbitrary + * value can be stored as the value: { time_delta, 8 bits, FST_RCV_Q }. + * this is currently not implemented so that the branchless decode is: + * uint32_t shcnt = 2 << (vli & 1); tdelta = vli >> shcnt; + */ #define FST_RCV_X (1 | (0<<1)) #define FST_RCV_Z (1 | (1<<1)) #define FST_RCV_H (1 | (2<<1)) @@ -119,6 +155,7 @@ void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint3 #define FST_RCV_W (1 | (4<<1)) #define FST_RCV_L (1 | (5<<1)) #define FST_RCV_D (1 | (6<<1)) +#define FST_RCV_Q (1 | (7<<1)) #define FST_RCV_STR "xzhuwl-?" /* 01234567 */ @@ -336,20 +373,27 @@ return(rc); static unsigned char *fstCopyVarint32ToLeft(unsigned char *pnt, uint32_t v) { -unsigned char buf[5]; -unsigned char *spnt = buf; -uint32_t nxt; +unsigned char *spnt; +uint32_t nxt = v; +int cnt = 1; +int i; -while((nxt = v>>7)) +while((nxt = nxt>>7)) /* determine len to avoid temp buffer copying to cut down on load-hit-store */ { - *(spnt++) = (v&0x7f) | 0x80; + cnt++; + } + +pnt -= cnt; +spnt = pnt; +cnt--; + +for(i=0;i>7; + *(spnt++) = ((unsigned char)v) | 0x80; v = nxt; } -*(spnt++) = (v&0x7f); - -do { - *(--pnt) = *(--spnt); - } while(spnt != buf); +*spnt = (unsigned char)v; return(pnt); } @@ -361,10 +405,10 @@ uint64_t nxt; while((nxt = v>>7)) { - *(pnt++) = (v&0x7f) | 0x80; + *(pnt++) = ((unsigned char)v) | 0x80; v = nxt; } -*(pnt++) = (v&0x7f); +*(pnt++) = (unsigned char)v; return(pnt); } @@ -492,10 +536,65 @@ int len; while((nxt = v>>7)) { - *(pnt++) = (v&0x7f) | 0x80; + *(pnt++) = ((unsigned char)v) | 0x80; v = nxt; } -*(pnt++) = (v&0x7f); +*(pnt++) = (unsigned char)v; + +len = pnt-buf; +fstFwrite(buf, len, 1, handle); +return(len); +} + + +/* signed integer read/write routines are currently unused */ +static int64_t fstGetSVarint64(unsigned char *mem, int *skiplen) +{ +unsigned char *mem_orig = mem; +int64_t rc = 0; +const int64_t one = 1; +const int siz = sizeof(int64_t) * 8; +int shift = 0; +unsigned char byt; + +do { + byt = *(mem++); + rc |= ((int64_t)(byt & 0x7f)) << shift; + shift += 7; + + } while(byt & 0x80); + +if((shift>= 7; + + if (((!v) && (!(byt & 0x40))) || ((v == -1) && (byt & 0x40))) + { + more = 0; + byt &= 0x7f; + } + + *(pnt++) = byt; + } while(more); len = pnt-buf; fstFwrite(buf, len, 1, handle); @@ -544,6 +643,7 @@ uint32_t maxvalpos; unsigned vc_emitted : 1; unsigned is_initial_time : 1; +unsigned fourpack : 1; unsigned fastpack : 1; int64_t timezero; @@ -638,10 +738,10 @@ pnt += 4; while((nxt = v>>7)) { - *(pnt++) = (v&0x7f) | 0x80; + *(pnt++) = ((unsigned char)v) | 0x80; v = nxt; } -*(pnt++) = (v&0x7f); +*(pnt++) = (unsigned char)v; memcpy(pnt, dbuf, siz); len = pnt-buf + siz; @@ -665,18 +765,18 @@ pnt += 4; while((nxt = v>>7)) { - *(pnt++) = (v&0x7f) | 0x80; + *(pnt++) = ((unsigned char)v) | 0x80; v = nxt; } -*(pnt++) = (v&0x7f); +*(pnt++) = (unsigned char)v; v = siz; while((nxt = v>>7)) { - *(pnt++) = (v&0x7f) | 0x80; + *(pnt++) = ((unsigned char)v) | 0x80; v = nxt; } -*(pnt++) = (v&0x7f); +*(pnt++) = (unsigned char)v; memcpy(pnt, dbuf, siz); @@ -827,14 +927,10 @@ xc->curval_mem = NULL; static void fstDetermineBreakSize(struct fstWriterContext *xc) { #if defined(__linux__) || defined(FST_MACOSX) +int was_set = 0; #ifdef __linux__ FILE *f = fopen("/proc/meminfo", "rb"); -#else -FILE *f = popen("system_profiler", "r"); -#endif - -int was_set = 0; if(f) { @@ -846,18 +942,10 @@ if(f) s = fgets(buf, 256, f); if(s && *s) { -#ifdef __linux__ if(!strncmp(s, "MemTotal:", 9)) { size_t v = atol(s+10); v *= 1024; /* convert to bytes */ -#else - if((s=strstr(s, "Memory:"))) - { - size_t v = atol(s+7); - v <<= 30; /* convert GB to bytes */ -#endif - v /= 8; /* chop down to 1/8 physical memory */ if(v > FST_BREAK_SIZE) { @@ -874,18 +962,45 @@ if(f) } } -#ifdef __linux__ fclose(f); -#else - pclose(f); -#endif } if(!was_set) -#endif { xc->fst_huge_break_size = FST_BREAK_SIZE; } +#else +int mib[2]; +int64_t v; +size_t length; + +mib[0] = CTL_HW; +mib[1] = HW_MEMSIZE; +length = sizeof(int64_t); +if(!sysctl(mib, 2, &v, &length, NULL, 0)) + { + v /= 8; + + if(v > FST_BREAK_SIZE) + { + if(v > FST_BREAK_SIZE_MAX) + { + v = FST_BREAK_SIZE_MAX; + } + + xc->fst_huge_break_size = v; + was_set = 1; + } + } + +if(!was_set) + { + xc->fst_huge_break_size = FST_BREAK_SIZE; + } +#endif +#else +xc->fst_huge_break_size = FST_BREAK_SIZE; +#endif xc->fst_break_size = xc->fst_orig_break_size = FST_BREAK_SIZE; xc->fst_break_add_size = xc->fst_orig_break_add_size = FST_BREAK_ADD_SIZE; @@ -969,8 +1084,8 @@ if(xc) int rc; destlen = xc->maxvalpos; - dmem = malloc(destlen); - rc = compress2(dmem, &destlen, xc->curval_mem, xc->maxvalpos, 9); + dmem = 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 */ xc->section_start = ftello(xc->handle); @@ -1054,7 +1169,7 @@ hashmask |= hashmask >> 16; #endif #endif -if((!xc)||(xc->vchg_siz <= 1)||(xc->already_in_flush)) return; +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; @@ -1064,7 +1179,7 @@ vchg_mem = xc->vchg_mem; f = xc->handle; fstWriterVarint(f, xc->maxhandle); /* emit current number of handles */ -fputc(xc->fastpack ? 'F' : 'Z', f); +fputc(xc->fourpack ? '4' : (xc->fastpack ? 'F' : 'Z'), f); fpos = 1; packmemlen = 1024; /* maintain a running "longest" allocation to */ @@ -1184,6 +1299,8 @@ for(i=0;imaxhandle;i++) if(is_binary) { unsigned char acc = 0; +#ifdef FST_DISABLE_DUFFS_DEVICE + /* old algorithm */ int shift = 7 - ((vm4ip[1]-1) & 7); for(idx=vm4ip[1]-1;idx>=0;idx--) { @@ -1196,6 +1313,24 @@ for(i=0;imaxhandle;i++) acc = 0; } } +#else + /* new algorithm */ + 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 1: acc |= (pnt[idx+0-8] & 1) << 7; + *(--scratchpnt) = acc; + idx -= 8; + } while(idx); + } +#endif scratchpnt = fstCopyVarint32ToLeft(scratchpnt, (time_delta << 1)); } @@ -1226,7 +1361,7 @@ for(i=0;imaxhandle;i++) else { free(packmem); - dmem = packmem = malloc(packmemlen = wrlen); + dmem = packmem = malloc(compressBound(packmemlen = wrlen)); } rc = compress2(dmem, &destlen, scratchpnt, wrlen, 4); @@ -1273,6 +1408,7 @@ for(i=0;imaxhandle;i++) } else { + /* this is extremely conservative: fastlz needs +5% for worst case, lz4 needs siz+(siz/255)+16 */ if(((wrlen * 2) + 2) <= packmemlen) { dmem = packmem; @@ -1283,7 +1419,7 @@ for(i=0;imaxhandle;i++) dmem = packmem = malloc(packmemlen = (wrlen * 2) + 2); } - rc = fastlz_compress(scratchpnt, wrlen, dmem); + rc = (xc->fourpack) ? LZ4_compress((char *)scratchpnt, (char *)dmem, wrlen) : fastlz_compress(scratchpnt, wrlen, dmem); if(rc < destlen) { #ifndef FST_DYNAMIC_ALIAS_DISABLE @@ -1366,42 +1502,89 @@ free(scratchpad); scratchpad = NULL; indxpos = ftello(f); xc->secnum++; -for(i=0;imaxhandle;i++) +#ifndef FST_DYNAMIC_ALIAS2_DISABLE +if(1) { - vm4ip = &(xc->valpos_mem[4*i]); + uint32_t prev_alias = 0; - if(vm4ip[2]) + for(i=0;imaxhandle;i++) { - if(zerocnt) - { - fpos += fstWriterVarint(f, (zerocnt << 1)); - zerocnt = 0; - } + vm4ip = &(xc->valpos_mem[4*i]); - if(vm4ip[2] & 0x80000000) + if(vm4ip[2]) { - fpos += fstWriterVarint(f, 0); /* signal */ - fpos += fstWriterVarint(f, (-(int32_t)vm4ip[2])); + if(zerocnt) + { + fpos += fstWriterVarint(f, (zerocnt << 1)); + zerocnt = 0; + } + + if(vm4ip[2] & 0x80000000) + { + if(vm4ip[2] != prev_alias) + { + fpos += fstWriterSVarint(f, (((int64_t)((int32_t)(prev_alias = vm4ip[2]))) << 1) | 1); + } + else + { + fpos += fstWriterSVarint(f, (0 << 1) | 1); + } + } + else + { + fpos += fstWriterSVarint(f, ((vm4ip[2] - prevpos) << 1) | 1); + prevpos = vm4ip[2]; + } + vm4ip[2] = 0; + vm4ip[3] = 0; /* clear out tchn idx */ } else { - fpos += fstWriterVarint(f, ((vm4ip[2] - prevpos) << 1) | 1); - prevpos = vm4ip[2]; + zerocnt++; } - vm4ip[2] = 0; - vm4ip[3] = 0; /* clear out tchn idx */ - } - else - { - zerocnt++; } } + else +#endif + { + for(i=0;imaxhandle;i++) + { + vm4ip = &(xc->valpos_mem[4*i]); + + if(vm4ip[2]) + { + if(zerocnt) + { + fpos += fstWriterVarint(f, (zerocnt << 1)); + zerocnt = 0; + } + + if(vm4ip[2] & 0x80000000) + { + fpos += fstWriterVarint(f, 0); /* signal, note that using a *signed* varint would be more efficient than this byte escape! */ + fpos += fstWriterVarint(f, (-(int32_t)vm4ip[2])); + } + else + { + fpos += fstWriterVarint(f, ((vm4ip[2] - prevpos) << 1) | 1); + prevpos = vm4ip[2]; + } + vm4ip[2] = 0; + vm4ip[3] = 0; /* clear out tchn idx */ + } + else + { + zerocnt++; + } + } + } + if(zerocnt) { /* fpos += */ fstWriterVarint(f, (zerocnt << 1)); /* scan-build */ } #ifdef FST_DEBUG -printf("value chains: %d\n", cnt); +fprintf(stderr, "value chains: %d\n", cnt); #endif xc->vchg_mem[0] = '!'; @@ -1419,7 +1602,7 @@ tmem = fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->tchn_han if(tmem) { unsigned long destlen = tlen; - unsigned char *dmem = malloc(destlen); + unsigned char *dmem = malloc(compressBound(destlen)); int rc = compress2(dmem, &destlen, tmem, tlen, 9); if((rc == Z_OK) && (destlen < tlen)) @@ -1454,7 +1637,11 @@ fflush(xc->handle); fstWriterFseeko(xc, xc->handle, xc->section_start-1, SEEK_SET); /* write out FST_BL_VCDATA over FST_BL_SKIP */ #ifndef FST_DYNAMIC_ALIAS_DISABLE +#ifndef FST_DYNAMIC_ALIAS2_DISABLE +fputc(FST_BL_VCDATA_DYN_ALIAS2, xc->handle); +#else fputc(FST_BL_VCDATA_DYN_ALIAS, xc->handle); +#endif #else fputc(FST_BL_VCDATA, xc->handle); #endif @@ -1472,7 +1659,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 - printf("<< dump file size limit reached, stopping dumping >>\n"); + fprintf(stderr, "<< dump file size limit reached, stopping dumping >>\n"); #endif } } @@ -1645,7 +1832,7 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) if(tmem) { unsigned long destlen = tlen; - unsigned char *dmem = malloc(destlen); + unsigned char *dmem = malloc(compressBound(destlen)); int rc = compress2(dmem, &destlen, tmem, tlen, 9); if((rc != Z_OK) || (destlen > tlen)) @@ -1708,10 +1895,10 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) if(xc->compress_hier) { - unsigned char *mem = malloc(FST_GZIO_LEN); off_t hl, eos; gzFile zhandle; int zfd; + int fourpack_duo = 0; #ifndef __MINGW32__ char *fnam = malloc(strlen(xc->filename) + 5 + 1); #endif @@ -1722,25 +1909,67 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) fstWriterUint64(xc->handle, 0); /* section length */ fstWriterUint64(xc->handle, xc->hier_file_len); /* uncompressed length */ - fflush(xc->handle); - zfd = dup(fileno(xc->handle)); - zhandle = gzdopen(zfd, "wb4"); - if(zhandle) + if(!xc->fourpack) { - fstWriterFseeko(xc, xc->hier_handle, 0, SEEK_SET); - for(hl = 0; hl < xc->hier_file_len; hl += FST_GZIO_LEN) + unsigned char *mem = malloc(FST_GZIO_LEN); + zfd = dup(fileno(xc->handle)); + fflush(xc->handle); + zhandle = gzdopen(zfd, "wb4"); + if(zhandle) { - unsigned len = ((xc->hier_file_len - hl) > FST_GZIO_LEN) ? FST_GZIO_LEN : (xc->hier_file_len - hl); - fstFread(mem, len, 1, xc->hier_handle); - gzwrite(zhandle, mem, len); + fstWriterFseeko(xc, xc->hier_handle, 0, SEEK_SET); + for(hl = 0; hl < xc->hier_file_len; hl += FST_GZIO_LEN) + { + unsigned len = ((xc->hier_file_len - hl) > FST_GZIO_LEN) ? FST_GZIO_LEN : (xc->hier_file_len - hl); + fstFread(mem, len, 1, xc->hier_handle); + gzwrite(zhandle, mem, len); + } + gzclose(zhandle); } - gzclose(zhandle); + else + { + close(zfd); + } + free(mem); } else { - close(zfd); + int lz4_maxlen; + unsigned char *mem; + unsigned char *hmem; + int packed_len; + + 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); + packed_len = LZ4_compress((char *)hmem, (char *)mem, xc->hier_file_len); + fstMunmap(hmem, xc->hier_file_len); + + fourpack_duo = (!xc->repack_on_close) && (xc->hier_file_len > FST_HDR_FOURPACK_DUO_SIZE); /* double pack when hierarchy is large */ + + if(fourpack_duo) /* double packing with LZ4 is faster than gzip */ + { + unsigned char *mem_duo; + int lz4_maxlen_duo; + int packed_len_duo; + + lz4_maxlen_duo = LZ4_compressBound(packed_len); + mem_duo = 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 */ + fstFwrite(mem_duo, packed_len_duo, 1, xc->handle); + free(mem_duo); + } + else + { + fstFwrite(mem, packed_len, 1, xc->handle); + } + + free(mem); } - free(mem); fstWriterFseeko(xc, xc->handle, 0, SEEK_END); eos = ftello(xc->handle); @@ -1749,7 +1978,9 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) fflush(xc->handle); fstWriterFseeko(xc, xc->handle, fixup_offs, SEEK_SET); - fputc(FST_BL_HIER, xc->handle); /* actual tag */ + fputc(xc->fourpack ? + ( fourpack_duo ? FST_BL_HIER_LZ4DUO : FST_BL_HIER_LZ4) : + FST_BL_HIER, xc->handle); /* actual tag now also == compression type */ fstWriterFseeko(xc, xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */ fflush(xc->handle); @@ -2129,12 +2360,13 @@ if(xc) } -void fstWriterSetPackType(void *ctx, int typ) +void fstWriterSetPackType(void *ctx, enum fstWriterPackType typ) { struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) { - xc->fastpack = (typ != 0); + xc->fastpack = (typ != FST_WR_PT_ZLIB); + xc->fourpack = (typ == FST_WR_PT_LZ4); } } @@ -2720,11 +2952,14 @@ unsigned char *temp_signal_value_buf; /* malloced for len in longest_signal_valu signed char timescale; unsigned char filetype; +unsigned use_vcd_extensions : 1; unsigned double_endian_match : 1; unsigned native_doubles_for_cb : 1; unsigned contains_geom_section : 1; -unsigned contains_hier_section : 1; /* valid for hier_pos */ -unsigned limit_range_valid : 1; /* valid for limit_range_start, limit_range_end */ +unsigned contains_hier_section : 1; /* valid for hier_pos */ +unsigned contains_hier_section_lz4duo : 1; /* valid for hier_pos (contains_hier_section_lz4 always also set) */ +unsigned contains_hier_section_lz4 : 1; /* valid for hier_pos */ +unsigned limit_range_valid : 1; /* valid for limit_range_start, limit_range_end */ char version[FST_HDR_SIM_VERSION_SIZE + 1]; char date[FST_HDR_DATE_SIZE + 1]; @@ -2773,6 +3008,14 @@ char str_scope_nam[FST_ID_NAM_SIZ+1]; char str_scope_comp[FST_ID_NAM_SIZ+1]; unsigned fseek_failed : 1; + +/* self-buffered I/O for writes */ + +#ifndef FST_WRITEX_DISABLE +int writex_pos; +int writex_fd; +unsigned char writex_buf[FST_WRITEX_MAX]; +#endif }; @@ -2793,6 +3036,41 @@ return(rc); } +#ifndef FST_WRITEX_DISABLE +static void fstWritex(struct fstReaderContext *xc, void *v, int len) +{ +unsigned char *s = (unsigned char *)v; + +if(len) + { + if(len < FST_WRITEX_MAX) + { + if(xc->writex_pos + len >= FST_WRITEX_MAX) + { + fstWritex(xc, NULL, 0); + } + + memcpy(xc->writex_buf + xc->writex_pos, s, len); + xc->writex_pos += len; + } + else + { + fstWritex(xc, NULL, 0); + if (write(xc->writex_fd, s, len)) { }; + } + } + else + { + if(xc->writex_pos) + { + if(write(xc->writex_fd, xc->writex_buf, xc->writex_pos)) { }; + xc->writex_pos = 0; + } + } +} +#endif + + /* * scope -> flat name handling */ @@ -3174,6 +3452,17 @@ if(xc) } +void fstReaderSetVcdExtensions(void *ctx, int enable) +{ +struct fstReaderContext *xc = (struct fstReaderContext *)ctx; + +if(xc) + { + xc->use_vcd_extensions = (enable != 0); + } +} + + void fstReaderIterBlocksSetNativeDoublesOnCallback(void *ctx, int enable) { struct fstReaderContext *xc = (struct fstReaderContext *)ctx; @@ -3186,54 +3475,34 @@ if(xc) /* * hierarchy processing */ -static char *fstVcdID(int value) +static void fstVcdID(char *buf, unsigned int value) { -static char buf[16]; char *pnt = buf; -int vmod; /* zero is illegal for a value...it is assumed they start at one */ -for(;;) +while (value) { - if((vmod = (value % 94))) - { - *(pnt++) = (char)(vmod + 32); - } - else - { - *(pnt++) = '~'; value -= 94; - } + value--; + *(pnt++) = (char)('!' + value % 94); value = value / 94; - if(!value) { break; } } *pnt = 0; -return(buf); } -static char *fstVcdIDForFwrite(int value, int *len) +static int fstVcdIDForFwrite(char *buf, unsigned int value) { -static char buf[16]; char *pnt = buf; -int vmod; /* zero is illegal for a value...it is assumed they start at one */ -for(;;) +while (value) { - if((vmod = (value % 94))) - { - *(pnt++) = (char)(vmod + 32); - } - else - { - *(pnt++) = '~'; value -= 94; - } + value--; + *(pnt++) = (char)('!' + value % 94); value = value / 94; - if(!value) { break; } } -*len = pnt-buf; -return(buf); +return(pnt - buf); } @@ -3247,21 +3516,50 @@ if(!xc->fh) char *fnam = malloc(strlen(xc->filename) + 6 + 16 + 32 + 1); unsigned char *mem = malloc(FST_GZIO_LEN); off_t hl, uclen; - gzFile zhandle; + off_t clen = 0; + gzFile zhandle = NULL; int zfd; + int htyp = FST_BL_SKIP; + + /* can't handle both set at once should never happen in a real file */ + if(!xc->contains_hier_section_lz4 && xc->contains_hier_section) + { + htyp = FST_BL_HIER; + } + else + if(xc->contains_hier_section_lz4 && !xc->contains_hier_section) + { + htyp = xc->contains_hier_section_lz4duo ? FST_BL_HIER_LZ4DUO : FST_BL_HIER_LZ4; + } sprintf(fnam, "%s.hier_%d_%p", xc->filename, getpid(), (void *)xc); fstReaderFseeko(xc, xc->f, xc->hier_pos, SEEK_SET); uclen = fstReaderUint64(xc->f); fflush(xc->f); - zfd = dup(fileno(xc->f)); - zhandle = gzdopen(zfd, "rb"); - if(!zhandle) + + if(htyp == FST_BL_HIER) { - close(zfd); - free(mem); - free(fnam); - return(0); + fstReaderFseeko(xc, xc->f, xc->hier_pos, SEEK_SET); + uclen = fstReaderUint64(xc->f); + fflush(xc->f); + + zfd = dup(fileno(xc->f)); + zhandle = gzdopen(zfd, "rb"); + if(!zhandle) + { + close(zfd); + free(mem); + free(fnam); + return(0); + } + } + else + if((htyp == FST_BL_HIER_LZ4) || (htyp == FST_BL_HIER_LZ4DUO)) + { + fstReaderFseeko(xc, xc->f, xc->hier_pos - 8, SEEK_SET); /* get section len */ + clen = fstReaderUint64(xc->f) - 16; + uclen = fstReaderUint64(xc->f); + fflush(xc->f); } #ifndef __MINGW32__ @@ -3282,26 +3580,79 @@ if(!xc->fh) if(fnam) unlink(fnam); #endif - for(hl = 0; hl < uclen; hl += FST_GZIO_LEN) + if(htyp == FST_BL_HIER) { - size_t len = ((uclen - hl) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - hl); - size_t gzreadlen = gzread(zhandle, mem, len); /* rc should equal len... */ - size_t fwlen; - - if(gzreadlen != len) + for(hl = 0; hl < uclen; hl += FST_GZIO_LEN) { - pass_status = 0; - break; + size_t len = ((uclen - hl) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - hl); + size_t gzreadlen = gzread(zhandle, mem, len); /* rc should equal len... */ + size_t fwlen; + + if(gzreadlen != len) + { + pass_status = 0; + break; + } + + fwlen = fstFwrite(mem, len, 1, xc->fh); + if(fwlen != 1) + { + pass_status = 0; + break; + } + } + gzclose(zhandle); + } + else + if(htyp == FST_BL_HIER_LZ4DUO) + { + unsigned char *lz4_cmem = malloc(clen); + unsigned char *lz4_ucmem = malloc(uclen); + unsigned char *lz4_ucmem2; + uint64_t uclen2; + int skiplen2 = 0; + + fstFread(lz4_cmem, clen, 1, xc->f); + + uclen2 = fstGetVarint64(lz4_cmem, &skiplen2); + lz4_ucmem2 = malloc(uclen2); + pass_status = (uclen2 == LZ4_decompress_safe_partial ((char *)lz4_cmem + skiplen2, (char *)lz4_ucmem2, clen - skiplen2, uclen2, uclen2)); + if(pass_status) + { + pass_status = (uclen == LZ4_decompress_safe_partial ((char *)lz4_ucmem2, (char *)lz4_ucmem, uclen2, uclen, uclen)); + + if(fstFwrite(lz4_ucmem, uclen, 1, xc->fh) != 1) + { + pass_status = 0; + } } - fwlen = fstFwrite(mem, len, 1, xc->fh); - if(fwlen != 1) + free(lz4_ucmem2); + free(lz4_ucmem); + free(lz4_cmem); + } + else + if(htyp == FST_BL_HIER_LZ4) + { + unsigned char *lz4_cmem = malloc(clen); + unsigned char *lz4_ucmem = 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)); + + if(fstFwrite(lz4_ucmem, uclen, 1, xc->fh) != 1) { pass_status = 0; - break; } - } - gzclose(zhandle); + + free(lz4_ucmem); + free(lz4_cmem); + } + else /* FST_BL_SKIP */ + { + pass_status = 0; + } + free(mem); free(fnam); @@ -3503,6 +3854,7 @@ uint32_t len, alias; int num_signal_dyn = 65536; int attrtype, subtype; uint64_t attrarg; +fstHandle maxhandle_scanbuild; if(!xc) return(0); @@ -3529,9 +3881,9 @@ if(fv) switch(xc->timescale) { - case 2: time_scale = 100; time_dimension[0] = ' '; break; + case 2: time_scale = 100; time_dimension[0] = 0; break; case 1: time_scale = 10; - case 0: time_dimension[0] = ' '; break; + case 0: time_dimension[0] = 0; break; case -1: time_scale = 100; time_dimension[0] = 'm'; break; case -2: time_scale = 10; @@ -3566,7 +3918,7 @@ if(fv) if(fv) fprintf(fv, "$timescale\n\t%d%ss\n$end\n", time_scale, time_dimension); } -xc->maxhandle = 0; +xc->maxhandle = 0; xc->num_alias = 0; free(xc->signal_lens); @@ -3613,7 +3965,7 @@ while(!feof(xc->fh)) attrarg = fstReaderVarint64(xc->fh); - if(fv) + if(fv && xc->use_vcd_extensions) { switch(attrtype) { @@ -3652,7 +4004,7 @@ while(!feof(xc->fh)) break; case FST_ST_GEN_ATTREND: - if(fv) fprintf(fv, "$attrend $end\n"); + if(fv && xc->use_vcd_extensions) fprintf(fv, "$attrend $end\n"); break; case FST_VT_VCD_EVENT: @@ -3720,8 +4072,10 @@ while(!feof(xc->fh)) } if(fv) { + char vcdid_buf[16]; uint32_t modlen = (vartype != FST_VT_VCD_PORT) ? len : ((len - 2) / 3); - fprintf(fv, "$var %s %"PRIu32" %s %s $end\n", vartypes[vartype], modlen, fstVcdID(xc->maxhandle+1), str); + fstVcdID(vcdid_buf, xc->maxhandle+1); + fprintf(fv, "$var %s %"PRIu32" %s %s $end\n", vartypes[vartype], modlen, vcdid_buf, str); } xc->maxhandle++; } @@ -3734,8 +4088,10 @@ while(!feof(xc->fh)) } if(fv) { + char vcdid_buf[16]; uint32_t modlen = (vartype != FST_VT_VCD_PORT) ? len : ((len - 2) / 3); - fprintf(fv, "$var %s %"PRIu32" %s %s $end\n", vartypes[vartype], modlen, fstVcdID(alias), str); + fstVcdID(vcdid_buf, alias); + fprintf(fv, "$var %s %"PRIu32" %s %s $end\n", vartypes[vartype], modlen, vcdid_buf, str); } xc->num_alias++; } @@ -3748,11 +4104,13 @@ while(!feof(xc->fh)) } if(fv) fprintf(fv, "$enddefinitions $end\n"); -xc->signal_lens = realloc(xc->signal_lens, xc->maxhandle*sizeof(uint32_t)); -xc->signal_typs = realloc(xc->signal_typs, xc->maxhandle*sizeof(unsigned char)); +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)); free(xc->process_mask); -xc->process_mask = calloc(1, (xc->maxhandle+7)/8); +xc->process_mask = calloc(1, (maxhandle_scanbuild+7)/8); free(xc->temp_signal_value_buf); xc->temp_signal_value_buf = malloc(xc->longest_signal_value_len + 1); @@ -3937,7 +4295,7 @@ if(gzread_pass_status) xc->timezero = fstReaderUint64(xc->f); } } - else if((sectype == FST_BL_VCDATA) || (sectype == FST_BL_VCDATA_DYN_ALIAS)) + else if((sectype == FST_BL_VCDATA) || (sectype == FST_BL_VCDATA_DYN_ALIAS) || (sectype == FST_BL_VCDATA_DYN_ALIAS2)) { if(hdr_incomplete) { @@ -4029,6 +4387,17 @@ if(gzread_pass_status) xc->contains_hier_section = 1; xc->hier_pos = ftello(xc->f); } + else if(sectype == FST_BL_HIER_LZ4DUO) + { + xc->contains_hier_section_lz4 = 1; + xc->contains_hier_section_lz4duo = 1; + xc->hier_pos = ftello(xc->f); + } + else if(sectype == FST_BL_HIER_LZ4) + { + xc->contains_hier_section_lz4 = 1; + xc->hier_pos = ftello(xc->f); + } else if(sectype == FST_BL_BLACKOUT) { uint32_t i; @@ -4107,7 +4476,7 @@ if((!nam)||(!(xc->f=fopen(nam, "rb")))) xc->filename = strdup(nam); rc = fstReaderInit(xc); - if((rc) && (xc->vc_section_count) && (xc->maxhandle) && ((xc->fh)||(xc->contains_hier_section))) + if((rc) && (xc->vc_section_count) && (xc->maxhandle) && ((xc->fh)||(xc->contains_hier_section||(xc->contains_hier_section_lz4)))) { /* more init */ xc->do_rewind = 1; @@ -4226,6 +4595,8 @@ uint32_t traversal_mem_offs; uint32_t *scatterptr, *headptr, *length_remaining; uint32_t cur_blackout = 0; int packtype; +unsigned char *mc_mem = NULL; +uint32_t mc_mem_len; /* corresponds to largest value encountered in chain_table_lengths[i] */ if(!xc) return(0); @@ -4233,7 +4604,15 @@ scatterptr = calloc(xc->maxhandle, sizeof(uint32_t)); headptr = calloc(xc->maxhandle, sizeof(uint32_t)); length_remaining = calloc(xc->maxhandle, sizeof(uint32_t)); -if(fv) { fprintf(fv, "$dumpvars\n"); } +if(fv) + { + fprintf(fv, "$dumpvars\n"); +#ifndef FST_WRITEX_DISABLE + fflush(fv); + setvbuf(fv, (char *) NULL, _IONBF, 0); /* even buffered IO is slow so disable it and use our own routines that don't need seeking */ + xc->writex_fd = fileno(fv); +#endif + } for(;;) { @@ -4248,13 +4627,13 @@ for(;;) if((sectype == EOF) || (sectype == FST_BL_SKIP)) { #ifdef FST_DEBUG - printf("<< EOF >>\n"); + fprintf(stderr, "<< EOF >>\n"); #endif break; } blkpos++; - if((sectype != FST_BL_VCDATA) && (sectype != FST_BL_VCDATA_DYN_ALIAS)) + if((sectype != FST_BL_VCDATA) && (sectype != FST_BL_VCDATA_DYN_ALIAS) && (sectype != FST_BL_VCDATA_DYN_ALIAS2)) { blkpos += seclen; continue; @@ -4287,9 +4666,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 - printf("sec: %d seclen: %d begtim: %d endtim: %d\n", + fprintf(stderr, "sec: %d seclen: %d begtim: %d endtim: %d\n", secnum, (int)seclen, (int)beg_tim, (int)end_tim); - printf("\tmem_required_for_traversal: %d\n", (int)mem_required_for_traversal); + fprintf(stderr, "\tmem_required_for_traversal: %d\n", (int)mem_required_for_traversal); #endif /* process time block */ { @@ -4307,7 +4686,7 @@ for(;;) tsec_clen = fstReaderUint64(xc->f); tsec_nitems = fstReaderUint64(xc->f); #ifdef FST_DEBUG - printf("\ttime section unc: %d, com: %d (%d items)\n", + fprintf(stderr, "\ttime 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 */ @@ -4350,7 +4729,7 @@ for(;;) tpnt += skiplen; } - tc_head = calloc(tsec_nitems, sizeof(uint32_t)); + tc_head = calloc(tsec_nitems /* scan-build */ ? tsec_nitems : 1, sizeof(uint32_t)); free(ucdata); } @@ -4369,12 +4748,20 @@ for(;;) if(fv) { - if(beg_tim) { fprintf(fv, "#%"PRIu64"\n", beg_tim); } + char wx_buf[32]; + int wx_len; + + if(beg_tim) + { + wx_len = sprintf(wx_buf, "#%"PRIu64"\n", beg_tim); + fstWritex(xc, wx_buf, wx_len); + } if((xc->num_blackouts)&&(cur_blackout != xc->num_blackouts)) { if(beg_tim == xc->blackout_times[cur_blackout]) { - fprintf(fv, "$dump%s $end\n", (xc->blackout_activity[cur_blackout++]) ? "on" : "off"); + wx_len = sprintf(wx_buf, "$dump%s $end\n", (xc->blackout_activity[cur_blackout++]) ? "on" : "off"); + fstWritex(xc, wx_buf, wx_len); } } } @@ -4424,11 +4811,12 @@ for(;;) { if(fv) { - int vcdid_len; - const char *vcd_id = fstVcdIDForFwrite(idx+1, &vcdid_len); - fputc(val, fv); - fstFwrite(vcd_id, vcdid_len, 1, fv); - fputc('\n', fv); + char vcd_id[16]; + + int vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); + vcd_id[0] = val; /* collapse 3 writes into one I/O call */ + vcd_id[vcdid_len + 1] = '\n'; + fstWritex(xc, vcd_id, vcdid_len + 2); } } } @@ -4451,13 +4839,16 @@ for(;;) { if(fv) { - int vcdid_len; - const char *vcd_id = fstVcdIDForFwrite(idx+1, &vcdid_len); - fputc((xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p', fv); - fstFwrite(mu+sig_offs, xc->signal_lens[idx], 1, fv); - fputc(' ', fv); - fstFwrite(vcd_id, vcdid_len, 1, fv); - fputc('\n', fv); + char vcd_id[16]; + int vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); + + vcd_id[0] = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p'; + fstWritex(xc, vcd_id, 1); + fstWritex(xc,mu+sig_offs, xc->signal_lens[idx]); + + vcd_id[0] = ' '; /* collapse 3 writes into one I/O call */ + vcd_id[vcdid_len + 1] = '\n'; + fstWritex(xc, vcd_id, vcdid_len + 2); } } } @@ -4511,6 +4902,10 @@ for(;;) { if(fv) { + char vcdid_buf[16]; + char wx_buf[64]; + int wx_len; + clone_d = (unsigned char *)&d; if(xc->double_endian_match) { @@ -4526,7 +4921,9 @@ for(;;) } } - fprintf(fv, "r%.16g %s\n", d, fstVcdID(idx+1)); + fstVcdID(vcdid_buf, idx+1); + wx_len = sprintf(wx_buf, "r%.16g %s\n", d, vcdid_buf); + fstWritex(xc, wx_buf, wx_len); } } } @@ -4548,9 +4945,9 @@ for(;;) packtype = fgetc(xc->f); #ifdef FST_DEBUG - printf("\tframe_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", + fprintf(stderr, "\tframe_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", (int)frame_uclen, (int)frame_clen, (int)frame_maxhandle); - printf("\tvc_maxhandle: %d, packtype: %c\n", (int)vc_maxhandle, packtype); + fprintf(stderr, "\tvc_maxhandle: %d, packtype: %c\n", (int)vc_maxhandle, packtype); #endif indx_pntr = blkpos + seclen - 24 -tsec_clen -8; @@ -4558,7 +4955,7 @@ for(;;) chain_clen = fstReaderUint64(xc->f); indx_pos = indx_pntr - chain_clen; #ifdef FST_DEBUG - printf("\tindx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen); + fprintf(stderr, "\tindx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen); #endif chain_cmem = malloc(chain_clen); if(!chain_cmem) goto block_err; @@ -4581,37 +4978,83 @@ for(;;) idx = 0; pval = 0; - do + if(sectype == FST_BL_VCDATA_DYN_ALIAS2) { - int skiplen; - uint64_t val = fstGetVarint32(pnt, &skiplen); - - if(!val) - { - pnt += skiplen; - val = fstGetVarint32(pnt, &skiplen); - chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */ - chain_table_lengths[idx] = -val; /* because during this loop iter would give stale data! */ - idx++; - } - else - if(val&1) - { - pval = chain_table[idx] = pval + (val >> 1); - if(idx) { chain_table_lengths[pidx] = pval - chain_table[pidx]; } - pidx = idx++; - } - else - { - int loopcnt = val >> 1; - for(i=0;i> 1; + if(shval > 0) + { + pval = chain_table[idx] = pval + shval; + if(idx) { chain_table_lengths[pidx] = pval - chain_table[pidx]; } + pidx = idx++; + } + else if(shval < 0) + { + chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */ + chain_table_lengths[idx] = prev_alias = shval; /* because during this loop iter would give stale data! */ + idx++; + } + else + { + chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */ + chain_table_lengths[idx] = prev_alias; /* because during this loop iter would give stale data! */ + idx++; + } } - } + else + { + uint64_t val = fstGetVarint32(pnt, &skiplen); + + int loopcnt = val >> 1; + for(i=0;i> 1); + if(idx) { chain_table_lengths[pidx] = pval - chain_table[pidx]; } + pidx = idx++; + } + else + { + int loopcnt = val >> 1; + for(i=0;i xc->maxhandle) idx = xc->maxhandle; for(i=0;if, &skiplen); if(val) { - unsigned char *mu = mem_for_traversal + traversal_mem_offs; - unsigned char *mc = malloc(chain_table_lengths[i]); + unsigned char *mu = mem_for_traversal + traversal_mem_offs; /* uncomp: dst */ + unsigned char *mc; /* comp: src */ unsigned long destlen = val; unsigned long sourcelen = chain_table_lengths[i]; - + + if(mc_mem_len < chain_table_lengths[i]) + { + free(mc_mem); + mc_mem = malloc(mc_mem_len = chain_table_lengths[i]); + } + mc = mc_mem; + fstFread(mc, chain_table_lengths[i], 1, xc->f); - if(packtype == 'F') + + switch(packtype) { - rc = fastlz_decompress(mc, sourcelen, mu, destlen); + case '4': rc = (destlen == LZ4_decompress_safe_partial((char *)mc, (char *)mu, sourcelen, destlen, destlen)) ? Z_OK : Z_DATA_ERROR; + break; + case 'F': fastlz_decompress(mc, sourcelen, mu, destlen); /* rc appears unreliable */ + break; + default: rc = uncompress(mu, &destlen, mc, sourcelen); + break; } - else - { - rc = uncompress(mu, &destlen, mc, sourcelen); - } - free(mc); + /* data to process is for(j=0;jlimit_range_valid) @@ -4726,12 +5187,15 @@ for(;;) } } - fprintf(fv, "#%"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)) { if(time_table[i] == xc->blackout_times[cur_blackout]) { - fprintf(fv, "$dump%s $end\n", (xc->blackout_activity[cur_blackout++]) ? "on" : "off"); + wx_len = sprintf(wx_buf, "$dump%s $end\n", (xc->blackout_activity[cur_blackout++]) ? "on" : "off"); + fstWritex(xc, wx_buf, wx_len); } } previous_time = time_table[i]; @@ -4769,11 +5233,12 @@ for(;;) { if(fv) { - int vcdid_len; - const char *vcd_id = fstVcdIDForFwrite(idx+1, &vcdid_len); - fputc(val, fv); - fstFwrite(vcd_id, vcdid_len, 1, fv); - fputc('\n', fv); + char vcd_id[16]; + int vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); + + vcd_id[0] = val; + vcd_id[vcdid_len+1] = '\n'; + fstWritex(xc, vcd_id, vcdid_len+2); } } headptr[idx] += skiplen; @@ -4814,21 +5279,23 @@ for(;;) { if(fv) { + char vcd_id[16]; int vcdid_len; - const char *vcd_id = fstVcdIDForFwrite(idx+1, &vcdid_len); - - fputc('s', fv); + + vcd_id[0] = 's'; + fstWritex(xc, vcd_id, 1); + + vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); { unsigned char *vesc = malloc(len*4 + 1); int vlen = fstUtilityBinToEsc(vesc, vdata, len); - - vesc[vlen] = 0; - fstFwrite(vesc, vlen, 1, fv); + fstWritex(xc, vesc, vlen); free(vesc); } - fputc(' ', fv); - fstFwrite(vcd_id, vcdid_len, 1, fv); - fputc('\n', fv); + + vcd_id[0] = ' '; + vcd_id[vcdid_len + 1] = '\n'; + fstWritex(xc, vcd_id, vcdid_len+2); } } } @@ -4884,8 +5351,10 @@ for(;;) else { if(fv) { - fputc((xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p', fv); - fstFwrite(xc->temp_signal_value_buf, len, 1, fv); + unsigned char ch_bp = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p'; + + fstWritex(xc, &ch_bp, 1); + fstWritex(xc, xc->temp_signal_value_buf, len); } } @@ -4903,8 +5372,10 @@ for(;;) { if(fv) { - fputc((xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p', fv); - fstFwrite(vdata, len, 1, fv); + unsigned char ch_bp = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p'; + + fstWritex(xc, &ch_bp, 1); + fstWritex(xc, vdata, len); } } } @@ -4981,6 +5452,9 @@ for(;;) { if(fv) { + char wx_buf[32]; + int wx_len; + clone_d = (unsigned char *)&d; if(xc->double_endian_match) { @@ -4996,18 +5470,19 @@ for(;;) } } - fprintf(fv, "r%.16g", d); + wx_len = sprintf(wx_buf, "r%.16g", d); + fstWritex(xc, wx_buf, wx_len); } } } if(fv) { - int vcdid_len; - const char *vcd_id = fstVcdIDForFwrite(idx+1, &vcdid_len); - fputc(' ', fv); - fstFwrite(vcd_id, vcdid_len, 1, fv); - fputc('\n', fv); + char vcd_id[16]; + int vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); + vcd_id[0] = ' '; + vcd_id[vcdid_len+1] = '\n'; + fstWritex(xc, vcd_id, vcdid_len+2); } skiplen += len; @@ -5032,25 +5507,30 @@ for(;;) block_err: free(tc_head); free(chain_cmem); - free(mem_for_traversal); + free(mem_for_traversal); mem_for_traversal = NULL; secnum++; if(secnum == xc->vc_section_count) break; /* in case file is growing, keep with original block count */ blkpos += seclen; } +if(mem_for_traversal) free(mem_for_traversal); /* scan-build */ free(length_remaining); free(headptr); free(scatterptr); -if(chain_table) - { - free(chain_table); - free(chain_table_lengths); - } +if(chain_table) free(chain_table); +if(chain_table_lengths) free(chain_table_lengths); free(time_table); +#ifndef FST_WRITEX_DISABLE +if(fv) + { + fstWritex(xc, NULL, 0); + } +#endif + return(1); } @@ -5167,7 +5647,7 @@ for(;;) } blkpos++; - if((sectype != FST_BL_VCDATA) && (sectype != FST_BL_VCDATA_DYN_ALIAS)) + if((sectype != FST_BL_VCDATA) && (sectype != FST_BL_VCDATA_DYN_ALIAS) && (sectype != FST_BL_VCDATA_DYN_ALIAS2)) { blkpos += seclen; continue; @@ -5189,7 +5669,7 @@ for(;;) beg_tim2 = fstReaderUint64(xc->f); end_tim2 = fstReaderUint64(xc->f); - if(((sectype != FST_BL_VCDATA)&&(sectype != FST_BL_VCDATA_DYN_ALIAS)) || (!seclen) || (beg_tim2 != tim)) + if(((sectype != FST_BL_VCDATA)&&(sectype != FST_BL_VCDATA_DYN_ALIAS)&&(sectype != FST_BL_VCDATA_DYN_ALIAS2)) || (!seclen) || (beg_tim2 != tim)) { blkpos = prev_blkpos; break; @@ -5214,9 +5694,9 @@ mem_required_for_traversal = fstReaderUint64(xc->f); #ifdef FST_DEBUG -printf("rvat sec: %d seclen: %d begtim: %d endtim: %d\n", +fprintf(stderr, "rvat sec: %d seclen: %d begtim: %d endtim: %d\n", secnum, (int)seclen, (int)beg_tim, (int)end_tim); -printf("\tmem_required_for_traversal: %d\n", (int)mem_required_for_traversal); +fprintf(stderr, "\tmem_required_for_traversal: %d\n", (int)mem_required_for_traversal); #endif /* process time block */ @@ -5235,7 +5715,7 @@ tsec_uclen = fstReaderUint64(xc->f); tsec_clen = fstReaderUint64(xc->f); tsec_nitems = fstReaderUint64(xc->f); #ifdef FST_DEBUG -printf("\ttime section unc: %d, com: %d (%d items)\n", +fprintf(stderr, "\ttime section unc: %d, com: %d (%d items)\n", (int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems); #endif ucdata = malloc(tsec_uclen); @@ -5310,9 +5790,9 @@ xc->rvat_vc_maxhandle = fstReaderVarint64(xc->f); xc->rvat_vc_start = ftello(xc->f); /* points to '!' character */ #ifdef FST_DEBUG -printf("\tframe_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", +fprintf(stderr, "\tframe_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", (int)frame_uclen, (int)frame_clen, (int)xc->rvat_frame_maxhandle); -printf("\tvc_maxhandle: %d\n", (int)xc->rvat_vc_maxhandle); +fprintf(stderr, "\tvc_maxhandle: %d\n", (int)xc->rvat_vc_maxhandle); #endif indx_pntr = blkpos + seclen - 24 -tsec_clen -8; @@ -5320,7 +5800,7 @@ fstReaderFseeko(xc, xc->f, indx_pntr, SEEK_SET); chain_clen = fstReaderUint64(xc->f); indx_pos = indx_pntr - chain_clen; #ifdef FST_DEBUG -printf("\tindx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen); +fprintf(stderr, "\tindx_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); @@ -5384,7 +5864,7 @@ for(i=0;irvat_data_valid = 1; @@ -5647,7 +6127,6 @@ if(xc->signal_lens[facidx] == 1) /**********************************************************************/ -#ifndef FST_DYNAMIC_ALIAS_DISABLE #ifndef _WAVE_HAVE_JUDY /***********************/ @@ -5850,7 +6329,6 @@ if(base && *base) } } -#endif #endif /**********************************************************************/ diff --git a/vpi/fstapi.h b/vpi/fstapi.h index 9ace034ac..d45a3894e 100644 --- a/vpi/fstapi.h +++ b/vpi/fstapi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2013 Tony Bybell. + * Copyright (c) 2009-2014 Tony Bybell. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -40,6 +40,12 @@ extern "C" { typedef uint32_t fstHandle; +enum fstWriterPackType { + FST_WR_PT_ZLIB = 0, + FST_WR_PT_FASTLZ = 1, + FST_WR_PT_LZ4 = 2 +}; + enum fstFileType { FST_FT_MIN = 0, @@ -57,6 +63,9 @@ enum fstBlockType { FST_BL_GEOM = 3, FST_BL_HIER = 4, FST_BL_VCDATA_DYN_ALIAS = 5, + FST_BL_HIER_LZ4 = 6, + FST_BL_HIER_LZ4DUO = 7, + FST_BL_VCDATA_DYN_ALIAS2 = 8, FST_BL_ZWRAPPER = 254, /* indicates that whole trace is gz wrapped */ FST_BL_SKIP = 255 /* used while block is being written */ @@ -338,7 +347,7 @@ void fstWriterSetDate(void *ctx, const char *dat); void fstWriterSetDumpSizeLimit(void *ctx, uint64_t numbytes); void fstWriterSetEnvVar(void *ctx, const char *envvar); void fstWriterSetFileType(void *ctx, enum fstFileType filetype); -void fstWriterSetPackType(void *ctx, int typ); /* type = 0 (libz), 1 (fastlz) */ +void fstWriterSetPackType(void *ctx, enum fstWriterPackType typ); void fstWriterSetParallelMode(void *ctx, int enable); void fstWriterSetRepackOnClose(void *ctx, int enable); /* type = 0 (none), 1 (libz) */ void fstWriterSetScope(void *ctx, enum fstScopeType scopetype, @@ -401,6 +410,7 @@ void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx); void fstReaderSetFacProcessMaskAll(void *ctx); void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_time); void fstReaderSetUnlimitedTimeRange(void *ctx); +void fstReaderSetVcdExtensions(void *ctx, int enable); /* diff --git a/vpi/lz4.c b/vpi/lz4.c new file mode 100644 index 000000000..ee37895f4 --- /dev/null +++ b/vpi/lz4.c @@ -0,0 +1,877 @@ +/* + LZ4 - Fast LZ compression algorithm + Copyright (C) 2011-2014, Yann Collet. + BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php) + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are + met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following disclaimer + in the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + You can contact the author at : + - LZ4 source repository : http://code.google.com/p/lz4/ + - LZ4 public forum : https://groups.google.com/forum/#!forum/lz4c +*/ + +/************************************** + Tuning parameters +**************************************/ +/* + * MEMORY_USAGE : + * Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.) + * Increasing memory usage improves compression ratio + * Reduced memory usage can improve speed, due to cache effect + * Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache + */ +#define MEMORY_USAGE 14 + +/* + * HEAPMODE : + * Select how default compression functions will allocate memory for their hash table, + * in memory stack (0:default, fastest), or in memory heap (1:requires memory allocation (malloc)). + */ +#define HEAPMODE 0 + + +/************************************** + CPU Feature Detection +**************************************/ +/* 32 or 64 bits ? */ +#if (defined(__x86_64__) || defined(_M_X64) || defined(_WIN64) \ + || defined(__powerpc64__) || defined(__ppc64__) || defined(__PPC64__) \ + || defined(__64BIT__) || defined(_LP64) || defined(__LP64__) \ + || defined(__ia64) || defined(__itanium__) || defined(_M_IA64) ) /* Detects 64 bits mode */ +# define LZ4_ARCH64 1 +#else +# define LZ4_ARCH64 0 +#endif + +/* + * Little Endian or Big Endian ? + * Overwrite the #define below if you know your architecture endianess + */ +#if defined (__GLIBC__) +# include +# if (__BYTE_ORDER == __BIG_ENDIAN) +# define LZ4_BIG_ENDIAN 1 +# endif +#elif (defined(__BIG_ENDIAN__) || defined(__BIG_ENDIAN) || defined(_BIG_ENDIAN)) && !(defined(__LITTLE_ENDIAN__) || defined(__LITTLE_ENDIAN) || defined(_LITTLE_ENDIAN)) +# define LZ4_BIG_ENDIAN 1 +#elif defined(__sparc) || defined(__sparc__) \ + || defined(__powerpc__) || defined(__ppc__) || defined(__PPC__) \ + || defined(__hpux) || defined(__hppa) \ + || defined(_MIPSEB) || defined(__s390__) +# define LZ4_BIG_ENDIAN 1 +#else +/* Little Endian assumed. PDP Endian and other very rare endian format are unsupported. */ +#endif + +/* + * Unaligned memory access is automatically enabled for "common" CPU, such as x86. + * For others CPU, such as ARM, the compiler may be more cautious, inserting unnecessary extra code to ensure aligned access property + * If you know your target CPU supports unaligned memory access, you want to force this option manually to improve performance + */ +#if defined(__ARM_FEATURE_UNALIGNED) +# define LZ4_FORCE_UNALIGNED_ACCESS 1 +#endif + +/* Define this parameter if your target system or compiler does not support hardware bit count */ +#if defined(_MSC_VER) && defined(_WIN32_WCE) /* Visual Studio for Windows CE does not support Hardware bit count */ +# define LZ4_FORCE_SW_BITCOUNT +#endif + +/* + * BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE : + * This option may provide a small boost to performance for some big endian cpu, although probably modest. + * You may set this option to 1 if data will remain within closed environment. + * This option is useless on Little_Endian CPU (such as x86) + */ + +/* #define BIG_ENDIAN_NATIVE_BUT_INCOMPATIBLE 1 */ + + +/************************************** + Compiler Options +**************************************/ +#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ +/* "restrict" is a known keyword */ +#else +# define restrict /* Disable restrict */ +#endif + +#ifdef _MSC_VER /* Visual Studio */ +# define FORCE_INLINE static __forceinline +# include /* For Visual 2005 */ +# if LZ4_ARCH64 /* 64-bits */ +# pragma intrinsic(_BitScanForward64) /* For Visual 2005 */ +# pragma intrinsic(_BitScanReverse64) /* For Visual 2005 */ +# else /* 32-bits */ +# pragma intrinsic(_BitScanForward) /* For Visual 2005 */ +# pragma intrinsic(_BitScanReverse) /* For Visual 2005 */ +# endif +# pragma warning(disable : 4127) /* disable: C4127: conditional expression is constant */ +#else +# ifdef __GNUC__ +# define FORCE_INLINE static inline __attribute__((always_inline)) +# else +# define FORCE_INLINE static inline +# endif +#endif + +#ifdef _MSC_VER /* Visual Studio */ +# define lz4_bswap16(x) _byteswap_ushort(x) +#else +# define lz4_bswap16(x) ((unsigned short int) ((((x) >> 8) & 0xffu) | (((x) & 0xffu) << 8))) +#endif + +#define GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) + +#if (GCC_VERSION >= 302) || (__INTEL_COMPILER >= 800) || defined(__clang__) +# define expect(expr,value) (__builtin_expect ((expr),(value)) ) +#else +# define expect(expr,value) (expr) +#endif + +#define likely(expr) expect((expr) != 0, 1) +#define unlikely(expr) expect((expr) != 0, 0) + + +/************************************** + Memory routines +**************************************/ +#include /* malloc, calloc, free */ +#define ALLOCATOR(n,s) calloc(n,s) +#define FREEMEM free +#include /* memset, memcpy */ +#define MEM_INIT memset + + +/************************************** + Includes +**************************************/ +#include "lz4.h" + + +/************************************** + Basic Types +**************************************/ +#if defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */ +# include + typedef uint8_t BYTE; + typedef uint16_t U16; + typedef uint32_t U32; + typedef int32_t S32; + typedef uint64_t U64; +#else + typedef unsigned char BYTE; + typedef unsigned short U16; + typedef unsigned int U32; + typedef signed int S32; + typedef unsigned long long U64; +#endif + +#if defined(__GNUC__) && !defined(LZ4_FORCE_UNALIGNED_ACCESS) +# define _PACKED __attribute__ ((packed)) +#else +# define _PACKED +#endif + +#if !defined(LZ4_FORCE_UNALIGNED_ACCESS) && !defined(__GNUC__) +# if defined(__IBMC__) || defined(__SUNPRO_C) || defined(__SUNPRO_CC) +# pragma pack(1) +# else +# pragma pack(push, 1) +# endif +#endif + +typedef struct { U16 v; } _PACKED U16_S; +typedef struct { U32 v; } _PACKED U32_S; +typedef struct { U64 v; } _PACKED U64_S; +typedef struct {size_t v;} _PACKED size_t_S; + +#if !defined(LZ4_FORCE_UNALIGNED_ACCESS) && !defined(__GNUC__) +# if defined(__SUNPRO_C) || defined(__SUNPRO_CC) +# pragma pack(0) +# else +# pragma pack(pop) +# endif +#endif + +#define A16(x) (((U16_S *)(x))->v) +#define A32(x) (((U32_S *)(x))->v) +#define A64(x) (((U64_S *)(x))->v) +#define AARCH(x) (((size_t_S *)(x))->v) + + +/************************************** + Constants +**************************************/ +#define LZ4_HASHLOG (MEMORY_USAGE-2) +#define HASHTABLESIZE (1 << MEMORY_USAGE) +#define HASHNBCELLS4 (1 << LZ4_HASHLOG) + +#define MINMATCH 4 + +#define COPYLENGTH 8 +#define LASTLITERALS 5 +#define MFLIMIT (COPYLENGTH+MINMATCH) +static const int LZ4_minLength = (MFLIMIT+1); + +#define KB *(1U<<10) +#define MB *(1U<<20) +#define GB *(1U<<30) + +#define LZ4_64KLIMIT ((64 KB) + (MFLIMIT-1)) +#define SKIPSTRENGTH 6 /* Increasing this value will make the compression run slower on incompressible data */ + +#define MAXD_LOG 16 +#define MAX_DISTANCE ((1 << MAXD_LOG) - 1) + +#define ML_BITS 4 +#define ML_MASK ((1U<=e; */ +#else +# define LZ4_WILDCOPY(d,s,e) { if (likely(e-d <= 8)) LZ4_COPY8(d,s) else do { LZ4_COPY8(d,s) } while (d>3); +# elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_clzll(val) >> 3); +# else + int r; + if (!(val>>32)) { r=4; } else { r=0; val>>=32; } + if (!(val>>16)) { r+=2; val>>=8; } else { val>>=24; } + r += (!val); + return r; +# endif +# else +# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanForward64( &r, val ); + return (int)(r>>3); +# elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_ctzll(val) >> 3); +# else + static const int DeBruijnBytePos[64] = { 0, 0, 0, 0, 0, 1, 1, 2, 0, 3, 1, 3, 1, 4, 2, 7, 0, 2, 3, 6, 1, 5, 3, 5, 1, 3, 4, 4, 2, 5, 6, 7, 7, 0, 1, 2, 3, 3, 4, 6, 2, 6, 5, 5, 3, 4, 5, 6, 7, 1, 2, 4, 6, 4, 4, 5, 7, 2, 6, 5, 7, 6, 7, 7 }; + return DeBruijnBytePos[((U64)((val & -(long long)val) * 0x0218A392CDABBD3FULL)) >> 58]; +# endif +# endif +} + +#else + +FORCE_INLINE int LZ4_NbCommonBytes (register U32 val) +{ +# if defined(LZ4_BIG_ENDIAN) +# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r = 0; + _BitScanReverse( &r, val ); + return (int)(r>>3); +# elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_clz(val) >> 3); +# else + int r; + if (!(val>>16)) { r=2; val>>=8; } else { r=0; val>>=24; } + r += (!val); + return r; +# endif +# else +# if defined(_MSC_VER) && !defined(LZ4_FORCE_SW_BITCOUNT) + unsigned long r; + _BitScanForward( &r, val ); + return (int)(r>>3); +# elif defined(__GNUC__) && (GCC_VERSION >= 304) && !defined(LZ4_FORCE_SW_BITCOUNT) + return (__builtin_ctz(val) >> 3); +# else + static const int DeBruijnBytePos[32] = { 0, 0, 3, 0, 3, 1, 3, 0, 3, 2, 2, 1, 3, 2, 0, 1, 3, 3, 1, 2, 2, 2, 2, 0, 3, 1, 2, 0, 1, 0, 1, 1 }; + return DeBruijnBytePos[((U32)((val & -(S32)val) * 0x077CB531U)) >> 27]; +# endif +# endif +} + +#endif + + +/**************************** + Compression functions +****************************/ +FORCE_INLINE int LZ4_hashSequence(U32 sequence, tableType_t tableType) +{ + if (tableType == byU16) + return (((sequence) * 2654435761U) >> ((MINMATCH*8)-(LZ4_HASHLOG+1))); + else + return (((sequence) * 2654435761U) >> ((MINMATCH*8)-LZ4_HASHLOG)); +} + +FORCE_INLINE int LZ4_hashPosition(const BYTE* p, tableType_t tableType) { return LZ4_hashSequence(A32(p), tableType); } + +FORCE_INLINE void LZ4_putPositionOnHash(const BYTE* p, U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase) +{ + switch (tableType) + { + case byPtr: { const BYTE** hashTable = (const BYTE**) tableBase; hashTable[h] = p; break; } + case byU32: { U32* hashTable = (U32*) tableBase; hashTable[h] = (U32)(p-srcBase); break; } + case byU16: { U16* hashTable = (U16*) tableBase; hashTable[h] = (U16)(p-srcBase); break; } + } +} + +FORCE_INLINE void LZ4_putPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) +{ + U32 h = LZ4_hashPosition(p, tableType); + LZ4_putPositionOnHash(p, h, tableBase, tableType, srcBase); +} + +FORCE_INLINE const BYTE* LZ4_getPositionOnHash(U32 h, void* tableBase, tableType_t tableType, const BYTE* srcBase) +{ + if (tableType == byPtr) { const BYTE** hashTable = (const BYTE**) tableBase; return hashTable[h]; } + if (tableType == byU32) { U32* hashTable = (U32*) tableBase; return hashTable[h] + srcBase; } + { U16* hashTable = (U16*) tableBase; return hashTable[h] + srcBase; } /* default, to ensure a return */ +} + +FORCE_INLINE const BYTE* LZ4_getPosition(const BYTE* p, void* tableBase, tableType_t tableType, const BYTE* srcBase) +{ + U32 h = LZ4_hashPosition(p, tableType); + return LZ4_getPositionOnHash(h, tableBase, tableType, srcBase); +} + + +FORCE_INLINE int LZ4_compress_generic( + void* ctx, + const char* source, + char* dest, + int inputSize, + int maxOutputSize, + + limitedOutput_directive limitedOutput, + tableType_t tableType, + prefix64k_directive prefix) +{ + const BYTE* ip = (const BYTE*) source; + const BYTE* const base = (prefix==withPrefix) ? ((LZ4_Data_Structure*)ctx)->base : (const BYTE*) source; + const BYTE* const lowLimit = ((prefix==withPrefix) ? ((LZ4_Data_Structure*)ctx)->bufferStart : (const BYTE*)source); + const BYTE* anchor = (const BYTE*) source; + const BYTE* const iend = ip + inputSize; + const BYTE* const mflimit = iend - MFLIMIT; + const BYTE* const matchlimit = iend - LASTLITERALS; + + BYTE* op = (BYTE*) dest; + BYTE* const oend = op + maxOutputSize; + + int length; + const int skipStrength = SKIPSTRENGTH; + U32 forwardH; + + /* Init conditions */ + if ((U32)inputSize > (U32)LZ4_MAX_INPUT_SIZE) return 0; /* Unsupported input size, too large (or negative) */ + if ((prefix==withPrefix) && (ip != ((LZ4_Data_Structure*)ctx)->nextBlock)) return 0; /* must continue from end of previous block */ + if (prefix==withPrefix) ((LZ4_Data_Structure*)ctx)->nextBlock=iend; /* do it now, due to potential early exit */ + if ((tableType == byU16) && (inputSize>=(int)LZ4_64KLIMIT)) return 0; /* Size too large (not within 64K limit) */ + if (inputSize> skipStrength; + ip = forwardIp; + forwardIp = ip + step; + + if (unlikely(forwardIp > mflimit)) { goto _last_literals; } + + forwardH = LZ4_hashPosition(forwardIp, tableType); + ref = LZ4_getPositionOnHash(h, ctx, tableType, base); + LZ4_putPositionOnHash(ip, h, ctx, tableType, base); + + } while ((ref + MAX_DISTANCE < ip) || (A32(ref) != A32(ip))); + + /* Catch up */ + while ((ip>anchor) && (ref > lowLimit) && (unlikely(ip[-1]==ref[-1]))) { ip--; ref--; } + + /* Encode Literal length */ + length = (int)(ip - anchor); + token = op++; + if ((limitedOutput) && (unlikely(op + length + (2 + 1 + LASTLITERALS) + (length/255) > oend))) return 0; /* Check output limit */ + if (length>=(int)RUN_MASK) + { + int len = length-RUN_MASK; + *token=(RUN_MASK<= 255 ; len-=255) *op++ = 255; + *op++ = (BYTE)len; + } + else *token = (BYTE)(length<>8) > oend))) return 0; /* Check output limit */ + if (length>=(int)ML_MASK) + { + *token += ML_MASK; + length -= ML_MASK; + for (; length > 509 ; length-=510) { *op++ = 255; *op++ = 255; } + if (length >= 255) { length-=255; *op++ = 255; } + *op++ = (BYTE)length; + } + else *token += (BYTE)(length); + + /* Test end of chunk */ + if (ip > mflimit) { anchor = ip; break; } + + /* Fill table */ + LZ4_putPosition(ip-2, ctx, tableType, base); + + /* Test next position */ + ref = LZ4_getPosition(ip, ctx, tableType, base); + LZ4_putPosition(ip, ctx, tableType, base); + if ((ref + MAX_DISTANCE >= ip) && (A32(ref) == A32(ip))) { token = op++; *token=0; goto _next_match; } + + /* Prepare next loop */ + anchor = ip++; + forwardH = LZ4_hashPosition(ip, tableType); + } + +_last_literals: + /* Encode Last Literals */ + { + int lastRun = (int)(iend - anchor); + if ((limitedOutput) && (((char*)op - dest) + lastRun + 1 + ((lastRun+255-RUN_MASK)/255) > (U32)maxOutputSize)) return 0; /* Check output limit */ + if (lastRun>=(int)RUN_MASK) { *op++=(RUN_MASK<= 255 ; lastRun-=255) *op++ = 255; *op++ = (BYTE) lastRun; } + else *op++ = (BYTE)(lastRun<hashTable, 0, sizeof(lz4ds->hashTable)); + lz4ds->bufferStart = base; + lz4ds->base = base; + lz4ds->nextBlock = base; +} + +int LZ4_resetStreamState(void* state, const char* inputBuffer) +{ + if ((((size_t)state) & 3) != 0) return 1; /* Error : pointer is not aligned on 4-bytes boundary */ + LZ4_init((LZ4_Data_Structure*)state, (const BYTE*)inputBuffer); + return 0; +} + +void* LZ4_create (const char* inputBuffer) +{ + void* lz4ds = ALLOCATOR(1, sizeof(LZ4_Data_Structure)); + LZ4_init ((LZ4_Data_Structure*)lz4ds, (const BYTE*)inputBuffer); + return lz4ds; +} + + +int LZ4_free (void* LZ4_Data) +{ + FREEMEM(LZ4_Data); + return (0); +} + + +char* LZ4_slideInputBuffer (void* LZ4_Data) +{ + LZ4_Data_Structure* lz4ds = (LZ4_Data_Structure*)LZ4_Data; + size_t delta = lz4ds->nextBlock - (lz4ds->bufferStart + 64 KB); + + if ( (lz4ds->base - delta > lz4ds->base) /* underflow control */ + || ((size_t)(lz4ds->nextBlock - lz4ds->base) > 0xE0000000) ) /* close to 32-bits limit */ + { + size_t deltaLimit = (lz4ds->nextBlock - 64 KB) - lz4ds->base; + int nH; + + for (nH=0; nH < HASHNBCELLS4; nH++) + { + if ((size_t)(lz4ds->hashTable[nH]) < deltaLimit) lz4ds->hashTable[nH] = 0; + else lz4ds->hashTable[nH] -= (U32)deltaLimit; + } + memcpy((void*)(lz4ds->bufferStart), (const void*)(lz4ds->nextBlock - 64 KB), 64 KB); + lz4ds->base = lz4ds->bufferStart; + lz4ds->nextBlock = lz4ds->base + 64 KB; + } + else + { + memcpy((void*)(lz4ds->bufferStart), (const void*)(lz4ds->nextBlock - 64 KB), 64 KB); + lz4ds->nextBlock -= delta; + lz4ds->base -= delta; + } + + return (char*)(lz4ds->nextBlock); +} + + +int LZ4_compress_continue (void* LZ4_Data, const char* source, char* dest, int inputSize) +{ + return LZ4_compress_generic(LZ4_Data, source, dest, inputSize, 0, notLimited, byU32, withPrefix); +} + + +int LZ4_compress_limitedOutput_continue (void* LZ4_Data, const char* source, char* dest, int inputSize, int maxOutputSize) +{ + return LZ4_compress_generic(LZ4_Data, source, dest, inputSize, maxOutputSize, limited, byU32, withPrefix); +} + + +/**************************** + Decompression functions +****************************/ + +/* + * This generic decompression function cover all use cases. + * It shall be instanciated several times, using different sets of directives + * Note that it is essential this generic function is really inlined, + * in order to remove useless branches during compilation optimisation. + */ +FORCE_INLINE int LZ4_decompress_generic( + const char* source, + char* dest, + int inputSize, + int outputSize, /* If endOnInput==endOnInputSize, this value is the max size of Output Buffer. */ + + int endOnInput, /* endOnOutputSize, endOnInputSize */ + int prefix64k, /* noPrefix, withPrefix */ + int partialDecoding, /* full, partial */ + int targetOutputSize /* only used if partialDecoding==partial */ + ) +{ + /* Local Variables */ + const BYTE* restrict ip = (const BYTE*) source; + const BYTE* ref; + const BYTE* const iend = ip + inputSize; + + BYTE* op = (BYTE*) dest; + BYTE* const oend = op + outputSize; + BYTE* cpy; + BYTE* oexit = op + targetOutputSize; + + /*const size_t dec32table[] = {0, 3, 2, 3, 0, 0, 0, 0}; / static reduces speed for LZ4_decompress_safe() on GCC64 */ + const size_t dec32table[] = {4-0, 4-3, 4-2, 4-3, 4-0, 4-0, 4-0, 4-0}; /* static reduces speed for LZ4_decompress_safe() on GCC64 */ + static const size_t dec64table[] = {0, 0, 0, (size_t)-1, 0, 1, 2, 3}; + + + /* Special cases */ + if ((partialDecoding) && (oexit> oend-MFLIMIT)) oexit = oend-MFLIMIT; /* targetOutputSize too high => decode everything */ + if ((endOnInput) && (unlikely(outputSize==0))) return ((inputSize==1) && (*ip==0)) ? 0 : -1; /* Empty output buffer */ + if ((!endOnInput) && (unlikely(outputSize==0))) return (*ip==0?1:-1); + + + /* Main Loop */ + while (1) + { + unsigned token; + size_t length; + + /* get runlength */ + token = *ip++; + if ((length=(token>>ML_BITS)) == RUN_MASK) + { + unsigned s=255; + while (((endOnInput)?ip(partialDecoding?oexit:oend-MFLIMIT)) || (ip+length>iend-(2+1+LASTLITERALS))) ) + || ((!endOnInput) && (cpy>oend-COPYLENGTH))) + { + if (partialDecoding) + { + if (cpy > oend) goto _output_error; /* Error : write attempt beyond end of output buffer */ + if ((endOnInput) && (ip+length > iend)) goto _output_error; /* Error : read attempt beyond end of input buffer */ + } + else + { + if ((!endOnInput) && (cpy != oend)) goto _output_error; /* Error : block decoding must stop exactly there */ + if ((endOnInput) && ((ip+length != iend) || (cpy > oend))) goto _output_error; /* Error : input must be consumed */ + } + memcpy(op, ip, length); + ip += length; + op += length; + break; /* Necessarily EOF, due to parsing restrictions */ + } + LZ4_WILDCOPY(op, ip, cpy); ip -= (op-cpy); op = cpy; + + /* get offset */ + LZ4_READ_LITTLEENDIAN_16(ref,cpy,ip); ip+=2; + if ((prefix64k==noPrefix) && (unlikely(ref < (BYTE* const)dest))) goto _output_error; /* Error : offset outside destination buffer */ + + /* get matchlength */ + if ((length=(token&ML_MASK)) == ML_MASK) + { + while ((!endOnInput) || (ipoend-COPYLENGTH-(STEPSIZE-4))) + { + if (cpy > oend-LASTLITERALS) goto _output_error; /* Error : last 5 bytes must be literals */ + LZ4_SECURECOPY(op, ref, (oend-COPYLENGTH)); + while(op (unsigned int)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16) +static inline int LZ4_compressBound(int isize) { return LZ4_COMPRESSBOUND(isize); } + +/* +LZ4_compressBound() : + Provides the maximum size that LZ4 may output in a "worst case" scenario (input data not compressible) + primarily useful for memory allocation of output buffer. + inline function is recommended for the general case, + macro is also provided when result needs to be evaluated at compilation (such as stack memory allocation). + + isize : is the input size. Max supported value is LZ4_MAX_INPUT_SIZE + return : maximum output size in a "worst case" scenario + or 0, if input size is too large ( > LZ4_MAX_INPUT_SIZE) +*/ + + +int LZ4_compress_limitedOutput (const char* source, char* dest, int inputSize, int maxOutputSize); + +/* +LZ4_compress_limitedOutput() : + Compress 'inputSize' bytes from 'source' into an output buffer 'dest' of maximum size 'maxOutputSize'. + If it cannot achieve it, compression will stop, and result of the function will be zero. + This function never writes outside of provided output buffer. + + inputSize : Max supported value is LZ4_MAX_INPUT_VALUE + maxOutputSize : is the size of the destination buffer (which must be already allocated) + return : the number of bytes written in buffer 'dest' + or 0 if the compression fails +*/ + + +int LZ4_decompress_fast (const char* source, char* dest, int outputSize); + +/* +LZ4_decompress_fast() : + outputSize : is the original (uncompressed) size + return : the number of bytes read from the source buffer (in other words, the compressed size) + If the source stream is malformed, the function will stop decoding and return a negative result. + note : This function is a bit faster than LZ4_decompress_safe() + This function never writes outside of output buffers, but may read beyond input buffer in case of malicious data packet. + Use this function preferably into a trusted environment (data to decode comes from a trusted source). + Destination buffer must be already allocated. Its size must be a minimum of 'outputSize' bytes. +*/ + +int LZ4_decompress_safe_partial (const char* source, char* dest, int inputSize, int targetOutputSize, int maxOutputSize); + +/* +LZ4_decompress_safe_partial() : + This function decompress a compressed block of size 'inputSize' at position 'source' + into output buffer 'dest' of size 'maxOutputSize'. + The function tries to stop decompressing operation as soon as 'targetOutputSize' has been reached, + reducing decompression time. + return : the number of bytes decoded in the destination buffer (necessarily <= maxOutputSize) + Note : this number can be < 'targetOutputSize' should the compressed block to decode be smaller. + Always control how many bytes were decoded. + If the source stream is detected malformed, the function will stop decoding and return a negative result. + This function never writes outside of output buffer, and never reads outside of input buffer. It is therefore protected against malicious data packets +*/ + + +int LZ4_sizeofState(); +int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize); +int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize); + +/* +These functions are provided should you prefer to allocate memory for compression tables with your own allocation methods. +To know how much memory must be allocated for the compression tables, use : +int LZ4_sizeofState(); + +Note that tables must be aligned on 4-bytes boundaries, otherwise compression will fail (return code 0). + +The allocated memory can be provided to the compressions functions using 'void* state' parameter. +LZ4_compress_withState() and LZ4_compress_limitedOutput_withState() are equivalent to previously described functions. +They just use the externally allocated memory area instead of allocating their own (on stack, or on heap). +*/ + + +/************************************** + Streaming Functions +**************************************/ +void* LZ4_create (const char* inputBuffer); +int LZ4_compress_continue (void* LZ4_Data, const char* source, char* dest, int inputSize); +int LZ4_compress_limitedOutput_continue (void* LZ4_Data, const char* source, char* dest, int inputSize, int maxOutputSize); +char* LZ4_slideInputBuffer (void* LZ4_Data); +int LZ4_free (void* LZ4_Data); + +/* +These functions allow the compression of dependent blocks, where each block benefits from prior 64 KB within preceding blocks. +In order to achieve this, it is necessary to start creating the LZ4 Data Structure, thanks to the function : + +void* LZ4_create (const char* inputBuffer); +The result of the function is the (void*) pointer on the LZ4 Data Structure. +This pointer will be needed in all other functions. +If the pointer returned is NULL, then the allocation has failed, and compression must be aborted. +The only parameter 'const char* inputBuffer' must, obviously, point at the beginning of input buffer. +The input buffer must be already allocated, and size at least 192KB. +'inputBuffer' will also be the 'const char* source' of the first block. + +All blocks are expected to lay next to each other within the input buffer, starting from 'inputBuffer'. +To compress each block, use either LZ4_compress_continue() or LZ4_compress_limitedOutput_continue(). +Their behavior are identical to LZ4_compress() or LZ4_compress_limitedOutput(), +but require the LZ4 Data Structure as their first argument, and check that each block starts right after the previous one. +If next block does not begin immediately after the previous one, the compression will fail (return 0). + +When it's no longer possible to lay the next block after the previous one (not enough space left into input buffer), a call to : +char* LZ4_slideInputBuffer(void* LZ4_Data); +must be performed. It will typically copy the latest 64KB of input at the beginning of input buffer. +Note that, for this function to work properly, minimum size of an input buffer must be 192KB. +==> The memory position where the next input data block must start is provided as the result of the function. + +Compression can then resume, using LZ4_compress_continue() or LZ4_compress_limitedOutput_continue(), as usual. + +When compression is completed, a call to LZ4_free() will release the memory used by the LZ4 Data Structure. +*/ + +int LZ4_sizeofStreamState(); +int LZ4_resetStreamState(void* state, const char* inputBuffer); + +/* +These functions achieve the same result as : +void* LZ4_create (const char* inputBuffer); + +They are provided here to allow the user program to allocate memory using its own routines. + +To know how much space must be allocated, use LZ4_sizeofStreamState(); +Note also that space must be 4-bytes aligned. + +Once space is allocated, you must initialize it using : LZ4_resetStreamState(void* state, const char* inputBuffer); +void* state is a pointer to the space allocated. +It must be aligned on 4-bytes boundaries, and be large enough. +The parameter 'const char* inputBuffer' must, obviously, point at the beginning of input buffer. +The input buffer must be already allocated, and size at least 192KB. +'inputBuffer' will also be the 'const char* source' of the first block. + +The same space can be re-used multiple times, just by initializing it each time with LZ4_resetStreamState(). +return value of LZ4_resetStreamState() must be 0 is OK. +Any other value means there was an error (typically, pointer is not aligned on 4-bytes boundaries). +*/ + + +int LZ4_decompress_safe_withPrefix64k (const char* source, char* dest, int inputSize, int maxOutputSize); +int LZ4_decompress_fast_withPrefix64k (const char* source, char* dest, int outputSize); + +/* +*_withPrefix64k() : + These decoding functions work the same as their "normal name" versions, + but can use up to 64KB of data in front of 'char* dest'. + These functions are necessary to decode inter-dependant blocks. +*/ + + +/************************************** + Obsolete Functions +**************************************/ +/* +These functions are deprecated and should no longer be used. +They are provided here for compatibility with existing user programs. +*/ +static inline int LZ4_uncompress (const char* source, char* dest, int outputSize) { return LZ4_decompress_fast(source, dest, outputSize); } +static inline int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize) { return LZ4_decompress_safe(source, dest, isize, maxOutputSize); } + + + +#if defined (__cplusplus) +} +#endif + From 734d56ce25c7822610c20edb6e70205016ec74bd Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 10 Apr 2014 14:36:06 -0700 Subject: [PATCH 021/245] Remove space issue. --- parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parse.y b/parse.y index 757fc8ced..94de008a8 100644 --- a/parse.y +++ b/parse.y @@ -3850,7 +3850,7 @@ port_declaration @2.first_line); real_type_t*real_type = new real_type_t(real_type_t::REAL); FILE_NAME(real_type, @3); - pform_module_define_port(@2, name, NetNet::PINPUT, + pform_module_define_port(@2, name, NetNet::PINPUT, NetNet::WIRE, real_type, $1); port_declaration_context.port_type = NetNet::PINPUT; port_declaration_context.port_net_type = NetNet::WIRE; From fdcb073c146ad890c0d90bcfa95c1ad6bec2e8bc Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 13 Apr 2014 16:25:30 -0700 Subject: [PATCH 022/245] Fix a variety of bugs in vpi_handle_by_name. This function was apparently not well tested, because any use of acc_handle_object() triggered a use of vpi_handle_by_name that was buggy. The implementation was awkwardly written, to parts of it were redone. --- vvp/vpi_priv.cc | 105 ++++++++++++++++++++++++++++++++++++------------ 1 file changed, 80 insertions(+), 25 deletions(-) diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index 43e0cde7a..043320dc6 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -23,6 +23,7 @@ #ifdef CHECK_WITH_VALGRIND # include "vvp_cleanup.h" #endif +# include # include # include # include @@ -31,6 +32,7 @@ # include # include +using namespace std; vpi_mode_t vpi_mode_flag = VPI_MODE_NONE; FILE*vpi_trace = 0; @@ -1262,22 +1264,30 @@ static vpiHandle find_name(const char *name, vpiHandle handle) static vpiHandle find_scope(const char *name, vpiHandle handle, int depth) { - vpiHandle iter, hand, rtn = 0; - iter = !handle ? vpi_iterate(vpiModule, NULL) : - vpi_iterate(vpiInternalScope, handle); + vpiHandle iter = handle==0 + ? vpi_iterate(vpiModule, NULL) + : vpi_iterate(vpiInternalScope, handle); + vector name_buf (strlen(name)+1); + strcpy(&name_buf[0], name); + char*nm_first = &name_buf[0]; + char*nm_rest = strchr(nm_first, '.'); + if (nm_rest) { + *nm_rest++ = 0; + } + + vpiHandle rtn = 0; + vpiHandle hand; while (iter && (hand = vpi_scan(iter))) { char *nm = vpi_get_str(vpiName, hand); - int len = strlen(nm); - const char *cp = name + len; /* hier separator */ - if (!handle && !strcmp(name, nm)) { - /* root module */ - rtn = hand; - } else if (!strncmp(name, nm, len) && *(cp) == '.') - /* recurse deeper */ - rtn = find_scope(cp+1, hand, depth + 1); + if (strcmp(nm_first,nm)==0) { + if (nm_rest) + rtn=find_scope(nm_rest, hand, depth+1); + else + rtn = hand; + } /* found it yet ? */ if (rtn) { @@ -1286,9 +1296,6 @@ static vpiHandle find_scope(const char *name, vpiHandle handle, int depth) } } - /* matched up to here */ - if (!rtn) rtn = handle; - return rtn; } @@ -1301,6 +1308,20 @@ vpiHandle vpi_handle_by_name(const char *name, vpiHandle scope) name, scope); } + // Chop the name into path and base. For example, if the name + // is "a.b.c", then nm_path becomes "a.b" and nm_base becomes + // "c". If the name is "c" then nm_path is nil and nm_base is "c". + vector name_buf (strlen(name)+1); + strcpy(&name_buf[0], name); + char*nm_path = &name_buf[0]; + char*nm_base = strrchr(nm_path, '.'); + if (nm_base) { + *nm_base++ = 0; + } else { + nm_base = nm_path; + nm_path = 0; + } + /* If scope provided, look in corresponding module; otherwise * traverse the hierarchy specified in name to find the leaf module * and try finding it there. @@ -1315,26 +1336,60 @@ vpiHandle vpi_handle_by_name(const char *name, vpiHandle scope) hand = scope; break; default: + if (vpi_trace) { + fprintf(vpi_trace, "vpi_handle_by_name: " + "Scope is not a vpiScope or vpiModule\n"); + } // Use vpi_chk_error() here when it is implemented. return 0; } + + } else if (nm_path) { + // The name has a path, and no other scope handle was + // passed in. That suggests we are looking for "a.b.c" + // in the root scope. So convert "a.b" to a scope and + // start there to look for "c". + hand = find_scope(nm_path, NULL, 0); + nm_path = 0; + } else { - hand = find_scope(name, NULL, 0); + // Special case: scope==, meaning we are looking in + // the root, and there is no path to the name, i.e. the + // string is "c" instead of "top.c". Try to find "c" as + // a scope and return that. + hand = find_scope(nm_base, NULL, 0); } - if (hand) { - /* remove hierarchical portion of name */ - const char *nm = vpi_get_str(vpiFullName, hand); - int len = strlen(nm); - const char *cp = name + len; - if (!strncmp(name, nm, len) && *cp == '.') name = cp + 1; + if (hand == 0) { + if (vpi_trace) { + fprintf(vpi_trace, "vpi_handle_by_name: " + "Scope does not exist. Giving up.\n"); + } - /* Ok, time to burn some cycles */ - vpiHandle out = find_name(name, hand); - return out; + return 0; } - return 0; + // If there is a path part, then use it to find the + // scope. For example, if the full name is a.b.c, then + // the nm_path string is a.b and we search for that + // scope. If we find it, then set hand to that scope. + if (nm_path) { + vpiHandle tmp = find_scope(nm_path, hand, 0); + while (tmp == 0 && hand != 0) { + hand = vpi_handle(vpiScope, hand); + tmp = find_scope(nm_path, hand, 0); + } + hand = tmp; + } + + // Now we have the correct scope, look for the item. + vpiHandle out = find_name(nm_base, hand); + + if (vpi_trace) { + fprintf(vpi_trace, "vpi_handle_by_name: DONE\n"); + } + + return out; } From b687cc5f2180f2e587cdd6e7d0538d4a835f2abc Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 17 Apr 2014 16:25:18 -0700 Subject: [PATCH 023/245] Remove cppcheck warnings in tgt-vvp --- tgt-vvp/eval_expr.c | 2 -- tgt-vvp/eval_object.c | 4 ++-- tgt-vvp/stmt_assign.c | 4 ++-- tgt-vvp/vvp_process.c | 12 ++++++------ 4 files changed, 10 insertions(+), 12 deletions(-) diff --git a/tgt-vvp/eval_expr.c b/tgt-vvp/eval_expr.c index 67fb21df3..0b84bb96f 100644 --- a/tgt-vvp/eval_expr.c +++ b/tgt-vvp/eval_expr.c @@ -3623,8 +3623,6 @@ struct vector_info draw_eval_expr_wid(ivl_expr_t expr, unsigned wid, "%u at %s:%d\n", ivl_expr_file(expr), ivl_expr_lineno(expr), ivl_expr_type(expr), __FILE__, __LINE__); exit(1); - res.base = 0; - res.wid = 0; break; case IVL_EX_EVENT: fprintf(stderr, "%s:%u: vvp.tgt error: A named event is not " diff --git a/tgt-vvp/eval_object.c b/tgt-vvp/eval_object.c index e343fb3a1..9482c9cc6 100644 --- a/tgt-vvp/eval_object.c +++ b/tgt-vvp/eval_object.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -67,7 +67,7 @@ static int eval_darray_new(ivl_expr_t ex) } if (init_expr && ivl_expr_type(init_expr)==IVL_EX_ARRAY_PATTERN) { - int idx; + unsigned idx; struct vector_info rvec; unsigned wid; switch (ivl_type_base(element_type)) { diff --git a/tgt-vvp/stmt_assign.c b/tgt-vvp/stmt_assign.c index 2274e2ada..c05bd1fe1 100644 --- a/tgt-vvp/stmt_assign.c +++ b/tgt-vvp/stmt_assign.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2011-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -418,7 +418,7 @@ static void set_vec_to_lval_slice(ivl_lval_t lval, unsigned bit, unsigned wid) fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set); draw_eval_expr_into_integer(word_ix, 3); fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_set); - fprintf(vvp_out, " %%ix/mov 1, %u;\n", part_off_reg); + fprintf(vvp_out, " %%ix/mov 1, %d;\n", part_off_reg); clr_word(part_off_reg); } else { draw_eval_expr_into_integer(part_off_ex, 1); diff --git a/tgt-vvp/vvp_process.c b/tgt-vvp/vvp_process.c index ae5eb3629..59eeb7cbc 100644 --- a/tgt-vvp/vvp_process.c +++ b/tgt-vvp/vvp_process.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -57,7 +57,7 @@ static void assign_to_array_r_word(ivl_signal_t lsig, ivl_expr_t word_ix, /* This code is common to all the different types of array delays. */ if (number_is_immediate(word_ix, IMM_WID, 0) && !number_is_unknown(word_ix)) { - fprintf(vvp_out, " %%ix/load %u, %lu, 0; address\n", + fprintf(vvp_out, " %%ix/load %d, %lu, 0; address\n", word_ix_reg, get_number_immediate(word_ix)); } else { /* Calculate array word index into index register 3 */ @@ -74,7 +74,7 @@ static void assign_to_array_r_word(ivl_signal_t lsig, ivl_expr_t word_ix, /* Calculated delay... */ int delay_index = allocate_word(); draw_eval_expr_into_integer(dexp, delay_index); - fprintf(vvp_out, " %%ix/mov 3, %u;\n", word_ix_reg); + fprintf(vvp_out, " %%ix/mov 3, %d;\n", word_ix_reg); fprintf(vvp_out, " %%assign/ar/d v%p, %d;\n", lsig, delay_index); clr_word(word_ix_reg); @@ -152,7 +152,7 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix, /* If the index expression has XZ bits, skip the assign. */ fprintf(vvp_out, " %%jmp/1 t_%u, 4;\n", skip_assign); if (dexp == 0) { - fprintf(vvp_out, " %%ix/mov 3, %u;\n", word_ix_reg); + fprintf(vvp_out, " %%ix/mov 3, %d;\n", word_ix_reg); clr_word(word_ix_reg); } } else { @@ -171,8 +171,8 @@ static void assign_to_array_word(ivl_signal_t lsig, ivl_expr_t word_ix, fprintf(vvp_out, " %%ix/load 0, %u, 0; word width\n", width); if (dexp != 0) { - fprintf(vvp_out, " %%ix/mov 1, %u;\n", part_off_reg); - fprintf(vvp_out, " %%ix/mov 3, %u;\n", word_ix_reg); + fprintf(vvp_out, " %%ix/mov 1, %d;\n", part_off_reg); + fprintf(vvp_out, " %%ix/mov 3, %d;\n", word_ix_reg); fprintf(vvp_out, " %%assign/av/d v%p, %d, %u;\n", lsig, delay_index, bit); clr_word(part_off_reg); From e4476d544fc3bba30b8e286b135b9739dcaac8ca Mon Sep 17 00:00:00 2001 From: Cary R Date: Fri, 25 Apr 2014 13:49:11 -0700 Subject: [PATCH 024/245] Improve SDF warnings to separate name and scope Some of the SDF warnings were mixing some of the scope path with the instance name. These are now separated into just scope and instance name. There was also a place where vpi_get_str() was being called twice in a single print statement. This is illegal since vpi_get_str() uses a single buffer and multiple calls will overwrite the buffer. --- vpi/sys_sdf.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/vpi/sys_sdf.c b/vpi/sys_sdf.c index 506446912..2ee6c1fe1 100644 --- a/vpi/sys_sdf.c +++ b/vpi/sys_sdf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -101,7 +101,7 @@ void sdf_select_instance(const char*celltype, const char*cellinst) vpi_printf("SDF WARNING: %s:%d: ", vpi_get_str(vpiFile, sdf_callh), (int)vpi_get(vpiLineNo, sdf_callh)); vpi_printf("Unable to find %s in scope %s.\n", - cellinst, vpi_get_str(vpiFullName, scope)); + src, vpi_get_str(vpiFullName, scope)); return; } @@ -110,16 +110,16 @@ void sdf_select_instance(const char*celltype, const char*cellinst) vpi_printf("SDF WARNING: %s:%d: ", vpi_get_str(vpiFile, sdf_callh), (int)vpi_get(vpiLineNo, sdf_callh)); vpi_printf("Scope %s in %s is not a module.\n", - cellinst, vpi_get_str(vpiFullName, sdf_scope)); + src, vpi_get_str(vpiFullName, scope)); } /* The matching scope (a module) should have the expected type. */ if (strcmp(celltype,vpi_get_str(vpiDefName,sdf_cur_cell)) != 0) { vpi_printf("SDF WARNING: %s:%d: ", vpi_get_str(vpiFile, sdf_callh), (int)vpi_get(vpiLineNo, sdf_callh)); - vpi_printf("Module %s in %s is not a %s; it is an %s\n", cellinst, - vpi_get_str(vpiFullName, sdf_scope), celltype, - vpi_get_str(vpiDefName, sdf_cur_cell)); + vpi_printf("Module %s in %s is not a %s; it is a ", src, + vpi_get_str(vpiFullName, scope), celltype); + vpi_printf("%s\n", vpi_get_str(vpiDefName, sdf_cur_cell)); } } From 8c80193fc527f73ba01c10f4a79116b089b66cfe Mon Sep 17 00:00:00 2001 From: Cary R Date: Sat, 26 Apr 2014 20:55:21 -0700 Subject: [PATCH 025/245] Ignore SDF COND and CONDELSE delay definitions. --- vpi/Makefile.in | 2 +- vpi/sdf_lexor.lex | 65 ++++++++++++++++++++++++++--------------------- vpi/sdf_parse.y | 51 ++++++++++++++++++++++++++++++++----- 3 files changed, 82 insertions(+), 36 deletions(-) diff --git a/vpi/Makefile.in b/vpi/Makefile.in index a6b1c1416..ea04009b5 100644 --- a/vpi/Makefile.in +++ b/vpi/Makefile.in @@ -55,7 +55,7 @@ O = sys_table.o sys_convert.o sys_countdrivers.o sys_darray.o sys_deposit.o sys_ 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 \ - sys_priv.o sdf_lexor.o sdf_parse.o stringheap.o vams_simparam.o \ + sys_priv.o sdf_parse.o sdf_lexor.o stringheap.o vams_simparam.o \ table_mod.o table_mod_lexor.o table_mod_parse.o OPP = vcd_priv2.o diff --git a/vpi/sdf_lexor.lex b/vpi/sdf_lexor.lex index 523550db9..17d4eeaa1 100644 --- a/vpi/sdf_lexor.lex +++ b/vpi/sdf_lexor.lex @@ -5,7 +5,7 @@ %{ /* - * Copyright (c) 2007-2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 2007-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -107,6 +107,11 @@ static int yywrap(void) "===" { return K_CEQ; } "!==" { return K_CNE; } + /* Other operators. */ + +"&&" { return K_LAND; } +"||" { return K_LOR; } + /* The HCHAR (hierarchy separator) is set by the SDF file itself. We recognize here the HCHAR. */ [./] { @@ -124,34 +129,36 @@ static struct { const char*name; int code; } keywords[] = { - { "ABSOLUTE", K_ABSOLUTE }, - { "CELL", K_CELL }, - { "CELLTYPE", K_CELLTYPE }, - { "DATE", K_DATE }, - { "DELAY", K_DELAY }, - { "DELAYFILE", K_DELAYFILE }, - { "DESIGN", K_DESIGN }, - { "DIVIDER", K_DIVIDER }, - { "HOLD", K_HOLD }, - { "INCREMENT", K_INCREMENT }, - { "INTERCONNECT",K_INTERCONNECT }, - { "INSTANCE", K_INSTANCE }, - { "IOPATH", K_IOPATH }, - { "PROCESS", K_PROCESS }, - { "PROGRAM", K_PROGRAM }, - { "RECREM", K_RECREM }, - { "RECOVERY", K_RECOVERY }, - { "REMOVAL", K_REMOVAL }, - { "SDFVERSION", K_SDFVERSION }, - { "SETUP", K_SETUP }, - { "SETUPHOLD", K_SETUPHOLD }, - { "TEMPERATURE",K_TEMPERATURE }, - { "TIMESCALE", K_TIMESCALE }, - { "TIMINGCHECK",K_TIMINGCHECK }, - { "VENDOR", K_VENDOR }, - { "VERSION", K_VERSION }, - { "VOLTAGE", K_VOLTAGE }, - { "WIDTH", K_WIDTH }, + { "ABSOLUTE", K_ABSOLUTE }, + { "CELL", K_CELL }, + { "CELLTYPE", K_CELLTYPE }, + { "DATE", K_DATE }, + { "COND", K_COND }, + { "CONDELSE", K_CONDELSE }, + { "DELAY", K_DELAY }, + { "DELAYFILE", K_DELAYFILE }, + { "DESIGN", K_DESIGN }, + { "DIVIDER", K_DIVIDER }, + { "HOLD", K_HOLD }, + { "INCREMENT", K_INCREMENT }, + { "INTERCONNECT", K_INTERCONNECT }, + { "INSTANCE", K_INSTANCE }, + { "IOPATH", K_IOPATH }, + { "PROCESS", K_PROCESS }, + { "PROGRAM", K_PROGRAM }, + { "RECREM", K_RECREM }, + { "RECOVERY", K_RECOVERY }, + { "REMOVAL", K_REMOVAL }, + { "SDFVERSION", K_SDFVERSION }, + { "SETUP", K_SETUP }, + { "SETUPHOLD", K_SETUPHOLD }, + { "TEMPERATURE", K_TEMPERATURE }, + { "TIMESCALE", K_TIMESCALE }, + { "TIMINGCHECK", K_TIMINGCHECK }, + { "VENDOR", K_VENDOR }, + { "VERSION", K_VERSION }, + { "VOLTAGE", K_VOLTAGE }, + { "WIDTH", K_WIDTH }, { 0, IDENTIFIER } }; diff --git a/vpi/sdf_parse.y b/vpi/sdf_parse.y index 793ad120c..e145abef6 100644 --- a/vpi/sdf_parse.y +++ b/vpi/sdf_parse.y @@ -1,7 +1,7 @@ %{ /* - * Copyright (c) 1998-2010 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -44,13 +44,15 @@ char sdf_use_hchar = '.'; struct sdf_delval_list_s delval_list; }; -%token K_ABSOLUTE K_CELL K_CELLTYPE K_COND K_DATE K_DELAYFILE K_DELAY K_DESIGN -%token K_DIVIDER K_HOLD K_INCREMENT K_INSTANCE K_INTERCONNECT K_IOPATH -%token K_NEGEDGE K_POSEDGE K_PROCESS K_PROGRAM K_RECREM K_RECOVERY -%token K_REMOVAL K_SDFVERSION K_SETUP K_SETUPHOLD K_TEMPERATURE -%token K_TIMESCALE K_TIMINGCHECK K_VENDOR K_VERSION K_VOLTAGE K_WIDTH +%token K_ABSOLUTE K_CELL K_CELLTYPE K_COND K_CONDELSE K_DATE K_DELAYFILE +%token K_DELAY K_DESIGN K_DIVIDER K_HOLD K_INCREMENT K_INSTANCE +%token K_INTERCONNECT K_IOPATH K_NEGEDGE K_POSEDGE K_PROCESS K_PROGRAM +%token K_RECREM K_RECOVERY K_REMOVAL K_SDFVERSION K_SETUP K_SETUPHOLD +%token K_TEMPERATURE K_TIMESCALE K_TIMINGCHECK K_VENDOR K_VERSION +%token K_VOLTAGE K_WIDTH %token K_01 K_10 K_0Z K_Z1 K_1Z K_Z0 %token K_EQ K_NE K_CEQ K_CNE K_LOGICAL_ONE K_LOGICAL_ZERO +%token K_LAND K_LOR %token HCHAR %token QSTRING IDENTIFIER @@ -70,6 +72,10 @@ char sdf_use_hchar = '.'; %type delval_list +%left K_LOR +%left K_LAND +%left K_EQ K_NE K_CEQ K_CNE + %% source_file @@ -261,6 +267,26 @@ del_def | '(' K_IOPATH error ')' { vpi_printf("%s:%d: SDF ERROR: Invalid/malformed IOPATH\n", sdf_parse_path, @2.first_line); } + | '(' K_COND conditional_port_expr + '(' K_IOPATH port_spec port_instance delval_list ')' ')' + { + /* Skip conditional path back annotation for now. */ + } + | '(' K_COND QSTRING conditional_port_expr + '(' K_IOPATH port_spec port_instance delval_list ')' ')' + { + /* Skip conditional path back annotation for now. */ + } + | '(' K_COND error ')' + { vpi_printf("%s:%d: SDF ERROR: Invalid/malformed COND\n", + sdf_parse_path, @2.first_line); } + | '(' K_CONDELSE '(' K_IOPATH port_spec port_instance delval_list ')' ')' + { + /* Skip ifnone back annotation for now. */ + } + | '(' K_CONDELSE error ')' + { vpi_printf("%s:%d: SDF ERROR: Invalid/malformed CONDELSE\n", + sdf_parse_path, @2.first_line); } /* | '(' K_INTERCONNECT port_instance port_instance delval_list ')' */ | '(' K_INTERCONNECT port_interconnect port_interconnect delval_list ')' { if (sdf_flag_warning) vpi_printf("%s:%d: SDF WARNING: " @@ -322,6 +348,19 @@ timing_check_condition | port_interconnect equality_operator scalar_constant ; + /* This is not complete! */ +conditional_port_expr + : port + | scalar_constant + | '(' conditional_port_expr ')' + | conditional_port_expr K_LAND conditional_port_expr + | conditional_port_expr K_LOR conditional_port_expr + | conditional_port_expr K_EQ conditional_port_expr + | conditional_port_expr K_NE conditional_port_expr + | conditional_port_expr K_CEQ conditional_port_expr + | conditional_port_expr K_CNE conditional_port_expr + ; + equality_operator : K_EQ | K_NE From d6405f86d45194557d9e8686535c9ae4a91ccf37 Mon Sep 17 00:00:00 2001 From: Cary R Date: Sat, 26 Apr 2014 20:58:29 -0700 Subject: [PATCH 026/245] Fix space issue --- vpi/sdf_parse.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vpi/sdf_parse.y b/vpi/sdf_parse.y index e145abef6..bbac4f4c7 100644 --- a/vpi/sdf_parse.y +++ b/vpi/sdf_parse.y @@ -272,7 +272,7 @@ del_def { /* Skip conditional path back annotation for now. */ } - | '(' K_COND QSTRING conditional_port_expr + | '(' K_COND QSTRING conditional_port_expr '(' K_IOPATH port_spec port_instance delval_list ')' ')' { /* Skip conditional path back annotation for now. */ From a1d65336d25193db59eebefb2e80f117a71a1dda Mon Sep 17 00:00:00 2001 From: Cary R Date: Sun, 27 Apr 2014 17:25:47 -0700 Subject: [PATCH 027/245] Add SDF warning message and release COND and CONDELSE memory --- vpi/sdf_parse.y | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/vpi/sdf_parse.y b/vpi/sdf_parse.y index bbac4f4c7..77e3f6e75 100644 --- a/vpi/sdf_parse.y +++ b/vpi/sdf_parse.y @@ -269,20 +269,29 @@ del_def sdf_parse_path, @2.first_line); } | '(' K_COND conditional_port_expr '(' K_IOPATH port_spec port_instance delval_list ')' ')' - { - /* Skip conditional path back annotation for now. */ + { if (sdf_flag_warning) vpi_printf("%s:%d: SDF WARNING: " + "COND not supported.\n", + sdf_parse_path, @2.first_line); + free($6.string_val); + free($7); } | '(' K_COND QSTRING conditional_port_expr '(' K_IOPATH port_spec port_instance delval_list ')' ')' - { - /* Skip conditional path back annotation for now. */ + { if (sdf_flag_warning) vpi_printf("%s:%d: SDF WARNING: " + "COND not supported.\n", + sdf_parse_path, @2.first_line); + free($7.string_val); + free($8); } | '(' K_COND error ')' { vpi_printf("%s:%d: SDF ERROR: Invalid/malformed COND\n", sdf_parse_path, @2.first_line); } | '(' K_CONDELSE '(' K_IOPATH port_spec port_instance delval_list ')' ')' - { - /* Skip ifnone back annotation for now. */ + { if (sdf_flag_warning) vpi_printf("%s:%d: SDF WARNING: " + "CONDELSE not supported.\n", + sdf_parse_path, @2.first_line); + free($5.string_val); + free($6); } | '(' K_CONDELSE error ')' { vpi_printf("%s:%d: SDF ERROR: Invalid/malformed CONDELSE\n", From 650cedb5161d7e3769c919623c9ccef46d2d039e Mon Sep 17 00:00:00 2001 From: Cary R Date: Sun, 27 Apr 2014 17:56:48 -0700 Subject: [PATCH 028/245] More SDF memory cleanup fixes --- vpi/sdf_parse.y | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/vpi/sdf_parse.y b/vpi/sdf_parse.y index 77e3f6e75..0cb7b2045 100644 --- a/vpi/sdf_parse.y +++ b/vpi/sdf_parse.y @@ -280,6 +280,7 @@ del_def { if (sdf_flag_warning) vpi_printf("%s:%d: SDF WARNING: " "COND not supported.\n", sdf_parse_path, @2.first_line); + free($3); free($7.string_val); free($8); } @@ -327,11 +328,17 @@ tchk_def port_tchk : port_instance + { free($1); } /* This must only be an edge. For now we just accept everything. */ | cond_edge_start port_instance ')' + { free($2); } /* These must only be a cond. For now we just accept everything. */ | cond_edge_start timing_check_condition port_spec ')' + { free($3.string_val); } | cond_edge_start QSTRING timing_check_condition port_spec ')' + { free($2); + free($4.string_val); + } ; cond_edge_start @@ -352,14 +359,19 @@ cond_edge_identifier timing_check_condition : port_interconnect + { free($1); } | '~' port_interconnect + { free($2); } | '!' port_interconnect + { free($2); } | port_interconnect equality_operator scalar_constant + { free($1); } ; /* This is not complete! */ conditional_port_expr : port + { free($1); } | scalar_constant | '(' conditional_port_expr ')' | conditional_port_expr K_LAND conditional_port_expr From be8df11217c8ec059d1da082a8ed7f99305a22bc Mon Sep 17 00:00:00 2001 From: Cary R Date: Tue, 29 Apr 2014 14:20:08 -0700 Subject: [PATCH 029/245] Update fstapi.c to latest from GTKWave --- vpi/cppcheck.sup | 54 ++++++++--------- vpi/fstapi.c | 149 +++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 152 insertions(+), 51 deletions(-) diff --git a/vpi/cppcheck.sup b/vpi/cppcheck.sup index 833f1b7dc..30017eec4 100644 --- a/vpi/cppcheck.sup +++ b/vpi/cppcheck.sup @@ -3,33 +3,33 @@ // problems will not be fixed. // fstapi.c from GTKWave -obsoleteFunctionsasctime:fstapi.c:840 -obsoleteFunctionsalloca:fstapi.c:2225 -unreadVariable:fstapi.c:1569 -variableScope:fstapi.c:581 -variableScope:fstapi.c:1301 -variableScope:fstapi.c:1900 -variableScope:fstapi.c:2029 -variableScope:fstapi.c:2454 -variableScope:fstapi.c:2646 -variableScope:fstapi.c:2805 -variableScope:fstapi.c:2806 -variableScope:fstapi.c:3521 -variableScope:fstapi.c:3692 -variableScope:fstapi.c:4135 -variableScope:fstapi.c:4144 -variableScope:fstapi.c:4676 -variableScope:fstapi.c:4679 -variableScope:fstapi.c:5177 -variableScope:fstapi.c:5178 -variableScope:fstapi.c:5334 -variableScope:fstapi.c:5392 -variableScope:fstapi.c:5705 -variableScope:fstapi.c:5708 -variableScope:fstapi.c:5944 -variableScope:fstapi.c:6049 -variableScope:fstapi.c:6050 -variableScope:fstapi.c:6081 +obsoleteFunctionsasctime:fstapi.c:928 +obsoleteFunctionsalloca:fstapi.c:2316 +unreadVariable:fstapi.c:1660 +variableScope:fstapi.c:664 +variableScope:fstapi.c:1392 +variableScope:fstapi.c:1991 +variableScope:fstapi.c:2120 +variableScope:fstapi.c:2545 +variableScope:fstapi.c:2737 +variableScope:fstapi.c:2896 +variableScope:fstapi.c:2897 +variableScope:fstapi.c:3615 +variableScope:fstapi.c:3791 +variableScope:fstapi.c:4234 +variableScope:fstapi.c:4243 +variableScope:fstapi.c:4777 +variableScope:fstapi.c:4780 +variableScope:fstapi.c:5278 +variableScope:fstapi.c:5279 +variableScope:fstapi.c:5435 +variableScope:fstapi.c:5493 +variableScope:fstapi.c:5806 +variableScope:fstapi.c:5809 +variableScope:fstapi.c:6045 +variableScope:fstapi.c:6150 +variableScope:fstapi.c:6151 +variableScope:fstapi.c:6182 // lxt2_write.c from GTKWave obsoleteFunctionsalloca:lxt2_write.c:1813 diff --git a/vpi/fstapi.c b/vpi/fstapi.c index 7f1ee1cd7..ae158032f 100644 --- a/vpi/fstapi.c +++ b/vpi/fstapi.c @@ -52,6 +52,10 @@ #include #endif +#ifdef __MINGW32__ +#include +#endif + #if HAVE_ALLOCA_H #include #elif defined(__GNUC__) @@ -171,6 +175,85 @@ return(fopen(nam, mode)); } +/* + * system-specific temp file handling + */ +#ifdef __MINGW32__ + +static FILE* tmpfile_open(char **nam) +{ +char *fname = NULL; +TCHAR szTempFileName[MAX_PATH]; +TCHAR lpTempPathBuffer[MAX_PATH]; +DWORD dwRetVal = 0; +UINT uRetVal = 0; +FILE *fh = NULL; + +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__); + exit(255); + } + else + { + uRetVal = GetTempFileName(lpTempPathBuffer, TEXT("FSTW"), 0, szTempFileName); + if (uRetVal == 0) + { + fprintf(stderr, "GetTempFileName() failed in "__FILE__" line %d, exiting.\n", __LINE__); + exit(255); + } + else + { + fname = strdup(szTempFileName); + } + } + + if(fname) + { + *nam = fname; + fh = unlink_fopen(fname, "w+b"); + } + } + +return(fh); +} + +#else + +static FILE* tmpfile_open(char **nam) +{ +FILE *f = tmpfile(); /* replace with mkstemp() + fopen(), etc if this is not good enough */ +if(nam) { *nam = NULL; } +return(f); +} + +#endif + + +static void tmpfile_close(FILE **f, char **nam) +{ +if(f) + { + if(*f) { fclose(*f); *f = NULL; } + } + +if(nam) + { + if(*nam) + { + unlink(*nam); + free(*nam); + *nam = NULL; + } + } +} + +/*****************************************/ + + /* * to remove warn_unused_result compile time messages * (in the future there needs to be results checking) @@ -702,6 +785,11 @@ Pvoid_t path_array; uint32_t path_array_count; unsigned fseek_failed : 1; + +char *geom_handle_nam; +char *valpos_handle_nam; +char *curval_handle_nam; +char *tchn_handle_nam; }; @@ -1018,7 +1106,8 @@ struct fstWriterContext *xc = calloc(1, sizeof(struct fstWriterContext)); xc->compress_hier = use_compressed_hier; fstDetermineBreakSize(xc); -if((!nam)||(!(xc->handle=unlink_fopen(nam, "w+b")))) +if((!nam)|| + (!(xc->handle=unlink_fopen(nam, "w+b")))) { free(xc); xc=NULL; @@ -1032,14 +1121,13 @@ if((!nam)||(!(xc->handle=unlink_fopen(nam, "w+b")))) strcpy(hf + flen, ".hier"); xc->hier_handle = unlink_fopen(hf, "w+b"); - xc->geom_handle = tmpfile(); /* .geom */ - xc->valpos_handle = tmpfile(); /* .offs */ - xc->curval_handle = tmpfile(); /* .bits */ - xc->tchn_handle = tmpfile(); /* .tchn */ + xc->geom_handle = tmpfile_open(&xc->geom_handle_nam); /* .geom */ + xc->valpos_handle = tmpfile_open(&xc->valpos_handle_nam); /* .offs */ + 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); - free(hf); if(xc->hier_handle && xc->geom_handle && xc->valpos_handle && xc->curval_handle && xc->vchg_mem && xc->tchn_handle) { xc->filename = strdup(nam); @@ -1055,15 +1143,18 @@ if((!nam)||(!(xc->handle=unlink_fopen(nam, "w+b")))) } else { - if(xc->hier_handle) fclose(xc->hier_handle); - if(xc->geom_handle) fclose(xc->geom_handle); - if(xc->valpos_handle) fclose(xc->valpos_handle); - if(xc->curval_handle) fclose(xc->curval_handle); - if(xc->tchn_handle) fclose(xc->tchn_handle); + fclose(xc->handle); + if(xc->hier_handle) { fclose(xc->hier_handle); unlink(hf); } + tmpfile_close(&xc->geom_handle, &xc->geom_handle_nam); + tmpfile_close(&xc->valpos_handle, &xc->valpos_handle_nam); + tmpfile_close(&xc->curval_handle, &xc->curval_handle_nam); + tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam); free(xc->vchg_mem); free(xc); xc=NULL; } + + free(hf); } return(xc); @@ -1688,7 +1779,7 @@ free(xc->curval_mem); #endif free(xc->valpos_mem); free(xc->vchg_mem); -fclose(xc->tchn_handle); +tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam); free(xc); return(NULL); @@ -1731,7 +1822,7 @@ if(xc->parallel_enabled) } xc->tchn_cnt = xc->tchn_idx = 0; - xc->tchn_handle = tmpfile(); + xc->tchn_handle = tmpfile_open(&xc->tchn_handle_nam); /* child thread will deallocate file/name */ fstWriterFseeko(xc, xc->tchn_handle, 0, SEEK_SET); fstFtruncate(fileno(xc->tchn_handle), 0); @@ -2003,11 +2094,11 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) fstWriterUint64(xc->handle, xc->secnum); fflush(xc->handle); - if(xc->tchn_handle) { fclose(xc->tchn_handle); xc->tchn_handle = NULL; } + tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam); free(xc->vchg_mem); xc->vchg_mem = NULL; - if(xc->curval_handle) { fclose(xc->curval_handle); xc->curval_handle = NULL; } - if(xc->valpos_handle) { fclose(xc->valpos_handle); xc->valpos_handle = NULL; } - if(xc->geom_handle) { fclose(xc->geom_handle); xc->geom_handle = NULL; } + tmpfile_close(&xc->curval_handle, &xc->curval_handle_nam); + tmpfile_close(&xc->valpos_handle, &xc->valpos_handle_nam); + tmpfile_close(&xc->geom_handle, &xc->geom_handle_nam); if(xc->hier_handle) { fclose(xc->hier_handle); xc->hier_handle = NULL; } if(xc->handle) { @@ -3016,6 +3107,9 @@ int writex_pos; int writex_fd; unsigned char writex_buf[FST_WRITEX_MAX]; #endif + +char *f_nam; +char *fh_nam; }; @@ -3535,14 +3629,16 @@ if(!xc->fh) sprintf(fnam, "%s.hier_%d_%p", xc->filename, getpid(), (void *)xc); fstReaderFseeko(xc, xc->f, xc->hier_pos, SEEK_SET); uclen = fstReaderUint64(xc->f); +#ifndef __MINGW32__ fflush(xc->f); - +#endif if(htyp == FST_BL_HIER) { fstReaderFseeko(xc, xc->f, xc->hier_pos, SEEK_SET); uclen = fstReaderUint64(xc->f); +#ifndef __MINGW32__ fflush(xc->f); - +#endif zfd = dup(fileno(xc->f)); zhandle = gzdopen(zfd, "rb"); if(!zhandle) @@ -3559,7 +3655,9 @@ if(!xc->fh) fstReaderFseeko(xc, xc->f, xc->hier_pos - 8, SEEK_SET); /* get section len */ clen = fstReaderUint64(xc->f) - 16; uclen = fstReaderUint64(xc->f); +#ifndef __MINGW32__ fflush(xc->f); +#endif } #ifndef __MINGW32__ @@ -3567,10 +3665,11 @@ if(!xc->fh) if(!xc->fh) #endif { - xc->fh = tmpfile(); + xc->fh = tmpfile_open(&xc->fh_nam); free(fnam); fnam = NULL; if(!xc->fh) { + tmpfile_close(&xc->fh, &xc->fh_nam); free(mem); return(0); } @@ -4158,9 +4257,9 @@ if(sectype == FST_BL_ZWRAPPER) fcomp = fopen(hf, "w+b"); if(!fcomp) { - fcomp = tmpfile(); + fcomp = tmpfile_open(&xc->f_nam); free(hf); hf = NULL; - if(!fcomp) return(0); + if(!fcomp) { tmpfile_close(&fcomp, &xc->f_nam); return(0); } } #if defined(FST_MACOSX) @@ -4179,7 +4278,9 @@ if(sectype == FST_BL_ZWRAPPER) #endif fstReaderFseeko(xc, xc->f, 1+8+8, SEEK_SET); +#ifndef __MINGW32__ fflush(xc->f); +#endif zfd = dup(fileno(xc->f)); zhandle = gzdopen(zfd, "rb"); @@ -4528,12 +4629,12 @@ if(xc) if(xc->fh) { - fclose(xc->fh); xc->fh = NULL; + tmpfile_close(&xc->fh, &xc->fh_nam); } if(xc->f) { - fclose(xc->f); xc->f = NULL; + tmpfile_close(&xc->f, &xc->f_nam); if(xc->filename_unpacked) { unlink(xc->filename_unpacked); From c32610d13521ba4251ccb24e3d0a530eb968d93e Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sun, 4 May 2014 20:39:05 +0100 Subject: [PATCH 030/245] Further fix for GitHub issue 19 : incorrect handling of large shift values. Apply the same fix to vvp as was applied to the compiler. See commit 065c48527c462a1d1cc06717f762616d0fab6023 for details. --- vvp/vvp_net.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index a9df069a2..aaf8f0203 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -1707,12 +1707,13 @@ template bool vector4_to_value(const vvp_vector4_t&vec, T&val) T msk = 1; unsigned size = vec.size(); - if (size > 8*sizeof(val)) size = 8*sizeof(val); for (unsigned idx = 0 ; idx < size ; idx += 1) { switch (vec.value(idx)) { case BIT4_0: break; case BIT4_1: + // On overflow, return the maximum value of type T + if (msk == 0) return ~msk; res |= msk; break; default: From 17be8e8c7c962c3af6f98c9b30f390a12e74ac1a Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Wed, 16 Apr 2014 21:06:01 -0700 Subject: [PATCH 031/245] Handle special case of if inside of block. If statements within blocks can confuse the synthesizer when there are outputs that are assigned ahead of the if statement. This patch handles that case. --- netlist.h | 5 +++ synth2.cc | 129 +++++++++++++++++++++++++++++++++++++----------------- 2 files changed, 93 insertions(+), 41 deletions(-) diff --git a/netlist.h b/netlist.h index 4f49bf9b2..3242e26c0 100644 --- a/netlist.h +++ b/netlist.h @@ -2542,6 +2542,11 @@ class NetProc : public virtual LineInfo { // Recursively checks to see if there is delay in this element. virtual DelayType delay_type() const; + protected: + bool synth_async_block_substatement_(Design*des, NetScope*scope, + NexusSet&nex_map, + NetBus&accumulated_nex_out, + NetProc*substmt); private: friend class NetBlock; NetProc*next_; diff --git a/synth2.cc b/synth2.cc index b6dd772cf..208ecf168 100644 --- a/synth2.cc +++ b/synth2.cc @@ -93,8 +93,10 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, << ", nex_out.pin_count()==" << nex_out.pin_count() << endl; } - /* For now, assume there is exactly one output. */ - ivl_assert(*this, nex_out.pin_count() == 1); + ivl_assert(*this, nex_out.pin_count()==1); + ivl_assert(*this, rsig->pin_count()==1); + connect(nex_out.pin(0), rsig->pin(0)); + #if 0 if (lval_->lwidth() != lsig->vector_width()) { ivl_assert(*this, lval_->lwidth() < lsig->vector_width()); @@ -121,7 +123,6 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, rsig = tmp; } #endif - connect(nex_out.pin(0), rsig->pin(0)); /* This lval_ represents a reg that is a WIRE in the synthesized results. This function signals the destructor @@ -133,6 +134,57 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, return true; } +bool NetProc::synth_async_block_substatement_(Design*des, NetScope*scope, + NexusSet&nex_map, + NetBus&accumulated_nex_out, + NetProc*substmt) +{ + // Create a temporary map of the output only from this statement. + NexusSet tmp_map; + substmt->nex_output(tmp_map); + if (debug_synth2) { + cerr << get_fileline() << ": NetProc::synth_async_block_substatement_: " + << "tmp_map.size()==" << tmp_map.size() + << " for statement at " << substmt->get_fileline() + << endl; + } + + /* Create also a temporary NetBus to collect the + output from the synthesis. */ + NetBus tmp_out (scope, tmp_map.size()); + + // Map (and move) the accumulated_nex_out for this block + // to the version that we can pass to the next + // statement. We will move the result back later. + NetBus accumulated_tmp_out (scope, tmp_map.size()); + + for (unsigned idx = 0 ; idx < accumulated_nex_out.pin_count() ; idx += 1) { + unsigned ptr = tmp_map.find_nexus(nex_map[idx]); + if (ptr >= tmp_map.size()) + continue; + + connect(accumulated_tmp_out.pin(ptr), accumulated_nex_out.pin(idx)); + accumulated_nex_out.pin(idx).unlink(); + } + + bool ok_flag = substmt->synth_async(des, scope, tmp_map, tmp_out, accumulated_tmp_out); + + if (ok_flag == false) + return false; + + // Now map the output from the substatement back to the + // accumulated_nex_out for this block. Look for the + // nex_map pin that is linked to the tmp_map.pin(idx) + // pin, and link that to the tmp_out.pin(idx) output link. + for (unsigned idx = 0 ; idx < tmp_out.pin_count() ; idx += 1) { + unsigned ptr = nex_map.find_nexus(tmp_map[idx]); + ivl_assert(*this, ptr < accumulated_nex_out.pin_count()); + connect(accumulated_nex_out.pin(ptr), tmp_out.pin(idx)); + } + + return true; +} + /* * Sequential blocks are translated to asynchronous logic by * translating each statement of the block, in order, into gates. The @@ -152,45 +204,13 @@ bool NetBlock::synth_async(Design*des, NetScope*scope, do { cur = cur->next_; - /* Create a temporary map of the output only from this - statement. */ - NexusSet tmp_map; - cur->nex_output(tmp_map); - - /* Create also a temporary NetBus to collect the - output from the synthesis. */ - NetBus tmp_out (scope, tmp_map.size()); - - // Map (and move) the accumulated_nex_out for this block - // to the version that we can pass to the next - // statement. We will move the result back later. - NetBus accumulated_tmp_out (scope, tmp_map.size()); - - for (unsigned idx = 0 ; idx < accumulated_nex_out.pin_count() ; idx += 1) { - unsigned ptr = tmp_map.find_nexus(nex_map[idx]); - if (ptr >= tmp_map.size()) - continue; - - connect(accumulated_tmp_out.pin(ptr), accumulated_nex_out.pin(idx)); - accumulated_nex_out.pin(idx).unlink(); - } - - bool ok_flag = cur->synth_async(des, scope, tmp_map, tmp_out, accumulated_tmp_out); - + bool ok_flag = synth_async_block_substatement_(des, scope, nex_map, + accumulated_nex_out, + cur); flag = flag && ok_flag; if (ok_flag == false) continue; - // Now map the output from the substatement back to the - // accumulated_nex_out for this block. Look for the - // nex_map pin that is linked to the tmp_map.pin(idx) - // pin, and link that to the tmp_out.pin(idx) output link. - for (unsigned idx = 0 ; idx < tmp_out.pin_count() ; idx += 1) { - unsigned ptr = nex_map.find_nexus(tmp_map[idx]); - ivl_assert(*this, ptr < accumulated_nex_out.pin_count()); - connect(accumulated_nex_out.pin(ptr), tmp_out.pin(idx)); - } - } while (cur != last_); // The output from the block is now the accumulated outputs. @@ -386,6 +406,12 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, NetNet*ssig = expr_->synthesize(des, scope, expr_); assert(ssig); + if (debug_synth2) { + cerr << get_fileline() << ": NetCondit::synth_async: " + << "Synthesize if clause at " << if_->get_fileline() + << endl; + } + bool flag; NetBus asig(scope, nex_out.pin_count()); NetBus atmp(scope, nex_out.pin_count()); @@ -402,16 +428,29 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, connect(bsig.pin(idx), accumulated_nex_out.pin(idx)); accumulated_nex_out.pin(idx).unlink(); } + } else { - flag = else_->synth_async(des, scope, nex_map, bsig, btmp); + + if (debug_synth2) { + cerr << get_fileline() << ": NetCondit::synth_async: " + << "Synthesize else clause at " << else_->get_fileline() + << endl; + } + + flag = synth_async_block_substatement_(des, scope, nex_map, accumulated_nex_out, else_); if (!flag) { return false; } + for (unsigned idx = 0 ; idx < nex_out.pin_count() ; idx += 1) { + connect(bsig.pin(idx), accumulated_nex_out.pin(idx)); + accumulated_nex_out.pin(idx).unlink(); + } } ivl_assert(*this, nex_out.pin_count()==asig.pin_count()); ivl_assert(*this, nex_out.pin_count()==bsig.pin_count()); + bool rc_flag = true; for (unsigned idx = 0 ; idx < nex_out.pin_count() ; idx += 1) { ivl_assert(*this, asig.pin(idx).nexus()->pick_any_net()); ivl_assert(*this, bsig.pin(idx).nexus()->pick_any_net()); @@ -422,7 +461,15 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, } unsigned mux_width = asig.pin(idx).nexus()->vector_width(); ivl_assert(*this, mux_width != 0); - ivl_assert(*this, mux_width==bsig.pin(idx).nexus()->vector_width()); + if (mux_width != bsig.pin(idx).nexus()->vector_width()) { + cerr << get_fileline() << ": internal error: " + << "NetCondit::synth_async: " + << "Mux input sizes do not match." + << "A size=" << mux_width + << ", B size=" << bsig.pin(idx).nexus()->vector_width() + << endl; + rc_flag = false; + } NetMux*mux = new NetMux(scope, scope->local_symbol(), mux_width, 2, 1); @@ -448,7 +495,7 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, des->add_node(mux); } - return true; + return rc_flag; } bool NetEvWait::synth_async(Design*des, NetScope*scope, From 8d9f3a0920067b00c05ef303e73fea3c3d5e4e83 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 20 Apr 2014 08:24:28 -0700 Subject: [PATCH 032/245] Fix crashes scanning links. Signals are collected in a link map that uses the Link class so that it doesn't need to save Nexus objects. But naked uses of Link don't set the node_ and pin_zero_ members. So initialize them to zero so that Nexus scanners can skip these naked Links. --- net_link.cc | 2 ++ synth2.cc | 36 ++++++++++++++++++++++++++++-------- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/net_link.cc b/net_link.cc index 7552a9693..74e7f8790 100644 --- a/net_link.cc +++ b/net_link.cc @@ -105,6 +105,8 @@ Link::Link() : dir_(PASSIVE), drive0_(IVL_DR_STRONG), drive1_(IVL_DR_STRONG), next_(0), nexus_(0) { + node_ = 0; + pin_zero_ = true; } Link::~Link() diff --git a/synth2.cc b/synth2.cc index 208ecf168..9ded3d897 100644 --- a/synth2.cc +++ b/synth2.cc @@ -44,6 +44,11 @@ bool NetProc::synth_sync(Design*des, NetScope*scope, des->errors += 1; } + if (debug_synth2) { + cerr << get_fileline() << ": NetProc::synth_sync: " + << "This statement is an async input to a sync process." << endl; + } + /* Synthesize the input to the DFF. */ NetBus accumulated_nex_out (scope, nex_out.pin_count()); return synth_async(des, scope, nex_map, nex_out, accumulated_nex_out); @@ -571,6 +576,11 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NexusSet&nex_map, NetBus&nex_out, const vector&events_in) { + if (debug_synth2) { + cerr << get_fileline() << ": NetBlock::synth_sync: " + << "Examine this block for synchronous logic." << endl; + } + bool flag = true; NetProc*cur = last_; @@ -581,11 +591,6 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, NexusSet tmp_set; cur->nex_output(tmp_set); - /* NOTE: After this point, tmp_set should not be used as - the various functions I call do a lot of connecting, - and the nexa in the tmp_set may get realloced. Use - the tmp_map instead. */ - /* Create also a temporary net_out to collect the output. The tmp1 and tmp2 map and out sets together are used to collect the outputs from the substatement @@ -616,6 +621,11 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, } while (cur != last_); + if (debug_synth2) { + cerr << get_fileline() << ": NetBlock::synth_sync: " + << "Done Examining this block for synchronous logic." << endl; + } + return flag; } @@ -840,6 +850,11 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, NexusSet&nex_map, NetBus&nex_out, const vector&events_in) { + if (debug_synth2) { + cerr << get_fileline() << ": NetEvWait::synth_sync: " + << "Synchronous process an event statement." << endl; + } + if (events_in.size() > 0) { cerr << get_fileline() << ": error: Events are unaccounted" << " for in process synthesis." << endl; @@ -894,6 +909,11 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, return false; } + if (debug_synth2) { + cerr << get_fileline() << ": NetEvWait::synth_sync: " + << "Found and synthesized the FF clock." << endl; + } + connect(ff_clk->pin(0), pclk->pin(0)); if (pclk->edge() == NetEvProbe::NEGEDGE) { perm_string polarity = perm_string::literal("Clock:LPM_Polarity"); @@ -921,7 +941,7 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, bool NetProcTop::synth_sync(Design*des) { if (debug_synth2) { - cerr << get_fileline() << ": debug: " + cerr << get_fileline() << ": NetProcTop::synth_sync: " << "Process is apparently synchronous. Making NetFFs." << endl; } @@ -1033,7 +1053,7 @@ void synth2_f::process(Design*des, NetProcTop*top) if (top->scope()->attribute(perm_string::literal("ivl_synthesis_cell")).len() > 0) return; - if (top->is_synchronous()) do { + if (top->is_synchronous()) { bool flag = top->synth_sync(des); if (! flag) { cerr << top->get_fileline() << ": error: " @@ -1043,7 +1063,7 @@ void synth2_f::process(Design*des, NetProcTop*top) } des->delete_process(top); return; - } while (0); + } if (! top->is_asynchronous()) { bool synth_error_flag = false; From 5893d13ea39d6f52153f025333829da8081d603a Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 20 Apr 2014 08:58:38 -0700 Subject: [PATCH 033/245] Don't connect NetFF CE pin if it is not needed When the clock enable is not generated, don't try to hook it up then detach it. That will make a mess that needs clean up. Instead, leave unused ce pins (Enable) unconnected. --- synth2.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/synth2.cc b/synth2.cc index 9ded3d897..ad3c7ddc3 100644 --- a/synth2.cc +++ b/synth2.cc @@ -1009,7 +1009,8 @@ bool NetProcTop::synth_sync(Design*des) connect(tmp->pin(0), ff2->pin_Data()); connect(clock->pin(0), ff2->pin_Clock()); - connect(ce->pin(0), ff2->pin_Enable()); + if (ce->is_linked()) + connect(ce->pin(0), ff2->pin_Enable()); #if 0 if (ff->pin_Aset().is_linked()) connect(ff->pin_Aset(), ff2->pin_Aset()); From ec0c66ff25cce86095396b218332ae01bf79ae46 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 24 Apr 2014 18:36:49 -0700 Subject: [PATCH 034/245] Fix internal error elaborating types used in different scopes Some types, i.e. vector types with parameterized dimensions, may have different elaboration results in different scopes. Handle those cases in the elaboration caches. --- elab_sig.cc | 14 ++++++++++---- elab_type.cc | 15 +++++++++++++++ expr_synth.cc | 6 ++++++ pform_dump.cc | 24 +++++++++++++++++------- pform_types.cc | 9 --------- pform_types.h | 6 ++++-- synth2.cc | 24 +++++++++++++++++++++++- 7 files changed, 75 insertions(+), 23 deletions(-) diff --git a/elab_sig.cc b/elab_sig.cc index 2d6fdcf9b..980e198b1 100644 --- a/elab_sig.cc +++ b/elab_sig.cc @@ -563,7 +563,7 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const // Special case: this is a constructor, so the return // signal is also the first argument. For example, the // source code for the definition may be: - // function new(...); + // function new(...); // endfunction // In this case, the "@" port is the synthetic "this" // argument and we also use it as a return value at the @@ -594,6 +594,11 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const } if (ret_type) { + if (debug_elaborate) { + cerr << get_fileline() << ": PFunction::elaborate_sig: " + << "return type: " << *ret_type << endl; + return_type_->pform_dump(cerr, 8); + } list ret_unpacked; ret_sig = new NetNet(scope, fname, NetNet::REG, ret_unpacked, ret_type); @@ -615,9 +620,10 @@ void PFunction::elaborate_sig(Design*des, NetScope*scope) const NetFuncDef*def = new NetFuncDef(scope, ret_sig, ports, pdef); if (debug_elaborate) - cerr << get_fileline() << ": debug: " - << "Attach function definition to scope " - << scope_path(scope) << "." << endl; + cerr << get_fileline() << ": PFunction::elaborate_sig: " + << "Attach function definition " << scope_path(scope) + << " with ret_sig width=" << (ret_sig? ret_sig->vector_width() : 0) + << "." << endl; scope->set_func_def(def); diff --git a/elab_type.cc b/elab_type.cc index c4c97eaa7..1167c1902 100644 --- a/elab_type.cc +++ b/elab_type.cc @@ -31,6 +31,21 @@ using namespace std; +/* + * Elaborations of types may vary depending on the scope that it is + * done in, so keep a per-scope cache of the results. + */ +ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope) +{ + map::iterator pos = cache_type_elaborate_.lower_bound(scope); + if (pos->first == scope) + return pos->second; + + ivl_type_s*tmp = elaborate_type_raw(des, scope); + cache_type_elaborate_.insert(pos, pair(scope, tmp)); + return tmp; +} + ivl_type_s* data_type_t::elaborate_type_raw(Design*des, NetScope*) const { cerr << get_fileline() << ": internal error: " diff --git a/expr_synth.cc b/expr_synth.cc index 89242ec9b..8812f23f0 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -1440,6 +1440,12 @@ NetNet* NetEUFunc::synthesize(Design*des, NetScope*scope, NetExpr*root) osig->local_flag(true); connect(net->pin(0), osig->pin(0)); + if (debug_synth2) { + cerr << get_fileline() << ": NetEUFunc::synthesize: " + << "result_sig_->vector_width()=" << result_sig_->vector_width() + << ", osig->vector_width()=" << osig->vector_width() << endl; + } + /* Connect the pins to the arguments. */ NetFuncDef*def = func_->func_def(); for (unsigned idx = 0; idx < eparms.size(); idx += 1) { diff --git a/pform_dump.cc b/pform_dump.cc index a8b08c04b..65fcdbfe4 100644 --- a/pform_dump.cc +++ b/pform_dump.cc @@ -160,13 +160,6 @@ void parray_type_t::pform_dump(ostream&out, unsigned indent) const base_type->pform_dump(out, indent+4); } -void uarray_type_t::pform_dump(ostream&out, unsigned indent) const -{ - out << setw(indent) << "" << "Unpacked array " << "[...]" - << " of:" << endl; - base_type->pform_dump(out, indent+4); -} - void struct_type_t::pform_dump(ostream&out, unsigned indent) const { out << setw(indent) << "" << "Struct " << (packed_flag?"packed":"unpacked") @@ -181,6 +174,23 @@ void struct_type_t::pform_dump(ostream&out, unsigned indent) const } } +void uarray_type_t::pform_dump(ostream&out, unsigned indent) const +{ + out << setw(indent) << "" << "Unpacked array " << "[...]" + << " of:" << endl; + base_type->pform_dump(out, indent+4); +} + +void vector_type_t::pform_dump(ostream&fd, unsigned indent) const +{ + fd << setw(indent) << "" << "vector of " << base_type; + for (list::iterator cur = pdims->begin() + ; cur != pdims->end() ; ++cur) { + fd << "[" << *(cur->first) << ":" << *(cur->second) << "]"; + } + fd << endl; +} + void class_type_t::pform_dump(ostream&out, unsigned indent) const { out << setw(indent) << "" << "class " << name; diff --git a/pform_types.cc b/pform_types.cc index c809ffbf6..5a7868bef 100644 --- a/pform_types.cc +++ b/pform_types.cc @@ -24,15 +24,6 @@ data_type_t::~data_type_t() { } -ivl_type_s* data_type_t::elaborate_type(Design*des, NetScope*scope) -{ - if (cache_type_elaborate_) - return cache_type_elaborate_; - - cache_type_elaborate_ = elaborate_type_raw(des, scope); - return cache_type_elaborate_; -} - string_type_t::~string_type_t() { } diff --git a/pform_types.h b/pform_types.h index 32758f5e4..97149dcb4 100644 --- a/pform_types.h +++ b/pform_types.h @@ -88,7 +88,7 @@ struct pform_tf_port_t { */ class data_type_t : public LineInfo { public: - inline explicit data_type_t() : cache_type_elaborate_(0) { } + inline explicit data_type_t() { } virtual ~data_type_t() = 0; // This method is used to figure out the base type of a packed // compound object. Return IVL_VT_NO_TYPE if the type is not packed. @@ -102,7 +102,8 @@ class data_type_t : public LineInfo { // Elaborate the type to an ivl_type_s type. virtual ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const; - ivl_type_s*cache_type_elaborate_; + // Keep per-scope elaboration results cached. + std::map cache_type_elaborate_; }; struct void_type_t : public data_type_t { @@ -175,6 +176,7 @@ struct vector_type_t : public data_type_t { std::list*pd) : base_type(bt), signed_flag(sf), reg_flag(false), integer_flag(false), implicit_flag(false), pdims(pd) { } virtual ivl_variable_type_t figure_packed_base_type(void)const; + virtual void pform_dump(std::ostream&out, unsigned indent) const; ivl_type_s* elaborate_type_raw(Design*des, NetScope*scope) const; ivl_variable_type_t base_type; diff --git a/synth2.cc b/synth2.cc index ad3c7ddc3..560d553f6 100644 --- a/synth2.cc +++ b/synth2.cc @@ -89,6 +89,8 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, << "r-value signal is " << rsig->vector_width() << " bits." << endl; cerr << get_fileline() << ": NetAssignBase::synth_async: " << "lval_->lwidth()=" << lval_->lwidth() << endl; + cerr << get_fileline() << ": NetAssignBase::synth_async: " + << "lsig = " << scope_path(scope) << "." << lsig->name() << endl; if (const NetExpr*base = lval_->get_base()) { cerr << get_fileline() << ": NetAssignBase::synth_async: " << "base_=" << *base << endl; @@ -450,6 +452,12 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, connect(bsig.pin(idx), accumulated_nex_out.pin(idx)); accumulated_nex_out.pin(idx).unlink(); } + + if (debug_synth2) { + cerr << get_fileline() << ": NetCondit::synth_async: " + << "synthesize else clause at " << else_->get_fileline() + << " is done." << endl; + } } ivl_assert(*this, nex_out.pin_count()==asig.pin_count()); @@ -470,9 +478,23 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, cerr << get_fileline() << ": internal error: " << "NetCondit::synth_async: " << "Mux input sizes do not match." - << "A size=" << mux_width + << " A size=" << mux_width << ", B size=" << bsig.pin(idx).nexus()->vector_width() << endl; + cerr << get_fileline() << ": : " + << "asig node pins:" << endl; + asig.dump_node_pins(cerr, 8); + cerr << get_fileline() << ": : " + << "if_ statement:" << endl; + if_->dump(cerr, 8); + cerr << get_fileline() << ": : " + << "bsig node pins:" << endl; + bsig.dump_node_pins(cerr, 4); + if (else_) { + cerr << get_fileline() << ": : " + << "else_ statement:" << endl; + else_->dump(cerr, 8); + } rc_flag = false; } From be0c61051d9e473629226f4858a23c319affc76f Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 1 May 2014 20:37:33 -0700 Subject: [PATCH 035/245] Add synthesis of for-loops This required keeping for-loops as actual things through the netlist form so that the synthesizer can get at and understand the parts of the for-loop. This may improve vvp code generation in the future, but for now continue to present to the vvp code generation the block-while form. --- design_dump.cc | 7 ++++ elaborate.cc | 39 ++++++------------ emit.cc | 5 +++ expr_synth.cc | 16 ++++++++ net_func_eval.cc | 10 +++++ net_nex_input.cc | 19 +++++++++ net_nex_output.cc | 5 +++ net_proc.cc | 37 +++++++++++++++++ netlist.cc | 5 +++ netlist.h | 40 ++++++++++++++++++ synth2.cc | 101 ++++++++++++++++++++++++++++++++++++++++++---- 11 files changed, 250 insertions(+), 34 deletions(-) diff --git a/design_dump.cc b/design_dump.cc index 9a8a256d7..0004cc3b4 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -1165,6 +1165,13 @@ void NetForever::dump(ostream&o, unsigned ind) const statement_->dump(o, ind+2); } +void NetForLoop::dump(ostream&fd, unsigned ind) const +{ + fd << setw(ind) << "" << "FOR LOOP index=" << index_->name() << endl; + statement_->dump(fd, ind+4); + step_statement_->dump(fd, ind+4); +} + void NetFree::dump(ostream&o, unsigned ind) const { o << setw(ind) << "// free storage : " << scope_path(scope_) << endl; diff --git a/elaborate.cc b/elaborate.cc index 4c203db17..be406747e 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -4549,15 +4549,12 @@ NetForce* PForce::elaborate(Design*des, NetScope*scope) const */ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const { - NetExpr*etmp; + NetExpr*initial_expr; assert(scope); const PEIdent*id1 = dynamic_cast(name1_); assert(id1); - NetBlock*top = new NetBlock(NetBlock::SEQU, 0); - top->set_line(*this); - /* make the expression, and later the initial assignment to the condition variable. The statement in the for loop is very specifically an assignment. */ @@ -4569,34 +4566,23 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const return 0; } assert(sig); - NetAssign_*lv = new NetAssign_(sig); /* Make the r-value of the initial assignment, and size it properly. Then use it to build the assignment statement. */ - etmp = elaborate_rval_expr(des, scope, sig->net_type(), - lv->expr_type(), lv->lwidth(), - expr1_); + initial_expr = elaborate_rval_expr(des, scope, sig->net_type(), + sig->data_type(), sig->vector_width(), + expr1_); if (debug_elaborate) { cerr << get_fileline() << ": debug: FOR initial assign: " - << sig->name() << " = " << *etmp << endl; + << sig->name() << " = " << *initial_expr << endl; } - NetAssign*init = new NetAssign(lv, etmp); - init->set_line(*this); - - top->append(init); - - NetBlock*body = new NetBlock(NetBlock::SEQU, 0); - body->set_line(*this); - /* Elaborate the statement that is contained in the for loop. If there is an error, this will return 0 and I should skip the append. No need to worry, the error has been reported so it's OK that the netlist is bogus. */ - NetProc*tmp = statement_->elaborate(des, scope); - if (tmp) - body->append(tmp); + NetProc*sub = statement_->elaborate(des, scope); /* Now elaborate the for_step statement. I really should do @@ -4604,20 +4590,19 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const really does step the variable. */ if (debug_elaborate) { cerr << get_fileline() << ": debug: Elaborate for_step statement " - << sig->name() << " = " << *etmp << endl; + << sig->name() << " = " << *initial_expr << endl; } NetProc*step = step_->elaborate(des, scope); - body->append(step); - /* Elaborate the condition expression. Try to evaluate it too, in case it is a constant. This is an interesting case worthy of a warning. */ NetExpr*ce = elab_and_eval(des, scope, cond_, -1); if (ce == 0) { - delete top; + delete sub; + delete step; return 0; } @@ -4629,10 +4614,10 @@ NetProc* PForStatement::elaborate(Design*des, NetScope*scope) const /* All done, build up the loop. */ - NetWhile*loop = new NetWhile(ce, body); + NetForLoop*loop = new NetForLoop(sig, initial_expr, ce, sub, step); loop->set_line(*this); - top->append(loop); - return top; + loop->wrap_up(); + return loop; } /* diff --git a/emit.cc b/emit.cc index 4da13d0d3..7f8634b20 100644 --- a/emit.cc +++ b/emit.cc @@ -283,6 +283,11 @@ bool NetForever::emit_proc(struct target_t*tgt) const return true; } +bool NetForLoop::emit_proc(struct target_t*tgt) const +{ + return tgt->proc_block(as_block_); +} + bool NetFree::emit_proc(struct target_t*tgt) const { tgt->proc_free(this); diff --git a/expr_synth.cc b/expr_synth.cc index 8812f23f0..f709668b9 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -1271,6 +1271,22 @@ NetNet* NetETernary::synthesize(Design *des, NetScope*scope, NetExpr*root) */ NetNet* NetESignal::synthesize(Design*des, NetScope*scope, NetExpr*root) { + // If this is a synthesis with a specific value for the + // signal, then replace it (here) with a constant value. + if (net_->scope()==scope && net_->name()==scope->genvar_tmp) { + netvector_t*tmp_vec = new netvector_t(net_->data_type(), + net_->vector_width()-1, 0); + NetNet*tmp = new NetNet(scope, scope->local_symbol(), + NetNet::IMPLICIT, tmp_vec); + verinum tmp_val ((uint64_t)scope->genvar_tmp_val, net_->vector_width()); + NetConst*tmp_const = new NetConst(scope, scope->local_symbol(), tmp_val); + tmp_const->set_line(*this); + des->add_node(tmp_const); + + connect(tmp->pin(0), tmp_const->pin(0)); + return tmp; + } + if (word_ == 0) return net_; diff --git a/net_func_eval.cc b/net_func_eval.cc index d130f3723..a5b336b11 100644 --- a/net_func_eval.cc +++ b/net_func_eval.cc @@ -628,6 +628,16 @@ bool NetForever::evaluate_function(const LineInfo&loc, return flag; } +/* + * For now, resort to the block form of the statement until we learn + * to do this directly. + */ +bool NetForLoop::evaluate_function(const LineInfo&loc, + map&context_map) const +{ + return as_block_->evaluate_function(loc, context_map); +} + bool NetRepeat::evaluate_function(const LineInfo&loc, map&context_map) const { diff --git a/net_nex_input.cc b/net_nex_input.cc index fa2d9ecfc..50053bf04 100644 --- a/net_nex_input.cc +++ b/net_nex_input.cc @@ -406,6 +406,25 @@ NexusSet* NetForce::nex_input(bool) return new NexusSet; } +NexusSet* NetForLoop::nex_input(bool rem_out) +{ + NexusSet*result = init_expr_->nex_input(rem_out); + + NexusSet*tmp = condition_->nex_input(rem_out); + result->add(*tmp); + delete tmp; + + tmp = statement_->nex_input(rem_out); + result->add(*tmp); + delete tmp; + + tmp = step_statement_->nex_input(rem_out); + result->add(*tmp); + delete tmp; + + return result; +} + NexusSet* NetForever::nex_input(bool rem_out) { NexusSet*result = statement_->nex_input(rem_out); diff --git a/net_nex_output.cc b/net_nex_output.cc index 761937fb8..232f0a122 100644 --- a/net_nex_output.cc +++ b/net_nex_output.cc @@ -134,6 +134,11 @@ void NetEvWait::nex_output(NexusSet&out) statement_->nex_output(out); } +void NetForLoop::nex_output(NexusSet&out) +{ + if (statement_) statement_->nex_output(out); +} + void NetPDelay::nex_output(NexusSet&out) { if (statement_) statement_->nex_output(out); diff --git a/net_proc.cc b/net_proc.cc index d9412fa9d..081a4ea40 100644 --- a/net_proc.cc +++ b/net_proc.cc @@ -126,6 +126,43 @@ NetForever::~NetForever() delete statement_; } +NetForLoop::NetForLoop(NetNet*ind, NetExpr*iexpr, NetExpr*cond, NetProc*sub, NetProc*step) +: index_(ind), init_expr_(iexpr), condition_(cond), statement_(sub), step_statement_(step) +{ +} + +void NetForLoop::wrap_up() +{ + NetBlock*top = new NetBlock(NetBlock::SEQU, 0); + top->set_line(*this); + + NetAssign_*lv = new NetAssign_(index_); + NetAssign*set_stmt = new NetAssign(lv, init_expr_); + set_stmt->set_line(*init_expr_); + top->append(set_stmt); + + NetBlock*internal_block = new NetBlock(NetBlock::SEQU, 0); + internal_block->set_line(*this); + + internal_block->append(statement_); + internal_block->append(step_statement_); + + NetWhile*wloop = new NetWhile(condition_, internal_block); + wloop->set_line(*this); + + top->append(wloop); + + as_block_ = top; +} + +NetForLoop::~NetForLoop() +{ + delete init_expr_; + delete condition_; + delete statement_; + delete step_statement_; +} + NetPDelay::NetPDelay(uint64_t d, NetProc*st) : delay_(d), expr_(0), statement_(st) { diff --git a/netlist.cc b/netlist.cc index 4d184dc51..bd0070c6c 100644 --- a/netlist.cc +++ b/netlist.cc @@ -2756,6 +2756,11 @@ DelayType NetForever::delay_type() const return statement_->delay_type(); } +DelayType NetForLoop::delay_type() const +{ + return get_loop_delay_type(condition_, statement_); +} + DelayType NetPDelay::delay_type() const { if (expr_) { diff --git a/netlist.h b/netlist.h index 3242e26c0..bb8a2ac73 100644 --- a/netlist.h +++ b/netlist.h @@ -1172,6 +1172,8 @@ class NetScope : public Definitions, public Attrib { perm_string genvar_tmp; long genvar_tmp_val; + std::map loop_index_tmp; + private: void evaluate_parameter_logic_(Design*des, param_ref_t cur); void evaluate_parameter_real_(Design*des, param_ref_t cur); @@ -3308,6 +3310,44 @@ class NetForever : public NetProc { NetProc*statement_; }; +class NetForLoop : public NetProc { + + public: + explicit NetForLoop(NetNet*index, NetExpr*initial_expr, NetExpr*cond, + NetProc*sub, NetProc*step); + ~NetForLoop(); + + void wrap_up(); + + void emit_recurse(struct target_t*) const; + + virtual NexusSet* nex_input(bool rem_out = true); + 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 bool evaluate_function(const LineInfo&loc, + map&ctx) const; + + // synthesize as asynchronous logic, and return true. + bool synth_async(Design*des, NetScope*scope, + NexusSet&nex_map, NetBus&nex_out, + NetBus&accumulated_nex_out); + + private: + NetNet*index_; + NetExpr*init_expr_; + NetExpr*condition_; + NetProc*statement_; + NetProc*step_statement_; + + // The code generator needs to see this rewritten as a while + // loop with synthetic statements. This is a hack that I + // should probably take out later as the ivl_target learns + // about for loops. + NetBlock*as_block_; +}; + class NetFree : public NetProc { public: diff --git a/synth2.cc b/synth2.cc index 560d553f6..577be4cd3 100644 --- a/synth2.cc +++ b/synth2.cc @@ -100,16 +100,22 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, << ", nex_out.pin_count()==" << nex_out.pin_count() << endl; } - ivl_assert(*this, nex_out.pin_count()==1); - ivl_assert(*this, rsig->pin_count()==1); - connect(nex_out.pin(0), rsig->pin(0)); - -#if 0 + // 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()) { ivl_assert(*this, lval_->lwidth() < lsig->vector_width()); + // XXXX If we ar within a NetForLoop or similar + // processing, then there may be an index value. I + // currently do not know how to handle that, but + // probably I'm going to need the index_args passed in. long base_off = 0; - if (! eval_as_long(base_off, lval_->get_base())) { + + // Evaluate the index expression to a constant. + const NetExpr*base_expr_raw = lval_->get_base(); + ivl_assert(*this, base_expr_raw); + NetExpr*base_expr = base_expr_raw->evaluate_function(*this, scope->loop_index_tmp); + if (! eval_as_long(base_off, base_expr)) { assert(0); } ivl_assert(*this, base_off >= 0); @@ -129,7 +135,11 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, connect(ps->pin(0), rsig->pin(0)); rsig = tmp; } -#endif + + ivl_assert(*this, nex_out.pin_count()==1); + ivl_assert(*this, rsig->pin_count()==1); + connect(nex_out.pin(0), rsig->pin(0)); + /* This lval_ represents a reg that is a WIRE in the synthesized results. This function signals the destructor @@ -533,6 +543,83 @@ bool NetEvWait::synth_async(Design*des, NetScope*scope, return flag; } +bool NetForLoop::synth_async(Design*des, NetScope*scope, + NexusSet&nex_map, NetBus&nex_out, + NetBus&accumulated_nex_out) +{ + if (debug_synth2) { + cerr << get_fileline() << ": NetForLoop::synth_async: " + << "Index variable is " << index_->name() << endl; + cerr << get_fileline() << ": NetForLoop::synth_async: " + << "Initialization expression: " << *init_expr_ << endl; + } + + // Get the step assignment statement and break it into the + // l-value (should be the index) and the r-value, which is the + // step expressions. + NetAssign*step_assign = dynamic_cast (step_statement_); + ivl_assert(*this, step_assign); + ivl_assert(*this, step_assign->assign_operator()==0); + NetExpr*step_expr = step_assign->rval(); + + // Tell the scope that this index value is like a genvar. + LocalVar index_var; + index_var.nwords = 0; + + map index_args; + + // Calculate the initial value for the index. + index_var.value = init_expr_->evaluate_function(*this, index_args); + ivl_assert(*this, index_var.value); + index_args[index_->name()] = index_var; + + for (;;) { + // Evaluate the condition expression. If it is false, + // then we are going to break out of this synthesis loop. + NetExpr*tmp = condition_->evaluate_function(*this, index_args); + ivl_assert(*this, tmp); + + long cond_value; + bool rc = eval_as_long(cond_value, tmp); + ivl_assert(*this, rc); + delete tmp; + if (!cond_value) break; + + scope->genvar_tmp = index_->name(); + rc = eval_as_long(scope->genvar_tmp_val, index_var.value); + ivl_assert(*this, rc); + + if (debug_synth2) { + cerr << get_fileline() << ": NetForLoop::synth_async: " + << "Synthesis iteration with " << index_->name() + << "=" << *index_var.value << endl; + } + + // Synthesize the iterated expression. Stash the loop + // index value so that the substatements can see this + // value and use it during its own synthesis. + ivl_assert(*this, scope->loop_index_tmp.empty()); + scope->loop_index_tmp = index_args; + rc = statement_->synth_async(des, scope, nex_map, nex_out, accumulated_nex_out); + scope->loop_index_tmp.clear(); + + // Evaluate the step_expr to generate the next index value. + tmp = step_expr->evaluate_function(*this, index_args); + ivl_assert(*this, tmp); + delete index_var.value; + index_var.value = tmp; + index_args[index_->name()] = index_var; + } + + delete index_var.value; +#if 0 + cerr << get_fileline() << ": sorry: Synthesis of for-loops not implemented." << endl; + return as_block_->synth_async(des, scope, nex_map, nex_out, accumulated_nex_out); +#else + return true; +#endif +} + /* * This method is called when the process is shown to be * asynchronous. Figure out the nexus set of outputs from this From ce864fc6345311c803374b7a34c0ca83611bb87e Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Fri, 2 May 2014 18:30:44 -0700 Subject: [PATCH 036/245] Synthesis of NetForLoop step that ahs compressed assignment operators. --- synth2.cc | 29 +++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/synth2.cc b/synth2.cc index 577be4cd3..4057272b5 100644 --- a/synth2.cc +++ b/synth2.cc @@ -558,8 +558,8 @@ bool NetForLoop::synth_async(Design*des, NetScope*scope, // l-value (should be the index) and the r-value, which is the // step expressions. NetAssign*step_assign = dynamic_cast (step_statement_); + char assign_operator = step_assign->assign_operator(); ivl_assert(*this, step_assign); - ivl_assert(*this, step_assign->assign_operator()==0); NetExpr*step_expr = step_assign->rval(); // Tell the scope that this index value is like a genvar. @@ -606,18 +606,35 @@ bool NetForLoop::synth_async(Design*des, NetScope*scope, // Evaluate the step_expr to generate the next index value. tmp = step_expr->evaluate_function(*this, index_args); ivl_assert(*this, tmp); + + // If there is an assign_operator, then replace the + // index_var.value with (value tmp) and evaluate + // that to get the next value. "value" is the existing + // value, and "tmp" is the step value. We are replacing + // (value += tmp) with (value = value + tmp) and + // evaluating it. + switch (assign_operator) { + case 0: + break; + case '+': + case '-': + index_var.value = new NetEBAdd(assign_operator, tmp, index_var.value, 32, true); + tmp = index_var.value->evaluate_function(*this, index_args); + break; + + default: + cerr << get_fileline() << ": internal error: " + << "NetForLoop::synth_async: What to do with assign_operator=" << assign_operator << endl; + ivl_assert(*this, 0); + } delete index_var.value; index_var.value = tmp; index_args[index_->name()] = index_var; } delete index_var.value; -#if 0 - cerr << get_fileline() << ": sorry: Synthesis of for-loops not implemented." << endl; - return as_block_->synth_async(des, scope, nex_map, nex_out, accumulated_nex_out); -#else + return true; -#endif } /* From 109c5d895d209049d1e459532b472d2aaa7560e0 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sat, 3 May 2014 15:45:15 -0700 Subject: [PATCH 037/245] Synthesis of assignment that is part of larger block. It is possible for an assignment statement to be part of a grander complex that has lots of outputs, not all handled by this particular assignment. In that case, the assignment may need to figure out which output it is supposed to bind to. --- synth2.cc | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/synth2.cc b/synth2.cc index 4057272b5..35362d1ee 100644 --- a/synth2.cc +++ b/synth2.cc @@ -136,10 +136,21 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, rsig = tmp; } - ivl_assert(*this, nex_out.pin_count()==1); - ivl_assert(*this, rsig->pin_count()==1); - connect(nex_out.pin(0), rsig->pin(0)); + if (nex_out.pin_count() > 1) { + NexusSet tmp_set; + nex_output(tmp_set); + ivl_assert(*this, tmp_set.size()==1); + unsigned ptr = nex_map.find_nexus(tmp_set[0]); + ivl_assert(*this, rsig->pin_count()==1); + ivl_assert(*this, nex_map.size()==nex_out.pin_count()); + ivl_assert(*this, nex_out.pin_count() > ptr); + connect(nex_out.pin(ptr), rsig->pin(0)); + } else { + ivl_assert(*this, nex_out.pin_count()==1); + ivl_assert(*this, rsig->pin_count()==1); + connect(nex_out.pin(0), rsig->pin(0)); + } /* This lval_ represents a reg that is a WIRE in the synthesized results. This function signals the destructor From 020e280a98994ccb30369ef1ba70080e10b9fd2b Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 8 May 2014 14:00:39 -0700 Subject: [PATCH 038/245] nodangle functor accounts for NexusSet links In a design, there may be lingering NexusSet objects, or the nodangle may itself use NexusSet objects. This creates links, and this should not confuse the functor. While we are at it, clean up some handling of events structures. --- async.cc | 4 ++-- net_event.cc | 60 ++++++++++++++-------------------------------------- net_link.cc | 22 +++++++++++++------ netlist.cc | 10 ++++++--- netlist.h | 16 ++++++++------ nodangle.cc | 2 +- sync.cc | 2 +- synth2.cc | 2 +- 8 files changed, 52 insertions(+), 66 deletions(-) diff --git a/async.cc b/async.cc index fa5bbaee0..311b1af2c 100644 --- a/async.cc +++ b/async.cc @@ -50,8 +50,8 @@ bool NetEvWait::is_asynchronous() level sensitive, but the nex_async_ method takes care of that test. */ NexusSet*sense = new NexusSet; - for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) { - NexusSet*tmp = event(idx)->nex_async_(); + for (unsigned idx = 0 ; idx < events_.size() ; idx += 1) { + NexusSet*tmp = events_[idx]->nex_async_(); if (tmp == 0) { delete sense; return false; diff --git a/net_event.cc b/net_event.cc index 5ad61063a..9b67b5b99 100644 --- a/net_event.cc +++ b/net_event.cc @@ -20,6 +20,7 @@ # include "config.h" # include "compiler.h" # include "netlist.h" +# include "ivl_assert.h" /* * NOTE: The name_ is perm-allocated by the caller. @@ -316,6 +317,10 @@ void NetEvProbe::find_similar_probes(list&plist) for (Link*lcur = nex->first_nlink(); lcur; lcur = lcur->next_nlink()) { NetPins*obj = lcur->get_obj(); + // Skip NexusSet objects + if (obj == 0) + continue; + if (obj->pin_count() != pin_count()) continue; @@ -340,14 +345,14 @@ void NetEvProbe::find_similar_probes(list&plist) } NetEvWait::NetEvWait(NetProc*pr) -: statement_(pr), nevents_(0), events_(0) +: statement_(pr) { } NetEvWait::~NetEvWait() { - if (events_) { - for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) { + if (! events_.empty()) { + for (unsigned idx = 0 ; idx < events_.size() ; idx += 1) { NetEvent*tgt = events_[idx]; tgt->waitref_ -= 1; @@ -365,7 +370,7 @@ NetEvWait::~NetEvWait() delete tmp; } } - delete[]events_; + events_.clear(); } delete statement_; } @@ -374,29 +379,12 @@ void NetEvWait::add_event(NetEvent*tgt) { /* A wait fork is an empty event. */ if (! tgt) { - assert(nevents_ == 0); - nevents_ = 1; - events_ = new NetEvent*[1]; - events_[0] = 0; + assert(events_.empty()); + events_.push_back(0); return; } - if (nevents_ == 0) { - events_ = new NetEvent*[1]; - - } else { - assert(events_[0]); - NetEvent**tmp = new NetEvent*[nevents_+1]; - for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) { - tmp[idx] = events_[idx]; - assert(tmp[idx] != tgt); - } - delete[]events_; - events_ = tmp; - } - - events_[nevents_] = tgt; - nevents_ += 1; + events_.push_back(tgt); // Remember to tell the NetEvent that there is someone // pointing to it. @@ -411,14 +399,14 @@ void NetEvWait::add_event(NetEvent*tgt) void NetEvWait::replace_event(NetEvent*src, NetEvent*repl) { unsigned idx; - for (idx = 0 ; idx < nevents_ ; idx += 1) { + for (idx = 0 ; idx < events_.size() ; idx += 1) { if (events_[idx] == src) break; } - assert(idx < nevents_); + assert(idx < events_.size()); - /* First, remove me from the list held by the src NetEvent. */ + // First, remove me from the list held by the src NetEvent. assert(src->waitref_ > 0); src->waitref_ -= 1; struct NetEvent::wcell_*tmp = src->wlist_; @@ -435,6 +423,7 @@ void NetEvWait::replace_event(NetEvent*src, NetEvent*repl) delete tmp; } + // Replace the src pointer with the repl pointer. events_[idx] = repl; // Remember to tell the replacement NetEvent that there is @@ -448,23 +437,6 @@ void NetEvWait::replace_event(NetEvent*src, NetEvent*repl) } -unsigned NetEvWait::nevents() const -{ - return nevents_; -} - -const NetEvent* NetEvWait::event(unsigned idx) const -{ - assert(idx < nevents_); - return events_[idx]; -} - -NetEvent* NetEvWait::event(unsigned idx) -{ - assert(idx < nevents_); - return events_[idx]; -} - NetProc* NetEvWait::statement() { return statement_; diff --git a/net_link.cc b/net_link.cc index 74e7f8790..bccb4c065 100644 --- a/net_link.cc +++ b/net_link.cc @@ -90,13 +90,19 @@ void Nexus::connect(Link&r) void connect(Link&l, Link&r) { + Nexus*tmp; assert(&l != &r); - if (l.nexus_ != 0) { - connect(l.nexus_, r); - } else if (r.nexus_ != 0) { - connect(r.nexus_, l); + // If either the l or r link already are part of a Nexus, then + // re-use that nexus. Go through some effort so that we are + // not gratuitously creating Nexus object. + if (l.next_ && (tmp=l.find_nexus_())) { + connect(tmp, r); + } else if (r.next_ && (tmp=r.find_nexus_())) { + connect(tmp, l); } else { - Nexus*tmp = new Nexus(l); + // No existing Nexus (both links are so far unconnected) + // so start one. + tmp = new Nexus(l); tmp->connect(r); } } @@ -224,9 +230,11 @@ bool Link::is_linked() const bool Link::is_linked(const Link&that) const { - if (next_ == 0) + // If this or that link is linked to nothing, then they cannot + // be linked to each other. + if (! this->is_linked()) return false; - if (that.next_ == 0) + if (! that.is_linked()) return false; const Link*cur = next_; diff --git a/netlist.cc b/netlist.cc index bd0070c6c..ebbf29d0f 100644 --- a/netlist.cc +++ b/netlist.cc @@ -180,7 +180,11 @@ NetPins::NetPins(unsigned npins) NetPins::~NetPins() { - delete[] pins_; + if (pins_) { + assert(pins_[0].node_ == this); + assert(pins_[0].pin_zero_); + delete[] pins_; + } } Link& NetPins::pin(unsigned idx) @@ -194,7 +198,7 @@ Link& NetPins::pin(unsigned idx) } assert(idx < npins_); - assert(idx == 0? pins_[0].pin_zero_ : pins_[idx].pin_==idx); + assert(idx == 0? (pins_[0].pin_zero_ && pins_[0].node_==this) : pins_[idx].pin_==idx); return pins_[idx]; } @@ -208,7 +212,7 @@ const Link& NetPins::pin(unsigned idx) const } assert(pins_); assert(idx < npins_); - assert(idx == 0? pins_[0].pin_zero_ : pins_[idx].pin_==idx); + assert(idx == 0? (pins_[0].pin_zero_ && pins_[0].node_==this) : pins_[idx].pin_==idx); return pins_[idx]; } diff --git a/netlist.h b/netlist.h index bb8a2ac73..13b61e0a4 100644 --- a/netlist.h +++ b/netlist.h @@ -153,7 +153,10 @@ class Link { bool is_equal(const Link&that) const; // Return information about the object that this link is - // a part of. + // a part of. Note that the get_obj() method can return NIL if + // this Link is part of a NexusSet. That should be OK, because + // they are collection variables, and not functional parts of + // a design. const NetPins*get_obj() const; NetPins*get_obj(); unsigned get_pin() const; @@ -3200,9 +3203,9 @@ class NetEvWait : public NetProc { void add_event(NetEvent*tgt); void replace_event(NetEvent*orig, NetEvent*repl); - unsigned nevents() const; - const NetEvent*event(unsigned) const; - NetEvent*event(unsigned); + 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]; } NetProc*statement(); @@ -3236,9 +3239,8 @@ class NetEvWait : public NetProc { private: NetProc*statement_; - - unsigned nevents_; - NetEvent**events_; + // Events that I might wait for. + std::vectorevents_; }; ostream& operator << (ostream&out, const NetEvWait&obj); diff --git a/nodangle.cc b/nodangle.cc index 19336fc23..9c9940f28 100644 --- a/nodangle.cc +++ b/nodangle.cc @@ -117,7 +117,7 @@ void nodangle_f::event(Design*, NetEvent*ev) NetEvent*tmp = *idx; assert(tmp != ev); - tmp ->replace_event(ev); + tmp ->replace_event(ev); } } } diff --git a/sync.cc b/sync.cc index 1b3a62d88..41c210ac2 100644 --- a/sync.cc +++ b/sync.cc @@ -33,7 +33,7 @@ bool NetProc::is_synchronous() bool NetEvWait::is_synchronous() { - for (unsigned idx = 0 ; idx < nevents_ ; idx += 1) { + for (unsigned idx = 0 ; idx < events_.size() ; idx += 1) { NetEvent*ev = events_[idx]; if (ev->nprobe() == 0) diff --git a/synth2.cc b/synth2.cc index 35362d1ee..ad6f9b7ec 100644 --- a/synth2.cc +++ b/synth2.cc @@ -1002,7 +1002,7 @@ bool NetEvWait::synth_sync(Design*des, NetScope*scope, /* This can't be other than one unless there are named events, which I cannot synthesize. */ - assert(nevents_ == 1); + ivl_assert(*this, events_.size() == 1); NetEvent*ev = events_[0]; assert(ev->nprobe() >= 1); From f16c67d45a5681496b1f457d444df5baf7f4587e Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sat, 17 May 2014 16:58:36 -0700 Subject: [PATCH 039/245] synth2 NetForLoop synthesis works a lot like begin/end blocks. Using the synth_async_block_substatement_ makes the for-loop synthesis properly handle the chance that there are default inputs. --- synth2.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/synth2.cc b/synth2.cc index ad6f9b7ec..1d927af59 100644 --- a/synth2.cc +++ b/synth2.cc @@ -611,7 +611,11 @@ bool NetForLoop::synth_async(Design*des, NetScope*scope, // value and use it during its own synthesis. ivl_assert(*this, scope->loop_index_tmp.empty()); scope->loop_index_tmp = index_args; - rc = statement_->synth_async(des, scope, nex_map, nex_out, accumulated_nex_out); + + rc = synth_async_block_substatement_(des, scope, nex_map, + accumulated_nex_out, + statement_); + scope->loop_index_tmp.clear(); // Evaluate the step_expr to generate the next index value. @@ -645,6 +649,10 @@ bool NetForLoop::synth_async(Design*des, NetScope*scope, delete index_var.value; + // The output from the block is now the accumulated outputs. + for (unsigned idx = 0 ; idx < nex_out.pin_count() ; idx += 1) + connect(nex_out.pin(idx), accumulated_nex_out.pin(idx)); + return true; } From b7b77b2e75ec5726769def1c95489f316f50d82c Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Tue, 20 May 2014 00:08:03 +0100 Subject: [PATCH 040/245] Correct fix for GitHub issue 19. --- vvp/vvp_net.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/vvp/vvp_net.cc b/vvp/vvp_net.cc index aaf8f0203..0c29fa4b6 100644 --- a/vvp/vvp_net.cc +++ b/vvp/vvp_net.cc @@ -1713,8 +1713,10 @@ template bool vector4_to_value(const vvp_vector4_t&vec, T&val) break; case BIT4_1: // On overflow, return the maximum value of type T - if (msk == 0) return ~msk; - res |= msk; + if (msk == 0) + res = ~msk; + else + res |= msk; break; default: return false; From 6547fdee3dd03ceca07af9817f506213528b03ee Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 21 May 2014 09:00:47 -0700 Subject: [PATCH 041/245] vlog95: for cppcheck the target functions are used by the compiler. --- tgt-vlog95/Makefile.in | 3 ++- tgt-vlog95/cppcheck.sup | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 tgt-vlog95/cppcheck.sup diff --git a/tgt-vlog95/Makefile.in b/tgt-vlog95/Makefile.in index 19428f2e9..69a57b618 100644 --- a/tgt-vlog95/Makefile.in +++ b/tgt-vlog95/Makefile.in @@ -56,7 +56,8 @@ distclean: clean rm -f Makefile config.log cppcheck: $(O:.o=.c) - cppcheck --enable=all -f $(INCLUDE_PATH) $^ + cppcheck --enable=all -f --suppressions-list=$(srcdir)/cppcheck.sup \ + --relative-paths=$(srcdir) $(INCLUDE_PATH) $^ Makefile: $(srcdir)/Makefile.in ../config.status cd ..; ./config.status --file=tgt-vlog95/$@ diff --git a/tgt-vlog95/cppcheck.sup b/tgt-vlog95/cppcheck.sup new file mode 100644 index 000000000..f1a757bf9 --- /dev/null +++ b/tgt-vlog95/cppcheck.sup @@ -0,0 +1,8 @@ +// These are the global access functions called from the compiler so they +// are not used here. + +// target_design() +unusedFunction:vlog95.c:59 + +// target_query() +unusedFunction:vlog95.c:226 From d96e8872c1ac5fca5a4c8df871bfee9525672268 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Fri, 23 May 2014 21:55:46 +0100 Subject: [PATCH 042/245] Fix for GitHub issue 25 - compiler crash when function declared outside module. This is an error in traditional Verilog and a unsupported feature in SystemVerilog. Fail gracefully with a suitable error/sorry message. Do the same for task declarations. --- pform.cc | 33 +++++++++++++++++++++++---------- 1 file changed, 23 insertions(+), 10 deletions(-) diff --git a/pform.cc b/pform.cc index b8a408b86..7b899b688 100644 --- a/pform.cc +++ b/pform.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -344,7 +344,16 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto) FILE_NAME(task, loc); PScopeExtra*scopex = find_nearest_scopex(lexical_scope); - assert(scopex); + if ((scopex == 0) && (generation_flag < GN_VER2005_SV)) { + cerr << task->get_fileline() << ": error: task declarations " + "must be contained within a module." << endl; + error_count += 1; + } + if ((scopex == 0) && (generation_flag >= GN_VER2005_SV)) { + cerr << task->get_fileline() << ": sorry: task declarations " + "in the compilation unit scope are not yet supported." << endl; + error_count += 1; + } if (pform_cur_generate) { // Check if the task is already in the dictionary. @@ -357,7 +366,7 @@ PTask* pform_push_task_scope(const struct vlltype&loc, char*name, bool is_auto) error_count += 1; } pform_cur_generate->tasks[task->pscope_name()] = task; - } else { + } else if (scopex) { // Check if the task is already in the dictionary. if (scopex->tasks.find(task->pscope_name()) != scopex->tasks.end()) { cerr << task->get_fileline() << ": error: duplicate " @@ -381,13 +390,17 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name, PFunction*func = new PFunction(func_name, lexical_scope, is_auto); FILE_NAME(func, loc); - LexicalScope*scope = lexical_scope; - PScopeExtra*scopex = dynamic_cast (scope); - while (scope && !scopex) { - scope = scope->parent_scope(); - scopex = dynamic_cast (scope); + PScopeExtra*scopex = find_nearest_scopex(lexical_scope); + if ((scopex == 0) && (generation_flag < GN_VER2005_SV)) { + cerr << func->get_fileline() << ": error: function declarations " + "must be contained within a module." << endl; + error_count += 1; + } + if ((scopex == 0) && (generation_flag >= GN_VER2005_SV)) { + cerr << func->get_fileline() << ": sorry: function declarations " + "in the compilation unit scope are not yet supported." << endl; + error_count += 1; } - assert(scopex); if (pform_cur_generate) { // Check if the function is already in the dictionary. @@ -400,7 +413,7 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name, error_count += 1; } pform_cur_generate->funcs[func->pscope_name()] = func; - } else { + } else if (scopex != 0) { // Check if the function is already in the dictionary. if (scopex->funcs.find(func->pscope_name()) != scopex->funcs.end()) { cerr << func->get_fileline() << ": error: duplicate " From d05abf5ca4c93f0f386c86af19c6e1b494fa84ed Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Fri, 23 May 2014 22:36:28 +0100 Subject: [PATCH 043/245] Fix for GitHub issue 26 - compiler crash when module port has no internal net. The compiler correctly reports an error when a module port has no associated internal net/reg, but could crash when the module was instantiated. --- elaborate.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/elaborate.cc b/elaborate.cc index be406747e..783840a81 100644 --- a/elaborate.cc +++ b/elaborate.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 1998-2014 Stephen Williams (steve@icarus.com) * Copyright CERN 2013 / Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it @@ -1307,6 +1307,10 @@ void PGModule::elaborate_mod_(Design*des, Module*rmod, NetScope*scope) const perm_string pname = peek_tail_name(mport[0]->path()); NetNet*tmp = instance[0]->find_signal(pname); + + // Handle the error case where there is no internal + // signal connected to the port. + if (!tmp) continue; assert(tmp); if (tmp->port_type() == NetNet::PINPUT) { From 76883fa18c4d76725bfaa933cd58e777a94cda30 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sat, 24 May 2014 20:08:48 -0700 Subject: [PATCH 044/245] NetCondit synthesis accounts for smaller l-values If both conditions of a NetCondit device assign to the same subset of l-value bits, then generate a smaller NetMux device that only switches the affected bits. --- netmisc.cc | 65 +++++++++++++++++++++++++++++++++++++++++++++++++++++ netmisc.h | 2 ++ synth2.cc | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 129 insertions(+), 4 deletions(-) diff --git a/netmisc.cc b/netmisc.cc index ec08cffdf..c83fc1497 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -1354,3 +1354,68 @@ void assign_unpacked_with_bufz(Design*des, NetScope*scope, } } +/* + * synthesis sometimes needs to unpack assignment to a part + * select. That looks like this: + * + * foo[N] <= ; + * + * The NetAssignBase::synth_async() method will turn that into a + * netlist like this: + * + * NetAssignBase(PV) --> base()== + * (0) (1) + * | | + * v v + * foo + * + * This search will return a pointer to the NetAssignBase(PV) object, + * but only if it matches this pattern. + */ +NetPartSelect* detect_partselect_lval(Link&pin) +{ + NetPartSelect*found_ps = 0; + + Nexus*nex = pin.nexus(); + for (Link*cur = nex->first_nlink() ; cur ; cur = cur->next_nlink()) { + NetPins*obj; + unsigned obj_pin; + cur->cur_link(obj, obj_pin); + + // NetNet pins have no effect on this search. + if (dynamic_cast (obj)) + continue; + + if (NetPartSelect*ps = dynamic_cast (obj)) { + + // If this is the input side of a NetPartSelect, skip. + if (ps->pin(obj_pin).get_dir()==Link::INPUT) + continue; + + // Oops, driven by the wrong size of a + // NetPartSelect, so this is not going to work out. + if (ps->dir()==NetPartSelect::VP) + return 0; + + // So now we know this is a NetPartSelect::PV. It + // is a candidate for our part-select assign. If + // we already have a candidate, then give up. + if (found_ps) + return 0; + + // This is our candidate. Carry on. + found_ps = ps; + continue; + + } + + // If this is a driver to the Nexus that is not a + // NetPartSelect device. This cannot happen to + // part selected lval nets, so quit now. + if (obj->pin(obj_pin).get_dir() == Link::OUTPUT) + return 0; + + } + + return found_ps; +} diff --git a/netmisc.h b/netmisc.h index 1eb6ad717..f43d56fa8 100644 --- a/netmisc.h +++ b/netmisc.h @@ -353,4 +353,6 @@ extern void assign_unpacked_with_bufz(Design*des, NetScope*scope, const LineInfo*loc, NetNet*lval, NetNet*rval); +extern NetPartSelect* detect_partselect_lval(Link&pin); + #endif diff --git a/synth2.cc b/synth2.cc index 1d927af59..b3c01bde6 100644 --- a/synth2.cc +++ b/synth2.cc @@ -105,7 +105,7 @@ bool NetAssignBase::synth_async(Design*des, NetScope*scope, if (lval_->lwidth() != lsig->vector_width()) { ivl_assert(*this, lval_->lwidth() < lsig->vector_width()); - // XXXX If we ar within a NetForLoop or similar + // XXXX If we are within a NetForLoop or similar // processing, then there may be an index value. I // currently do not know how to handle that, but // probably I'm going to need the index_args passed in. @@ -481,6 +481,12 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, } } + /* The nex_out output, asig input, and bsig input all have the + same pin count (usually, but not always 1) because they are + net arrays of the same dimension. The for loop below creates + a NetMux for each pin of the output. (Note that pins may + be, in fact usually are, vectors.) */ + ivl_assert(*this, nex_out.pin_count()==asig.pin_count()); ivl_assert(*this, nex_out.pin_count()==bsig.pin_count()); @@ -493,13 +499,51 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, if (NetNet*tmp = nex_out.pin(idx).nexus()->pick_any_net()) { mux_data_type = tmp->data_type(); } + + unsigned mux_off = 0; unsigned mux_width = asig.pin(idx).nexus()->vector_width(); + const unsigned mux_lwidth = mux_width; ivl_assert(*this, mux_width != 0); + + NetPartSelect*apv = detect_partselect_lval(asig.pin(idx)); + if (debug_synth2 && apv) { + cerr << get_fileline() << ": NetCondit::synth_async: " + << "Assign-to-part apv base=" << apv->base() + << ", width=" << apv->width() << endl; + } + + NetPartSelect*bpv = detect_partselect_lval(bsig.pin(idx)); + if (debug_synth2 && bpv) { + cerr << get_fileline() << ": NetCondit::synth_async: " + << "Assign-to-part bpv base=" << bpv->base() + << ", width=" << bpv->width() << endl; + } + + if (apv && bpv && apv->width()==bpv->width() && apv->base()==bpv->base()) { + // The a and b sides are both assigning to the + // same bits of the output, so we can use that to + // create a much narrower mux that only + // manipulates the width of the part. + mux_width = apv->width(); + mux_off = apv->base(); + asig.pin(idx).unlink(); + bsig.pin(idx).unlink(); + connect(asig.pin(idx), apv->pin(0)); + connect(bsig.pin(idx), bpv->pin(0)); + delete apv; + delete bpv; + + } else { + // The part selects are of no use. Forget them. + apv = 0; + bpv = 0; + } + if (mux_width != bsig.pin(idx).nexus()->vector_width()) { cerr << get_fileline() << ": internal error: " << "NetCondit::synth_async: " << "Mux input sizes do not match." - << " A size=" << mux_width + << " A size=" << mux_lwidth << ", B size=" << bsig.pin(idx).nexus()->vector_width() << endl; cerr << get_fileline() << ": : " @@ -533,12 +577,26 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, NetNet*otmp = new NetNet(scope, scope->local_symbol(), NetNet::WIRE, not_an_array, tmp_type); otmp->local_flag(true); - connect(nex_out.pin(idx),otmp->pin(0)); + connect(mux->pin_Result(),otmp->pin(0)); connect(mux->pin_Sel(), ssig->pin(0)); connect(mux->pin_Data(1), asig.pin(idx)); connect(mux->pin_Data(0), bsig.pin(idx)); - connect(nex_out.pin(idx), mux->pin_Result()); + + // We are only muxing a part of the output vector, so + // make a NetPartSelect::PV to widen the vector to the + // output at hand. + if (mux_width < mux_lwidth) { + tmp_type = new netvector_t(mux_data_type, mux_lwidth-1,0); + NetNet*tmp = new NetNet(scope, scope->local_symbol(), + NetNet::WIRE, not_an_array, tmp_type); + NetPartSelect*ps = new NetPartSelect(tmp, mux_off, mux_width, NetPartSelect::PV); + des->add_node(ps); + connect(ps->pin(0), otmp->pin(0)); + otmp = tmp; + } + + connect(nex_out.pin(idx), otmp->pin(0)); des->add_node(mux); } From ef79f538d5c6e1ec87fe83abd9aee30655101b62 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 25 May 2014 18:33:26 -0700 Subject: [PATCH 045/245] When making NetCondit objects, handle output part select. When a mux (NetCondit) is only writing to a part of the output vector (and using only a part of the inputs) then blend the mux output with the previous statement output. --- netmisc.cc | 4 ++++ synth2.cc | 26 ++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/netmisc.cc b/netmisc.cc index c83fc1497..f3984e389 100644 --- a/netmisc.cc +++ b/netmisc.cc @@ -1382,6 +1382,10 @@ NetPartSelect* detect_partselect_lval(Link&pin) unsigned obj_pin; cur->cur_link(obj, obj_pin); + // Skip NexusSet objects. + if (obj == 0) + continue; + // NetNet pins have no effect on this search. if (dynamic_cast (obj)) continue; diff --git a/synth2.cc b/synth2.cc index b3c01bde6..c028817af 100644 --- a/synth2.cc +++ b/synth2.cc @@ -440,6 +440,8 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, << endl; } + NetBus statement_input (scope, nex_out.pin_count()); + bool flag; NetBus asig(scope, nex_out.pin_count()); NetBus atmp(scope, nex_out.pin_count()); @@ -459,6 +461,9 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, } else { + for (unsigned idx = 0 ; idx < nex_out.pin_count() ; idx += 1) { + connect(statement_input.pin(idx), accumulated_nex_out.pin(idx)); + } if (debug_synth2) { cerr << get_fileline() << ": NetCondit::synth_async: " << "Synthesize else clause at " << else_->get_fileline() @@ -598,6 +603,27 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, connect(nex_out.pin(idx), otmp->pin(0)); + // Handle the special case that this NetMux is only + // assigning to a part of the vector. If that is the + // case, then we need to blend this output with the + // already calculated input to this statement so that we + // don't accidentally disconnect the other drivers to + // other bits. + // FIXME: NEED TO CHECK THAT THESE DRIVERS DON'T + // OVERLAP. THIS CODE CURRENTLY DOESN'T DO THAT TEST. + if (mux_width < mux_lwidth && if_ && else_) { + if (debug_synth2) { + cerr << get_fileline() << ": NetCondit::synth_async: " + << "This MetMux only impacts a few bits of output," + << " so combine nex_out with statement input." + << endl; + cerr << get_fileline() << ": NetCondit::synth_async: " + << "MISSING TEST FOR CORRECTNESS OF THE BLEND!" + << endl; + } + connect(nex_out.pin(idx), statement_input.pin(idx)); + } + des->add_node(mux); } From 579b59b8eb2985409bd24bcc2e1748190ef49da4 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 25 May 2014 19:38:12 -0700 Subject: [PATCH 046/245] Sizer recognizes more LPM types. --- tgt-sizer/scan_logs.cc | 5 ++++ tgt-sizer/scan_lpms.cc | 67 ++++++++++++++++++++++++++++++++++++++++-- tgt-sizer/sizer.cc | 30 ++++++++++++++++++- tgt-sizer/sizer_priv.h | 6 ++++ 4 files changed, 105 insertions(+), 3 deletions(-) diff --git a/tgt-sizer/scan_logs.cc b/tgt-sizer/scan_logs.cc index 82a4df0d9..0269543ad 100644 --- a/tgt-sizer/scan_logs.cc +++ b/tgt-sizer/scan_logs.cc @@ -32,6 +32,11 @@ void scan_logs(ivl_scope_t scope, struct sizer_statistics&stats) for (unsigned idx = 0 ; idx < ivl_scope_logs(scope) ; idx += 1) { ivl_net_logic_t log = ivl_scope_log(scope, idx); switch (ivl_logic_type(log)) { + // These logic gate types don't really exist in a + // mapped design. + case IVL_LO_BUFZ: + break; + case IVL_LO_AND: case IVL_LO_OR: case IVL_LO_XOR: diff --git a/tgt-sizer/scan_lpms.cc b/tgt-sizer/scan_lpms.cc index 6298d1275..a5c6b5aae 100644 --- a/tgt-sizer/scan_lpms.cc +++ b/tgt-sizer/scan_lpms.cc @@ -37,7 +37,7 @@ static void scan_lpms_ff(ivl_scope_t, ivl_lpm_t lpm, struct sizer_statistics&sta * Count adders as 2m gates. * Also keep a count of adders by width, just out of curiosity. */ -static void scans_lpms_add(ivl_scope_t, ivl_lpm_t lpm, struct sizer_statistics&stats) +static void scan_lpms_add(ivl_scope_t, ivl_lpm_t lpm, struct sizer_statistics&stats) { unsigned wid = ivl_lpm_width(lpm); @@ -46,8 +46,35 @@ static void scans_lpms_add(ivl_scope_t, ivl_lpm_t lpm, struct sizer_statistics&s stats.gate_count += 2*wid; } +/* + * Count equality comparator as 2m gates. + * Also keep a count of comparators by width, just out of curiosity. + */ +static void scan_lpms_equality(ivl_scope_t, ivl_lpm_t lpm, struct sizer_statistics&stats) +{ + unsigned wid = ivl_lpm_width(lpm); + + stats.equality_count[wid] += 1; + + stats.gate_count += 2*wid; +} + +/* + * Count magnitude comparators as 2m gates. + * Also keep a count of comparators by width, just out of curiosity. + */ +static void scan_lpms_magnitude(ivl_scope_t, ivl_lpm_t lpm, struct sizer_statistics&stats) +{ + unsigned wid = ivl_lpm_width(lpm); + + stats.magnitude_count[wid] += 1; + + stats.gate_count += 2*wid; +} + /* * Count mux devices as 2m gates. + * Also count the mux slices of various select sizes. */ static void scan_lpms_mux(ivl_scope_t, ivl_lpm_t lpm, struct sizer_statistics&stats) { @@ -57,10 +84,25 @@ static void scan_lpms_mux(ivl_scope_t, ivl_lpm_t lpm, struct sizer_statistics&st return; } + // The "width" of a mux is the number of 1-bit slices. unsigned wid = ivl_lpm_width(lpm); + + // Count the slices of the various width of muxes. + stats.mux_count[2] += wid; + stats.gate_count += 2*wid; } +/* + * Count reduction gates (wide input gates) as 1m gates. + */ +static void scan_lpms_reduction(ivl_scope_t, ivl_lpm_t lpm, struct sizer_statistics&stats) +{ + unsigned wid = ivl_lpm_width(lpm); + + stats.gate_count += wid; +} + void scan_lpms(ivl_scope_t scope, struct sizer_statistics&stats) { for (unsigned idx = 0 ; idx < ivl_scope_lpms(scope) ; idx += 1) { @@ -77,7 +119,19 @@ void scan_lpms(ivl_scope_t scope, struct sizer_statistics&stats) break; case IVL_LPM_ADD: - scans_lpms_add(scope, lpm, stats); + scan_lpms_add(scope, lpm, stats); + break; + + case IVL_LPM_CMP_EQ: + case IVL_LPM_CMP_NE: + case IVL_LPM_CMP_EEQ: + case IVL_LPM_CMP_NEE: + scan_lpms_equality(scope, lpm, stats); + break; + + case IVL_LPM_CMP_GE: + case IVL_LPM_CMP_GT: + scan_lpms_magnitude(scope, lpm, stats); break; // D-Type flip-flops. @@ -89,6 +143,15 @@ void scan_lpms(ivl_scope_t scope, struct sizer_statistics&stats) scan_lpms_mux(scope, lpm, stats); break; + case IVL_LPM_RE_AND: + case IVL_LPM_RE_NAND: + case IVL_LPM_RE_OR: + case IVL_LPM_RE_NOR: + case IVL_LPM_RE_XOR: + case IVL_LPM_RE_XNOR: + scan_lpms_reduction(scope, lpm, stats); + break; + default: stats.lpm_bytype[ivl_lpm_type(lpm)] += 1; break; diff --git a/tgt-sizer/sizer.cc b/tgt-sizer/sizer.cc index 2c985dd3a..a729e6f2b 100644 --- a/tgt-sizer/sizer.cc +++ b/tgt-sizer/sizer.cc @@ -156,7 +156,22 @@ static void show_stats(struct sizer_statistics&stats) for (map::const_iterator cur = stats.adder_count.begin() ; cur != stats.adder_count.end() ; ++ cur) { - fprintf(sizer_out, " ADDER[%u]: %u\n", cur->first, cur->second); + fprintf(sizer_out, " ADDER[%u]: %u units\n", cur->first, cur->second); + } + + for (map::const_iterator cur = stats.equality_count.begin() + ; cur != stats.equality_count.end() ; ++ cur) { + fprintf(sizer_out, " EQUALITY[%u]: %u units\n", cur->first, cur->second); + } + + for (map::const_iterator cur = stats.magnitude_count.begin() + ; cur != stats.magnitude_count.end() ; ++ cur) { + fprintf(sizer_out, " MAGNITUDE[%u]: %u units\n", cur->first, cur->second); + } + + for (map::const_iterator cur = stats.mux_count.begin() + ; cur != stats.mux_count.end() ; ++ cur) { + fprintf(sizer_out, " MUX[%u]: %u slices\n", cur->first, cur->second); } // These are diagnostic outputs for when more detail is needed. @@ -195,6 +210,19 @@ struct sizer_statistics& sizer_statistics::operator += (const sizer_statistics&t ; cur != that.adder_count.end() ; ++ cur) adder_count[cur->first] += cur->second; + for (map::const_iterator cur = that.equality_count.begin() + ; cur != that.equality_count.end() ; ++ cur) + equality_count[cur->first] += cur->second; + + for (map::const_iterator cur = that.magnitude_count.begin() + ; cur != that.magnitude_count.end() ; ++ cur) + magnitude_count[cur->first] += cur->second; + + + for (map::const_iterator cur = that.mux_count.begin() + ; cur != that.mux_count.end() ; ++ cur) + mux_count[cur->first] += cur->second; + for (map::const_iterator cur = that.lpm_bytype.begin() ; cur != that.lpm_bytype.end() ; ++ cur) diff --git a/tgt-sizer/sizer_priv.h b/tgt-sizer/sizer_priv.h index 3732e3174..85ca43cb9 100644 --- a/tgt-sizer/sizer_priv.h +++ b/tgt-sizer/sizer_priv.h @@ -31,6 +31,12 @@ struct sizer_statistics { unsigned gate_count; // Count adders of various dimension std::map adder_count; + // count equality comparators + std::map equality_count; + // Count magnitude comparators + std::map magnitude_count; + // Count mux's of various dimension + std::map mux_count; // Different kinds of nodes that we have not accounted for std::map lpm_bytype; std::map log_bytype; From ded1bd49492ca9b4b3fd83cb85f128ddd51be0ef Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Mon, 2 Jun 2014 15:42:02 -0700 Subject: [PATCH 047/245] Sanity check to prevent bad code getting through synth2 blending When conditional ports are blending (by allowing NetPartSelects be connected together to the outputs) make sure there isn't an accidental overlap of drivers that invalidates the process. --- link_const.cc | 55 +++++++++++++++++++++++++++++++++++++++++++++++++++ netlist.h | 5 +++++ synth2.cc | 4 ++++ 3 files changed, 64 insertions(+) diff --git a/link_const.cc b/link_const.cc index 9b01c75b3..0e8c7e39d 100644 --- a/link_const.cc +++ b/link_const.cc @@ -232,3 +232,58 @@ verinum Nexus::driven_vector() const return val; } + +/* + * Calculate a vector that represent all the bits of the vector, with + * each driven bit set to true, otherwise false. + */ +vector Nexus::driven_mask(void) const +{ + vector mask (vector_width()); + + for (const Link*cur = first_nlink() ; cur ; cur = cur->next_nlink()) { + + Link::DIR link_dir = cur->get_dir(); + if (link_dir==Link::PASSIVE) + continue; + if (link_dir==Link::INPUT) + continue; + + const NetPins*obj = cur->get_obj(); + + // If the link is to a variable (REG or INTEGER) then + // the variable is driving all the bits. We have our + // complete answer, mark all the bits as driven and + // finish. Otherwise, we are not going to get new + // information from this node, move on. + if (const NetNet*sig = dynamic_cast (obj)) { + NetNet::Type sig_type = sig->type(); + if (sig_type==NetNet::INTEGER || sig_type==NetNet::REG) { + for (size_t idx = 0 ; idx < mask.size() ; idx += 1) + mask[idx] = true; + return mask; + } + continue; + } + + const NetPartSelect*obj_ps = dynamic_cast(obj); + if (obj_ps && obj_ps->dir()==NetPartSelect::VP) + continue; + if (obj_ps && cur->get_pin()!=1) + continue; + if (obj_ps) { + for (unsigned idx = 0 ; idx < obj_ps->width() ; idx += 1) { + size_t bit = idx + obj_ps->base(); + ivl_assert(*obj, bit < mask.size()); + mask[bit] = true; + } + continue; + } + + for (size_t idx = 0 ; idx < mask.size() ; idx += 1) + mask[idx] = true; + return mask; + } + + return mask; +} diff --git a/netlist.h b/netlist.h index 13b61e0a4..1f5d4e9be 100644 --- a/netlist.h +++ b/netlist.h @@ -386,6 +386,11 @@ class Nexus { verinum::V driven_value() const; verinum driven_vector() const; + /* Return a mask of the bits of this vector that are + driven. This is usually all false or all true, but in + special cases it may be a blend. */ + std::vector driven_mask(void)const; + /* The code generator sets an ivl_nexus_t to attach code generation details to the nexus. */ ivl_nexus_t t_cookie() const { return t_cookie_; } diff --git a/synth2.cc b/synth2.cc index c028817af..169c216eb 100644 --- a/synth2.cc +++ b/synth2.cc @@ -621,6 +621,10 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, << "MISSING TEST FOR CORRECTNESS OF THE BLEND!" << endl; } + vectormask = statement_input.pin(idx).nexus()->driven_mask(); + for (size_t bit = mux_off ; bit < mux_off+mux_width ; bit += 1) { + ivl_assert(*this, mask[bit]==false); + } connect(nex_out.pin(idx), statement_input.pin(idx)); } From 41ff18206a9e999a176cff4f84904757516fb755 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sat, 7 Jun 2014 10:53:40 -0700 Subject: [PATCH 048/245] NetCase::synth_async gets a better handle on partly used inputs Better handle the case where the output for some pins comes from an earlier assignment. This allows for multiple ways to specify default outputs for some cases: the default: case and pre-assignment. --- synth2.cc | 53 +++++++++++++++++++++++++++++++++++------------------ 1 file changed, 35 insertions(+), 18 deletions(-) diff --git a/synth2.cc b/synth2.cc index 169c216eb..86e7d8804 100644 --- a/synth2.cc +++ b/synth2.cc @@ -250,7 +250,7 @@ bool NetBlock::synth_async(Design*des, NetScope*scope, bool NetCase::synth_async(Design*des, NetScope*scope, NexusSet&nex_map, NetBus&nex_out, - NetBus&) + NetBus&accumulated_nex_out) { /* Synthesize the select expression. */ NetNet*esig = expr_->synthesize(des, scope, expr_); @@ -270,6 +270,14 @@ bool NetCase::synth_async(Design*des, NetScope*scope, } } + // The accumulated_nex_out is taken as the input for this + // statement. Since there are collection of statements that + // start at this same point, we save all these inputs and + // reuse them for each statement. + NetBus statement_input (scope, nex_out.pin_count()); + for (unsigned idx = 0 ; idx < nex_out.pin_count() ; idx += 1) { + connect(statement_input.pin(idx), accumulated_nex_out.pin(idx)); + } /* Collect all the statements into a map of index to statement. The guard expression it evaluated to be the @@ -310,21 +318,28 @@ bool NetCase::synth_async(Design*des, NetScope*scope, } - /* If there is a default clause, synthesize is once and we'll + /* If there is a default clause, synthesize it once and we'll link it in wherever it is needed. */ NetBus default_bus (scope, nex_map.size()); - vectordefault_sig (nex_map.size()); - if (statement_default) { - NetBus tmp (scope, nex_out.pin_count()); - statement_default->synth_async(des, scope, nex_map, default_bus, tmp); + bool flag = synth_async_block_substatement_(des, scope, nex_map, + accumulated_nex_out, + statement_default); + if (!flag) { + return false; + } - // Get the signal from the synthesized statement. This - // will be hooked to all the default cases. - ivl_assert(*this, default_bus.pin_count()==1); - default_sig[0] = default_bus.pin(0).nexus()->pick_any_net(); - ivl_assert(*this, default_sig[0]); + for (unsigned idx = 0 ; idx < default_bus.pin_count() ; idx += 1) { + connect(default_bus.pin(idx), accumulated_nex_out.pin(idx)); + accumulated_nex_out.pin(idx).unlink(); + } + + if (debug_synth2) { + cerr << get_fileline() << ": NetCase::synth_async: " + << "synthesize default clause at " << statement_default->get_fileline() + << " is done." << endl; + } } vector mux (mux_width.size()); @@ -360,9 +375,9 @@ bool NetCase::synth_async(Design*des, NetScope*scope, NetProc*stmt = statement_map[idx]; if (stmt==0 && statement_default) { - ivl_assert(*this, default_sig.size() == mux.size()); + ivl_assert(*this, default_bus.pin_count() == mux.size()); for (size_t mdx = 0 ; mdx < mux.size() ; mdx += 1) - connect(mux[mdx]->pin_Data(idx), default_sig[mdx]->pin(0)); + connect(mux[mdx]->pin_Data(idx), default_bus.pin(mdx)); continue; } @@ -373,17 +388,19 @@ bool NetCase::synth_async(Design*des, NetScope*scope, continue; } - NetBus tmp (scope, nex_map.size()); NetBus accumulated_tmp (scope, nex_map.size()); - stmt->synth_async(des, scope, nex_map, tmp, accumulated_tmp); + for (unsigned pin = 0 ; pin < nex_map.size() ; pin += 1) + connect(accumulated_tmp.pin(pin), statement_input.pin(pin)); + + + synth_async_block_substatement_(des, scope, nex_map, accumulated_tmp, stmt); - ivl_assert(*this, tmp.pin_count() == mux.size()); for (size_t mdx = 0 ; mdx < mux.size() ; mdx += 1) { - connect(mux[mdx]->pin_Data(idx), tmp.pin(mdx)); + connect(mux[mdx]->pin_Data(idx), accumulated_tmp.pin(mdx)); if (mux[mdx]->pin_Data(idx).nexus()->pick_any_net()==0) { cerr << get_fileline() << ": warning: case " << idx - << " has no input for mux " << mdx << "." << endl; + << " has no input for mux slice " << mdx << "." << endl; ivl_variable_type_t mux_data_type = IVL_VT_LOGIC; netvector_t*tmp_vec = new netvector_t(mux_data_type, mux_width[mdx]-1, 0); From 6323e6a0a5d07820bc2eb438187982a03d197e56 Mon Sep 17 00:00:00 2001 From: Cary R Date: Sat, 7 Jun 2014 18:18:59 -0700 Subject: [PATCH 049/245] Update files from GTKWave to the latest from SVN. --- vpi/fastlz.c | 18 +- vpi/fastlz.h | 26 +-- vpi/fstapi.c | 486 +++++++++++++++++++++++------------------------ vpi/fstapi.h | 4 +- vpi/lxt2_write.c | 120 ++++++------ vpi/lxt2_write.h | 22 +-- vpi/lxt_write.c | 154 +++++++-------- vpi/lxt_write.h | 26 +-- vpi/wavealloca.h | 6 +- 9 files changed, 431 insertions(+), 431 deletions(-) diff --git a/vpi/fastlz.c b/vpi/fastlz.c index aa2f8bfda..50bf56a46 100644 --- a/vpi/fastlz.c +++ b/vpi/fastlz.c @@ -1,4 +1,4 @@ -/* +/* FastLZ - lightning-fast lossless compression library Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) @@ -53,7 +53,7 @@ #define FASTLZ_INLINE inline #elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__) #define FASTLZ_INLINE __inline -#else +#else #define FASTLZ_INLINE #endif @@ -87,7 +87,7 @@ int fastlz_decompress(const void* input, int length, void* output, int maxout); #define MAX_DISTANCE 8192 #if !defined(FASTLZ_STRICT_ALIGN) -#define FASTLZ_READU16(p) *((const flzuint16*)(p)) +#define FASTLZ_READU16(p) *((const flzuint16*)(p)) #else #define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8) #endif @@ -233,7 +233,7 @@ static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* *hslot = anchor; /* is this a match? check the first 3 bytes */ - if(distance==0 || + if(distance==0 || #if FASTLZ_LEVEL==1 (distance >= MAX_DISTANCE) || #else @@ -246,11 +246,11 @@ static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* /* far, needs at least 5-byte match */ if(distance >= MAX_DISTANCE) { - if(*ip++ != *ref++ || *ip++!= *ref++) + if(*ip++ != *ref++ || *ip++!= *ref++) goto literal; len += 2; } - + match: #endif @@ -346,7 +346,7 @@ static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* while(len > MAX_LEN-2) { *op++ = (7 << 5) + (distance >> 8); - *op++ = MAX_LEN - 2 - 7 -2; + *op++ = MAX_LEN - 2 - 7 -2; *op++ = (distance & 255); len -= MAX_LEN-2; } @@ -457,7 +457,7 @@ static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void ref = op - ofs - MAX_DISTANCE; } #endif - + #ifdef FASTLZ_SAFE if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > op_limit)) return 0; @@ -530,7 +530,7 @@ static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void* input, int length, void return 0; #endif - *op++ = *ip++; + *op++ = *ip++; for(--ctrl; ctrl; ctrl--) *op++ = *ip++; diff --git a/vpi/fastlz.h b/vpi/fastlz.h index e0512c190..8b4eac2e8 100644 --- a/vpi/fastlz.h +++ b/vpi/fastlz.h @@ -1,4 +1,4 @@ -/* +/* FastLZ - lightning-fast lossless compression library Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) @@ -47,11 +47,11 @@ extern "C" { #endif /** - Compress a block of data in the input buffer and returns the size of - compressed block. The size of input buffer is specified by length. The + Compress a block of data in the input buffer and returns the size of + compressed block. The size of input buffer is specified by length. The minimum input buffer size is 16. - The output buffer must be at least 5% larger than the input buffer + The output buffer must be at least 5% larger than the input buffer and can not be smaller than 66 bytes. If the input is not compressible, the return value might be larger than @@ -63,9 +63,9 @@ extern "C" { int fastlz_compress(const void* input, int length, void* output); /** - Decompress a block of compressed data and returns the size of the - decompressed block. If error occurs, e.g. the compressed data is - corrupted or the output buffer is not large enough, then 0 (zero) + Decompress a block of compressed data and returns the size of the + decompressed block. If error occurs, e.g. the compressed data is + corrupted or the output buffer is not large enough, then 0 (zero) will be returned instead. The input buffer and the output buffer can not overlap. @@ -74,14 +74,14 @@ int fastlz_compress(const void* input, int length, void* output); more than what is specified in maxout. */ -int fastlz_decompress(const void* input, int length, void* output, int maxout); +int fastlz_decompress(const void* input, int length, void* output, int maxout); /** - Compress a block of data in the input buffer and returns the size of - compressed block. The size of input buffer is specified by length. The + Compress a block of data in the input buffer and returns the size of + compressed block. The size of input buffer is specified by length. The minimum input buffer size is 16. - The output buffer must be at least 5% larger than the input buffer + The output buffer must be at least 5% larger than the input buffer and can not be smaller than 66 bytes. If the input is not compressible, the return value might be larger than @@ -89,14 +89,14 @@ int fastlz_decompress(const void* input, int length, void* output, int maxout); The input buffer and the output buffer can not overlap. - Compression level can be specified in parameter level. At the moment, + Compression level can be specified in parameter level. At the moment, only level 1 and level 2 are supported. Level 1 is the fastest compression and generally useful for short data. Level 2 is slightly slower but it gives better compression ratio. Note that the compressed data, regardless of the level, can always be decompressed using the function fastlz_decompress above. -*/ +*/ int fastlz_compress_level(int level, const void* input, int length, void* output); diff --git a/vpi/fstapi.c b/vpi/fstapi.c index ae158032f..331879741 100644 --- a/vpi/fstapi.c +++ b/vpi/fstapi.c @@ -56,7 +56,7 @@ #include #endif -#if HAVE_ALLOCA_H +#ifdef HAVE_ALLOCA_H #include #elif defined(__GNUC__) #ifndef __MINGW32__ @@ -125,7 +125,7 @@ void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint3 #endif #if defined(__APPLE__) && defined(__MACH__) -#define FST_MACOSX +#define FST_MACOSX #include #endif @@ -197,7 +197,7 @@ if(nam) /* cppcheck warning fix: nam is always defined, so this is not needed */ fprintf(stderr, "GetTempPath() failed in "__FILE__" line %d, exiting.\n", __LINE__); exit(255); } - else + else { uRetVal = GetTempFileName(lpTempPathBuffer, TEXT("FSTW"), 0, szTempFileName); if (uRetVal == 0) @@ -242,11 +242,11 @@ if(f) if(nam) { - if(*nam) - { - unlink(*nam); + if(*nam) + { + unlink(*nam); free(*nam); - *nam = NULL; + *nam = NULL; } } } @@ -254,7 +254,7 @@ if(nam) /*****************************************/ -/* +/* * to remove warn_unused_result compile time messages * (in the future there needs to be results checking) */ @@ -277,7 +277,7 @@ return(ftruncate(fd, length)); /* * realpath compatibility */ -static char *fstRealpath(const char *path, char *resolved_path) +static char *fstRealpath(const char *path, char *resolved_path) { #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __CYGWIN__ || defined HAVE_REALPATH @@ -287,7 +287,7 @@ if(!resolved_path) resolved_path = malloc(PATH_MAX+1); /* fixes bug on Leopard when resolved_path == NULL */ } #endif - + return(realpath(path, resolved_path)); #else @@ -406,12 +406,12 @@ for(;;) { rc <<= 7; rc |= (uint32_t)(*mem & 0x7f); - if(mem == mem_orig) + if(mem == mem_orig) { break; } mem--; - } + } return(rc); } @@ -449,14 +449,14 @@ for(;;) } mem--; } - -return(rc); + +return(rc); } static unsigned char *fstCopyVarint32ToLeft(unsigned char *pnt, uint32_t v) { -unsigned char *spnt; +unsigned char *spnt; uint32_t nxt = v; int cnt = 1; int i; @@ -495,7 +495,7 @@ while((nxt = v>>7)) return(pnt); } - + static uint64_t fstGetVarint64(unsigned char *mem, int *skiplen) { @@ -517,8 +517,8 @@ for(;;) } mem--; } - -return(rc); + +return(rc); } @@ -546,8 +546,8 @@ for(;;) } mem--; } - -return(rc); + +return(rc); } @@ -576,8 +576,8 @@ for(;;) } mem--; } - -return(rc); + +return(rc); } @@ -605,8 +605,8 @@ for(;;) } mem--; } - -return(rc); + +return(rc); } @@ -1051,7 +1051,7 @@ if(f) } fclose(f); - } + } if(!was_set) { @@ -1280,7 +1280,7 @@ for(i=0;imaxhandle;i++) { vm4ip = &(xc->valpos_mem[4*i]); - if(vm4ip[2]) + if(vm4ip[2]) { uint32_t offs = vm4ip[2]; uint32_t next_offs; @@ -1302,8 +1302,8 @@ for(i=0;imaxhandle;i++) unsigned char val; uint32_t time_delta, rcv; next_offs = fstGetUint32(vchg_mem + offs); - offs += 4; - + offs += 4; + time_delta = fstGetVarint32(vchg_mem + offs, &wrlen); val = vchg_mem[offs+wrlen]; offs = next_offs; @@ -1313,7 +1313,7 @@ for(i=0;imaxhandle;i++) case '0': case '1': rcv = ((val&1)<<1) | (time_delta<<2); break; /* pack more delta bits in for 0/1 vchs */ - + case 'x': case 'X': rcv = FST_RCV_X | (time_delta<<4); break; case 'z': case 'Z': rcv = FST_RCV_Z | (time_delta<<4); break; case 'h': case 'H': rcv = FST_RCV_H | (time_delta<<4); break; @@ -1322,7 +1322,7 @@ for(i=0;imaxhandle;i++) case 'l': case 'L': rcv = FST_RCV_L | (time_delta<<4); break; default: rcv = FST_RCV_D | (time_delta<<4); break; } - + scratchpnt = fstCopyVarint32ToLeft(scratchpnt, rcv); } } @@ -1332,7 +1332,7 @@ for(i=0;imaxhandle;i++) /* fstGetUint32 (next_offs) + fstGetVarint32 (time_delta) + fstGetVarint32 (len) + payload */ unsigned char *pnt; uint32_t record_len; - uint32_t time_delta; + uint32_t time_delta; while(offs) { @@ -1402,8 +1402,8 @@ for(i=0;imaxhandle;i++) *(--scratchpnt) = acc; shift = 0; acc = 0; - } - } + } + } #else /* new algorithm */ idx = ((vm4ip[1]+7) & ~7); @@ -1609,11 +1609,11 @@ if(1) fpos += fstWriterVarint(f, (zerocnt << 1)); zerocnt = 0; } - + if(vm4ip[2] & 0x80000000) { if(vm4ip[2] != prev_alias) - { + { fpos += fstWriterSVarint(f, (((int64_t)((int32_t)(prev_alias = vm4ip[2]))) << 1) | 1); } else @@ -1631,7 +1631,7 @@ if(1) } else { - zerocnt++; + zerocnt++; } } } @@ -1649,7 +1649,7 @@ if(1) fpos += fstWriterVarint(f, (zerocnt << 1)); zerocnt = 0; } - + if(vm4ip[2] & 0x80000000) { fpos += fstWriterVarint(f, 0); /* signal, note that using a *signed* varint would be more efficient than this byte escape! */ @@ -1665,7 +1665,7 @@ if(1) } else { - zerocnt++; + zerocnt++; } } } @@ -1900,7 +1900,7 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) if(xc->is_initial_time) /* simulation time never advanced so mock up the changes as time zero ones */ { fstHandle dupe_idx; - + fstWriterEmitTimeChange(xc, 0); /* emit some time change just to have one */ for(dupe_idx = 0; dupe_idx < xc->maxhandle; dupe_idx++) /* now clone the values */ { @@ -1969,12 +1969,12 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) cur_bl = xc->blackout_head->tim; xc->blackout_curr = xc->blackout_head->next; free(xc->blackout_head); - xc->blackout_head = xc->blackout_curr; + xc->blackout_head = xc->blackout_curr; } eos = ftello(xc->handle); fstWriterFseeko(xc, xc->handle, bpos, SEEK_SET); - fstWriterUint64(xc->handle, eos - bpos); + fstWriterUint64(xc->handle, eos - bpos); fflush(xc->handle); fstWriterFseeko(xc, xc->handle, fixup_offs, SEEK_SET); @@ -1999,7 +1999,7 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) hlen = ftello(xc->handle); fstWriterUint64(xc->handle, 0); /* section length */ fstWriterUint64(xc->handle, xc->hier_file_len); /* uncompressed length */ - + if(!xc->fourpack) { unsigned char *mem = malloc(FST_GZIO_LEN); @@ -2059,7 +2059,7 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) fstFwrite(mem, packed_len, 1, xc->handle); } - free(mem); + free(mem); } fstWriterFseeko(xc, xc->handle, 0, SEEK_END); @@ -2069,8 +2069,8 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) fflush(xc->handle); fstWriterFseeko(xc, xc->handle, fixup_offs, SEEK_SET); - fputc(xc->fourpack ? - ( fourpack_duo ? FST_BL_HIER_LZ4DUO : FST_BL_HIER_LZ4) : + fputc(xc->fourpack ? + ( fourpack_duo ? FST_BL_HIER_LZ4DUO : FST_BL_HIER_LZ4) : FST_BL_HIER, xc->handle); /* actual tag now also == compression type */ fstWriterFseeko(xc, xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */ @@ -2093,15 +2093,15 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) fstWriterUint64(xc->handle, xc->maxhandle); fstWriterUint64(xc->handle, xc->secnum); fflush(xc->handle); - + tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam); free(xc->vchg_mem); xc->vchg_mem = NULL; tmpfile_close(&xc->curval_handle, &xc->curval_handle_nam); tmpfile_close(&xc->valpos_handle, &xc->valpos_handle_nam); tmpfile_close(&xc->geom_handle, &xc->geom_handle_nam); if(xc->hier_handle) { fclose(xc->hier_handle); xc->hier_handle = NULL; } - if(xc->handle) - { + if(xc->handle) + { if(xc->repack_on_close) { FILE *fp; @@ -2149,7 +2149,7 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) fstWriterFseeko(xc, fp, 1, SEEK_SET); fstWriterUint64(fp, offpnt - 1); fclose(fp); - fclose(xc->handle); xc->handle = NULL; + fclose(xc->handle); xc->handle = NULL; unlink(xc->filename); rename(hf, xc->filename); @@ -2157,18 +2157,18 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) else { xc->repack_on_close = 0; - fclose(xc->handle); xc->handle = NULL; + fclose(xc->handle); xc->handle = NULL; } free(hf); } else { - fclose(xc->handle); xc->handle = NULL; + fclose(xc->handle); xc->handle = NULL; } } -#ifdef __MINGW32__ +#ifdef __MINGW32__ { int flen = strlen(xc->filename); char *hf = calloc(1, flen + 6); @@ -2255,7 +2255,7 @@ if(xc) xc->filetype = filetype; - fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_FILETYPE, SEEK_SET); + fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_FILETYPE, SEEK_SET); fputc(xc->filetype, xc->handle); fflush(xc->handle); fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET); @@ -2311,7 +2311,7 @@ if(xc && path && path[0]) int slen = strlen(path); #ifndef _WAVE_HAVE_JUDY const uint32_t hashmask = FST_PATH_HASHMASK; - const unsigned char *path2 = (const unsigned char *)path; + const unsigned char *path2 = (const unsigned char *)path; #else char *path2 = alloca(slen + 1); /* judy lacks const qualifier in its JudyHSIns definition */ strcpy(path2, path); @@ -2337,8 +2337,8 @@ if(xc && path && path[0]) #endif path2, NULL); } - - fstWriterSetAttrGeneric(xc, rp ? rp : + + fstWriterSetAttrGeneric(xc, rp ? rp : #ifndef _WAVE_HAVE_JUDY (const char *) #endif @@ -2425,13 +2425,13 @@ if(xc && s) if(tv == 10) { seconds_exp++; - } + } else if(tv == 100) { seconds_exp+=2; } - + fstWriterSetTimescale(ctx, seconds_exp); } } @@ -2543,7 +2543,7 @@ fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir vd, { struct fstWriterContext *xc = (struct fstWriterContext *)ctx; int i, nlen, is_real; - + if(xc && nam) { if(xc->valpos_mem) @@ -2572,10 +2572,10 @@ if(xc && nam) } } - xc->hier_file_len += fstWriterVarint(xc->hier_handle, len); + xc->hier_file_len += fstWriterVarint(xc->hier_handle, len); if(aliasHandle > xc->maxhandle) aliasHandle = 0; - xc->hier_file_len += fstWriterVarint(xc->hier_handle, aliasHandle); + xc->hier_file_len += fstWriterVarint(xc->hier_handle, aliasHandle); xc->numsigs++; if(xc->numsigs == xc->next_huge_break) { @@ -2621,8 +2621,8 @@ if(xc && nam) else { fstFwrite(&xc->nan, 8, 1, xc->curval_handle); /* initialize doubles to NaN rather than x */ - } - + } + xc->maxvalpos+=len; xc->maxhandle++; return(xc->maxhandle); @@ -2650,7 +2650,7 @@ if(xc) fprintf(xc->hier_handle, "%s%c%s%c", scopename ? scopename : "", 0, scopecomp ? scopecomp : "", 0); - + if(scopename) { xc->hier_file_len += strlen(scopename); @@ -2702,7 +2702,7 @@ if(xc) fputc(subtype, xc->hier_handle); fprintf(xc->hier_handle, "%s%c", attrname ? attrname : "", 0); - + if(attrname) { xc->hier_file_len += strlen(attrname); @@ -2756,7 +2756,7 @@ if((xc) && (handle <= xc->maxhandle)) if(!xc->is_initial_time) { fpos = xc->vchg_siz; - + 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 */ @@ -2764,7 +2764,7 @@ if((xc) && (handle <= xc->maxhandle)) if(!xc->vchg_mem) { fprintf(stderr, "FATAL ERROR, could not realloc() in fstWriterEmitValueChange, exiting.\n"); - exit(255); + exit(255); } } #ifdef FST_REMOVE_DUPLICATE_VC @@ -2777,7 +2777,7 @@ if((xc) && (handle <= xc->maxhandle)) unsigned char *old_value = xc->vchg_mem + vm4ip[2] + 4; /* the +4 skips old vm4ip[2] value */ while(*(old_value++) & 0x80) { /* skips over varint encoded "xc->tchn_idx - vm4ip[3]" */ } memcpy(old_value, buf, len); /* overlay new value */ - + memcpy(xc->curval_mem + offs, buf, len); return; } @@ -2801,7 +2801,7 @@ if((xc) && (handle <= xc->maxhandle)) } } } - + memcpy(xc->curval_mem + offs, buf, len); } else @@ -2811,7 +2811,7 @@ if((xc) && (handle <= xc->maxhandle)) unsigned char *old_value = xc->vchg_mem + vm4ip[2] + 4; /* the +4 skips old vm4ip[2] value */ while(*(old_value++) & 0x80) { /* skips over varint encoded "xc->tchn_idx - vm4ip[3]" */ } *old_value = *buf; /* overlay new value */ - + *(xc->curval_mem + offs) = *buf; return; } @@ -2829,7 +2829,7 @@ if((xc) && (handle <= xc->maxhandle)) } } } - + *(xc->curval_mem + offs) = *buf; } #endif @@ -2878,7 +2878,7 @@ if((xc) && (handle <= xc->maxhandle)) if(!xc->vchg_mem) { fprintf(stderr, "FATAL ERROR, could not realloc() in fstWriterEmitVariableLengthValueChange, exiting.\n"); - exit(255); + exit(255); } } @@ -2983,7 +2983,7 @@ if(xc) static const char *vartypes[] = { "event", "integer", "parameter", "real", "real_parameter", "reg", "supply0", "supply1", "time", "tri", - "triand", "trior", "trireg", "tri0", "tri1", + "triand", "trior", "trireg", "tri0", "tri1", "wand", "wire", "wor", "port", "sparray", "realtime", "string", "bit", "logic", "int", "shortint", "longint", "byte", "enum", "shortreal" @@ -3083,7 +3083,7 @@ unsigned char *rvat_chain_mem; fstHandle rvat_chain_facidx; uint32_t rvat_chain_pos_tidx; -uint32_t rvat_chain_pos_idx; +uint32_t rvat_chain_pos_idx; uint64_t rvat_chain_pos_time; unsigned rvat_chain_pos_valid : 1; @@ -3213,7 +3213,7 @@ if(xc) const char *fstReaderPopScope(void *ctx) { struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -if(xc && xc->curr_hier) +if(xc && xc->curr_hier) { struct fstCurrHier *ch = xc->curr_hier; if(xc->curr_hier->prev) @@ -3310,9 +3310,9 @@ return(0); int fstReaderGetFacProcessMask(void *ctx, fstHandle facidx) { struct fstReaderContext *xc = (struct fstReaderContext *)ctx; - + if(xc) - { + { facidx--; if(facidxmaxhandle) { @@ -3329,9 +3329,9 @@ return(0); void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx) { struct fstReaderContext *xc = (struct fstReaderContext *)ctx; - + if(xc) - { + { facidx--; if(facidxmaxhandle) { @@ -3347,9 +3347,9 @@ if(xc) void fstReaderClrFacProcessMask(void *ctx, fstHandle facidx) { struct fstReaderContext *xc = (struct fstReaderContext *)ctx; - + if(xc) - { + { facidx--; if(facidxmaxhandle) { @@ -3365,9 +3365,9 @@ if(xc) void fstReaderSetFacProcessMaskAll(void *ctx) { struct fstReaderContext *xc = (struct fstReaderContext *)ctx; - + if(xc) - { + { memset(xc->process_mask, 0xff, (xc->maxhandle+7)/8); } } @@ -3376,9 +3376,9 @@ if(xc) void fstReaderClrFacProcessMaskAll(void *ctx) { struct fstReaderContext *xc = (struct fstReaderContext *)ctx; - + if(xc) - { + { memset(xc->process_mask, 0x00, (xc->maxhandle+7)/8); } } @@ -3665,7 +3665,7 @@ if(!xc->fh) if(!xc->fh) #endif { - xc->fh = tmpfile_open(&xc->fh_nam); + xc->fh = tmpfile_open(&xc->fh_nam); free(fnam); fnam = NULL; if(!xc->fh) { @@ -3673,7 +3673,7 @@ if(!xc->fh) free(mem); return(0); } - } + } #ifndef __MINGW32__ if(fnam) unlink(fnam); @@ -3686,13 +3686,13 @@ if(!xc->fh) size_t len = ((uclen - hl) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - hl); size_t gzreadlen = gzread(zhandle, mem, len); /* rc should equal len... */ size_t fwlen; - + if(gzreadlen != len) { pass_status = 0; break; } - + fwlen = fstFwrite(mem, len, 1, xc->fh); if(fwlen != 1) { @@ -3705,10 +3705,10 @@ 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_ucmem2; - uint64_t uclen2; + unsigned char *lz4_cmem = malloc(clen); + unsigned char *lz4_ucmem = malloc(uclen); + unsigned char *lz4_ucmem2; + uint64_t uclen2; int skiplen2 = 0; fstFread(lz4_cmem, clen, 1, xc->f); @@ -3733,9 +3733,9 @@ 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 = malloc(clen); + unsigned char *lz4_ucmem = 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)); @@ -3817,17 +3817,17 @@ if(!(isfeof=feof(xc->fh))) xc->hier.htyp = FST_HT_SCOPE; xc->hier.u.scope.typ = fgetc(xc->fh); xc->hier.u.scope.name = pnt = xc->str_scope_nam; - while((ch = fgetc(xc->fh))) + while((ch = fgetc(xc->fh))) { - *(pnt++) = ch; + *(pnt++) = ch; }; /* scopename */ *pnt = 0; xc->hier.u.scope.name_length = pnt - xc->hier.u.scope.name; xc->hier.u.scope.component = pnt = xc->str_scope_comp; - while((ch = fgetc(xc->fh))) + while((ch = fgetc(xc->fh))) { - *(pnt++) = ch; + *(pnt++) = ch; }; /* scopecomp */ *pnt = 0; xc->hier.u.scope.component_length = pnt - xc->hier.u.scope.component; @@ -3842,9 +3842,9 @@ if(!(isfeof=feof(xc->fh))) xc->hier.u.attr.typ = fgetc(xc->fh); xc->hier.u.attr.subtype = fgetc(xc->fh); xc->hier.u.attr.name = pnt = xc->str_scope_nam; - while((ch = fgetc(xc->fh))) + while((ch = fgetc(xc->fh))) { - *(pnt++) = ch; + *(pnt++) = ch; }; /* scopename */ *pnt = 0; xc->hier.u.attr.name_length = pnt - xc->hier.u.scope.name; @@ -3852,7 +3852,7 @@ if(!(isfeof=feof(xc->fh))) xc->hier.u.attr.arg = fstReaderVarint64(xc->fh); if(xc->hier.u.attr.typ == FST_AT_MISC) - { + { if((xc->hier.u.attr.subtype == FST_MT_SOURCESTEM)||(xc->hier.u.attr.subtype == FST_MT_SOURCEISTEM)) { int sidx_skiplen_dummy = 0; @@ -3902,9 +3902,9 @@ if(!(isfeof=feof(xc->fh))) xc->hier.u.var.typ = tag; xc->hier.u.var.direction = fgetc(xc->fh); xc->hier.u.var.name = pnt = xc->str_scope_nam; - while((ch = fgetc(xc->fh))) + while((ch = fgetc(xc->fh))) { - *(pnt++) = ch; + *(pnt++) = ch; }; /* varname */ *pnt = 0; xc->hier.u.var.name_length = pnt - xc->hier.u.var.name; @@ -3928,11 +3928,11 @@ if(!(isfeof=feof(xc->fh))) xc->hier.u.var.handle = alias; xc->hier.u.var.is_alias = 1; } - + break; default: - isfeof = 1; + isfeof = 1; break; } } @@ -3977,7 +3977,7 @@ 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); - + switch(xc->timescale) { case 2: time_scale = 100; time_dimension[0] = 0; break; @@ -3987,15 +3987,15 @@ if(fv) case -1: time_scale = 100; time_dimension[0] = 'm'; break; case -2: time_scale = 10; case -3: time_dimension[0] = 'm'; break; - + case -4: time_scale = 100; time_dimension[0] = 'u'; break; case -5: time_scale = 10; case -6: time_dimension[0] = 'u'; break; - + case -10: time_scale = 100; time_dimension[0] = 'p'; break; case -11: time_scale = 10; case -12: time_dimension[0] = 'p'; break; - + case -13: time_scale = 100; time_dimension[0] = 'f'; break; case -14: time_scale = 10; case -15: time_dimension[0] = 'f'; break; @@ -4007,7 +4007,7 @@ if(fv) case -19: time_scale = 100; time_dimension[0] = 'z'; break; case -20: time_scale = 10; case -21: time_dimension[0] = 'z'; break; - + case -7: time_scale = 100; time_dimension[0] = 'n'; break; case -8: time_scale = 10; case -9: @@ -4017,7 +4017,7 @@ if(fv) if(fv) fprintf(fv, "$timescale\n\t%d%ss\n$end\n", time_scale, time_dimension); } -xc->maxhandle = 0; +xc->maxhandle = 0; xc->num_alias = 0; free(xc->signal_lens); @@ -4036,9 +4036,9 @@ while(!feof(xc->fh)) scopetype = fgetc(xc->fh); if((scopetype < FST_ST_MIN) || (scopetype > FST_ST_MAX)) scopetype = FST_ST_VCD_MODULE; pnt = str; - while((ch = fgetc(xc->fh))) + while((ch = fgetc(xc->fh))) { - *(pnt++) = ch; + *(pnt++) = ch; }; /* scopename */ *pnt = 0; while(fgetc(xc->fh)) { }; /* scopecomp */ @@ -4054,9 +4054,9 @@ while(!feof(xc->fh)) attrtype = fgetc(xc->fh); subtype = fgetc(xc->fh); pnt = str; - while((ch = fgetc(xc->fh))) + while((ch = fgetc(xc->fh))) { - *(pnt++) = ch; + *(pnt++) = ch; }; /* attrname */ *pnt = 0; @@ -4077,7 +4077,7 @@ while(!feof(xc->fh)) 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); break; - case FST_AT_MISC: + case FST_AT_MISC: default: attrtype = FST_AT_MISC; if(subtype == FST_MT_COMMENT) { @@ -4139,9 +4139,9 @@ while(!feof(xc->fh)) vartype = tag; /* vardir = */ fgetc(xc->fh); /* unused in VCD reader, but need to advance read pointer */ pnt = str; - while((ch = fgetc(xc->fh))) + while((ch = fgetc(xc->fh))) { - *(pnt++) = ch; + *(pnt++) = ch; }; /* varname */ *pnt = 0; len = fstReaderVarint32(xc->fh); @@ -4169,7 +4169,7 @@ while(!feof(xc->fh)) len = (vartype != FST_VT_SV_SHORTREAL) ? 64 : 32; xc->signal_typs[xc->maxhandle] = FST_VT_VCD_REAL; } - if(fv) + if(fv) { char vcdid_buf[16]; uint32_t modlen = (vartype != FST_VT_VCD_PORT) ? len : ((len - 2) / 3); @@ -4185,7 +4185,7 @@ while(!feof(xc->fh)) len = (vartype != FST_VT_SV_SHORTREAL) ? 64 : 32; xc->signal_typs[xc->maxhandle] = FST_VT_VCD_REAL; } - if(fv) + if(fv) { char vcdid_buf[16]; uint32_t modlen = (vartype != FST_VT_VCD_PORT) ? len : ((len - 2) / 3); @@ -4194,7 +4194,7 @@ while(!feof(xc->fh)) } xc->num_alias++; } - + break; default: @@ -4259,7 +4259,7 @@ if(sectype == FST_BL_ZWRAPPER) { fcomp = tmpfile_open(&xc->f_nam); free(hf); hf = NULL; - if(!fcomp) { tmpfile_close(&fcomp, &xc->f_nam); return(0); } + if(!fcomp) { tmpfile_close(&fcomp, &xc->f_nam); return(0); } } #if defined(FST_MACOSX) @@ -4270,7 +4270,7 @@ if(sectype == FST_BL_ZWRAPPER) setvbuf(fcomp, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */ xc->filename_unpacked = hf; #else - if(hf) + if(hf) { unlink(hf); free(hf); @@ -4323,25 +4323,25 @@ if(gzread_pass_status) while(blkpos < endfile) { fstReaderFseeko(xc, xc->f, blkpos, SEEK_SET); - + sectype = fgetc(xc->f); seclen = fstReaderUint64(xc->f); - - if(sectype == EOF) + + if(sectype == EOF) { break; } if((hdr_incomplete) && (!seclen)) - { + { break; } - - if(!hdr_seen && (sectype != FST_BL_HDR)) + + if(!hdr_seen && (sectype != FST_BL_HDR)) { break; } - + blkpos++; if(sectype == FST_BL_HDR) { @@ -4349,12 +4349,12 @@ if(gzread_pass_status) { int ch; double dcheck; - + xc->start_time = fstReaderUint64(xc->f); - xc->end_time = fstReaderUint64(xc->f); - + xc->end_time = fstReaderUint64(xc->f); + hdr_incomplete = (xc->start_time == 0) && (xc->end_time == 0); - + fstFread(&dcheck, 8, 1, xc->f); xc->double_endian_match = (dcheck == FST_DOUBLE_ENDTEST); if(!xc->double_endian_match) @@ -4363,10 +4363,10 @@ if(gzread_pass_status) unsigned char rvs_buf[8]; double d; } vu; - + unsigned char *dcheck_alias = (unsigned char *)&dcheck; int rvs_idx; - + for(rvs_idx=0;rvs_idx<8;rvs_idx++) { vu.rvs_buf[rvs_idx] = dcheck_alias[7-rvs_idx]; @@ -4376,15 +4376,15 @@ if(gzread_pass_status) break; /* either corrupt file or wrong architecture (offset +33 also functions as matchword) */ } } - + hdr_seen = 1; - - xc->mem_used_by_writer = fstReaderUint64(xc->f); - xc->scope_count = fstReaderUint64(xc->f); - xc->var_count = fstReaderUint64(xc->f); - xc->maxhandle = fstReaderUint64(xc->f); + + xc->mem_used_by_writer = fstReaderUint64(xc->f); + xc->scope_count = fstReaderUint64(xc->f); + xc->var_count = fstReaderUint64(xc->f); + xc->maxhandle = fstReaderUint64(xc->f); xc->num_alias = xc->var_count - xc->maxhandle; - xc->vc_section_count = fstReaderUint64(xc->f); + xc->vc_section_count = fstReaderUint64(xc->f); ch = fgetc(xc->f); xc->timescale = (signed char)ch; fstFread(xc->version, FST_HDR_SIM_VERSION_SIZE, 1, xc->f); @@ -4402,7 +4402,7 @@ if(gzread_pass_status) { uint64_t bt = fstReaderUint64(xc->f); xc->end_time = fstReaderUint64(xc->f); - + if(!vc_section_count_actual) { xc->start_time = bt; } } @@ -4417,7 +4417,7 @@ if(gzread_pass_status) unsigned char *ucdata = malloc(uclen); unsigned char *pnt = ucdata; int i; - + xc->contains_geom_section = 1; xc->maxhandle = fstReaderUint64(xc->f); xc->longest_signal_value_len = 32; /* arbitrarily set at 32...this is much longer than an expanded double */ @@ -4431,7 +4431,7 @@ if(gzread_pass_status) unsigned long destlen = uclen; unsigned long sourcelen = clen; int rc; - + fstFread(cdata, clen, 1, xc->f); rc = uncompress(ucdata, &destlen, cdata, sourcelen); @@ -4440,26 +4440,26 @@ if(gzread_pass_status) printf("geom uncompress rc = %d\n", rc); exit(255); } - + free(cdata); } else { fstFread(ucdata, uclen, 1, xc->f); } - + free(xc->signal_lens); xc->signal_lens = malloc(sizeof(uint32_t) * xc->maxhandle); free(xc->signal_typs); xc->signal_typs = malloc(sizeof(unsigned char) * xc->maxhandle); - + for(i=0;imaxhandle;i++) { int skiplen; uint64_t val = fstGetVarint32(pnt, &skiplen); - + pnt += skiplen; - + if(val) { xc->signal_lens[i] = (val != 0xFFFFFFFF) ? val : 0; @@ -4478,8 +4478,8 @@ 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 = malloc(xc->longest_signal_value_len + 1); + free(ucdata); } } @@ -4519,7 +4519,7 @@ if(gzread_pass_status) xc->blackout_times[i] = cur_bl; } } - + blkpos += seclen; if(!hdr_seen) break; } @@ -4530,7 +4530,7 @@ if(gzread_pass_status) { xc->vc_section_count = vc_section_count_actual; } - + if(!xc->contains_geom_section) { fstReaderProcessHier(xc, NULL); /* recreate signal_lens/signal_typs info */ @@ -4627,14 +4627,14 @@ if(xc) free(xc->signal_lens); xc->signal_lens = NULL; free(xc->filename); xc->filename = NULL; - if(xc->fh) - { - tmpfile_close(&xc->fh, &xc->fh_nam); + if(xc->fh) + { + tmpfile_close(&xc->fh, &xc->fh_nam); } - if(xc->f) - { - tmpfile_close(&xc->f, &xc->f_nam); + if(xc->f) + { + tmpfile_close(&xc->f, &xc->f_nam); if(xc->filename_unpacked) { unlink(xc->filename_unpacked); @@ -4677,7 +4677,7 @@ uint64_t seclen, beg_tim; #ifdef FST_DEBUG uint64_t end_tim; #endif -uint64_t frame_uclen, frame_clen, frame_maxhandle, vc_maxhandle; +uint64_t frame_uclen, frame_clen, frame_maxhandle, vc_maxhandle; off_t vc_start; off_t indx_pntr, indx_pos; off_t *chain_table = NULL; @@ -4706,14 +4706,14 @@ headptr = calloc(xc->maxhandle, sizeof(uint32_t)); length_remaining = calloc(xc->maxhandle, sizeof(uint32_t)); if(fv) - { - fprintf(fv, "$dumpvars\n"); + { + fprintf(fv, "$dumpvars\n"); #ifndef FST_WRITEX_DISABLE fflush(fv); setvbuf(fv, (char *) NULL, _IONBF, 0); /* even buffered IO is slow so disable it and use our own routines that don't need seeking */ xc->writex_fd = fileno(fv); #endif - } + } for(;;) { @@ -4721,7 +4721,7 @@ for(;;) traversal_mem_offs = 0; fstReaderFseeko(xc, xc->f, blkpos, SEEK_SET); - + sectype = fgetc(xc->f); seclen = fstReaderUint64(xc->f); @@ -4744,7 +4744,7 @@ for(;;) beg_tim = fstReaderUint64(xc->f); #ifdef FST_DEBUG - end_tim = + end_tim = #endif fstReaderUint64(xc->f); @@ -4787,9 +4787,9 @@ 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, "\ttime section unc: %d, com: %d (%d items)\n", (int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems); -#endif +#endif if(tsec_clen > seclen) break; /* corrupted tsec_clen: by definition it can't be larger than size of section */ ucdata = malloc(tsec_uclen); if(!ucdata) break; /* malloc fail as tsec_uclen out of range from corrupted file */ @@ -4802,22 +4802,22 @@ for(;;) { cdata = malloc(tsec_clen); fstFread(cdata, tsec_clen, 1, xc->f); - + rc = uncompress(ucdata, &destlen, cdata, sourcelen); - + if(rc != Z_OK) { printf("tsec uncompress rc = %d\n", rc); exit(255); } - + free(cdata); } else { fstFread(ucdata, tsec_uclen, 1, xc->f); } - + free(time_table); time_table = calloc(tsec_nitems, sizeof(uint64_t)); tpnt = ucdata; @@ -4827,7 +4827,7 @@ for(;;) int skiplen; uint64_t val = fstGetVarint64(tpnt, &skiplen); tpval = time_table[ti] = tpval + val; - tpnt += skiplen; + tpnt += skiplen; } tc_head = calloc(tsec_nitems /* scan-build */ ? tsec_nitems : 1, sizeof(uint32_t)); @@ -4852,9 +4852,9 @@ for(;;) char wx_buf[32]; int wx_len; - if(beg_tim) - { - wx_len = sprintf(wx_buf, "#%"PRIu64"\n", beg_tim); + if(beg_tim) + { + wx_len = sprintf(wx_buf, "#%"PRIu64"\n", beg_tim); fstWritex(xc, wx_buf, wx_len); } if((xc->num_blackouts)&&(cur_blackout != xc->num_blackouts)) @@ -4944,7 +4944,7 @@ for(;;) int vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); vcd_id[0] = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p'; - fstWritex(xc, vcd_id, 1); + fstWritex(xc, vcd_id, 1); fstWritex(xc,mu+sig_offs, xc->signal_lens[idx]); vcd_id[0] = ' '; /* collapse 3 writes into one I/O call */ @@ -4958,7 +4958,7 @@ for(;;) double d; unsigned char *clone_d; unsigned char *srcdata = mu+sig_offs; - + if(value_change_callback) { if(xc->native_doubles_for_cb) @@ -4970,7 +4970,7 @@ for(;;) else { int j; - + clone_d = (unsigned char *)&d; for(j=0;j<8;j++) { @@ -4989,7 +4989,7 @@ for(;;) else { int j; - + for(j=0;j<8;j++) { clone_d[j] = srcdata[7-j]; @@ -5015,13 +5015,13 @@ for(;;) else { int j; - + for(j=0;j<8;j++) { clone_d[j] = srcdata[7-j]; } } - + fstVcdID(vcdid_buf, idx+1); wx_len = sprintf(wx_buf, "r%.16g %s\n", d, vcdid_buf); fstWritex(xc, wx_buf, wx_len); @@ -5029,7 +5029,7 @@ for(;;) } } } - } + } sig_offs += xc->signal_lens[idx]; } @@ -5062,7 +5062,7 @@ for(;;) if(!chain_cmem) goto block_err; fstReaderFseeko(xc, xc->f, indx_pos, SEEK_SET); fstFread(chain_cmem, chain_clen, 1, xc->f); - + if(vc_maxhandle > vc_maxhandle_largest) { free(chain_table); @@ -5118,7 +5118,7 @@ for(;;) chain_table[idx++] = 0; } } - + pnt += skiplen; } while (pnt != (chain_cmem + chain_clen)); } @@ -5127,7 +5127,7 @@ for(;;) do { int skiplen; uint64_t val = fstGetVarint32(pnt, &skiplen); - + if(!val) { pnt += skiplen; @@ -5136,7 +5136,7 @@ for(;;) chain_table_lengths[idx] = -val; /* because during this loop iter would give stale data! */ idx++; } - else + else if(val&1) { pval = chain_table[idx] = pval + (val >> 1); @@ -5151,7 +5151,7 @@ for(;;) chain_table[idx++] = 0; } } - + pnt += skiplen; } while (pnt != (chain_cmem + chain_clen)); } @@ -5169,7 +5169,7 @@ for(;;) if(((uint32_t)v32) < i) /* sanity check */ { chain_table[i] = chain_table[v32]; - chain_table_lengths[i] = chain_table_lengths[v32]; + chain_table_lengths[i] = chain_table_lengths[v32]; } } } @@ -5196,7 +5196,7 @@ for(;;) uint32_t val; uint32_t skiplen; uint32_t tdelta; - + fstReaderFseeko(xc, xc->f, vc_start + chain_table[i], SEEK_SET); val = fstReaderVarint32WithSkip(xc->f, &skiplen); if(val) @@ -5211,7 +5211,7 @@ for(;;) free(mc_mem); mc_mem = malloc(mc_mem_len = chain_table_lengths[i]); } - mc = mc_mem; + mc = mc_mem; fstFread(mc, chain_table_lengths[i], 1, xc->f); @@ -5240,13 +5240,13 @@ for(;;) length_remaining[i] = destlen; traversal_mem_offs += destlen; } - + if(rc != Z_OK) { printf("\tfac: %d clen: %d (rc=%d)\n", (int)i, (int)val, rc); exit(255); } - + if(xc->signal_lens[i] == 1) { uint32_t vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[i]); @@ -5258,7 +5258,7 @@ for(;;) uint32_t vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[i]); tdelta = vli >> 1; } - + scatterptr[i] = tc_head[tdelta]; tc_head[tdelta] = i+1; } @@ -5302,7 +5302,7 @@ for(;;) previous_time = time_table[i]; } } - + while(tc_head[i]) { idx = tc_head[i] - 1; @@ -5316,7 +5316,7 @@ for(;;) if(!(vli & 1)) { /* tdelta = vli >> 2; */ /* scan-build */ - val = ((vli >> 1) & 1) | '0'; + val = ((vli >> 1) & 1) | '0'; } else { @@ -5332,7 +5332,7 @@ for(;;) } else { - if(fv) + if(fv) { char vcd_id[16]; int vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); @@ -5344,17 +5344,17 @@ for(;;) } headptr[idx] += skiplen; length_remaining[idx] -= skiplen; - + tc_head[i] = scatterptr[idx]; scatterptr[idx] = 0; - + if(length_remaining[idx]) { int shamt; vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]); shamt = 2 << (vli & 1); tdelta = vli >> shamt; - + scatterptr[idx] = tc_head[i+tdelta]; tc_head[i+tdelta] = idx+1; } @@ -5378,13 +5378,13 @@ for(;;) } else { - if(fv) + if(fv) { char vcd_id[16]; int vcdid_len; vcd_id[0] = 's'; - fstWritex(xc, vcd_id, 1); + fstWritex(xc, vcd_id, 1); vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); { @@ -5394,7 +5394,7 @@ for(;;) free(vesc); } - vcd_id[0] = ' '; + vcd_id[0] = ' '; vcd_id[vcdid_len + 1] = '\n'; fstWritex(xc, vcd_id, vcdid_len+2); } @@ -5407,12 +5407,12 @@ for(;;) tc_head[i] = scatterptr[idx]; scatterptr[idx] = 0; - + if(length_remaining[idx]) { vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]); tdelta = vli >> 1; - + scatterptr[idx] = tc_head[i+tdelta]; tc_head[i+tdelta] = idx+1; } @@ -5451,9 +5451,9 @@ for(;;) } else { - if(fv) { + if(fv) { unsigned char ch_bp = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p'; - + fstWritex(xc, &ch_bp, 1); fstWritex(xc, xc->temp_signal_value_buf, len); } @@ -5500,7 +5500,7 @@ for(;;) ch = ((vdata[0] >> bit) & 1) | '0'; buf[j] = ch; } - + len = 1; srcdata = buf; } @@ -5520,7 +5520,7 @@ for(;;) else { int j; - + clone_d = (unsigned char *)&d; for(j=0;j<8;j++) { @@ -5539,7 +5539,7 @@ for(;;) else { int j; - + for(j=0;j<8;j++) { clone_d[j] = srcdata[7-j]; @@ -5564,20 +5564,20 @@ for(;;) else { int j; - + for(j=0;j<8;j++) { clone_d[j] = srcdata[7-j]; } } - + wx_len = sprintf(wx_buf, "r%.16g", d); fstWritex(xc, wx_buf, wx_len); } } } - if(fv) + if(fv) { char vcd_id[16]; int vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); @@ -5592,7 +5592,7 @@ for(;;) tc_head[i] = scatterptr[idx]; scatterptr[idx] = 0; - + if(length_remaining[idx]) { vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]); @@ -5676,7 +5676,7 @@ if(xc->signal_lens[facidx] == 1) clone_d[j] = srcdata[7-j]; } } - + sprintf((char *)buf, "%.16g", d); } } @@ -5790,7 +5790,7 @@ xc->rvat_beg_tim = beg_tim; xc->rvat_end_tim = end_tim; #ifdef FST_DEBUG -mem_required_for_traversal = +mem_required_for_traversal = #endif fstReaderUint64(xc->f); @@ -5816,27 +5816,27 @@ 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, "\ttime section unc: %d, com: %d (%d items)\n", (int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems); -#endif +#endif ucdata = 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); fstFread(cdata, tsec_clen, 1, xc->f); - + rc = uncompress(ucdata, &destlen, cdata, sourcelen); - + if(rc != Z_OK) { printf("tsec uncompress rc = %d\n", rc); exit(255); } - + free(cdata); } else @@ -5852,7 +5852,7 @@ for(ti=0;tirvat_time_table[ti] = tpval + val; - tpnt += skiplen; + tpnt += skiplen; } free(ucdata); @@ -5906,7 +5906,7 @@ fprintf(stderr, "\tindx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen); chain_cmem = 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)); @@ -5926,7 +5926,7 @@ do xc->rvat_chain_table_lengths[idx] = -val; idx++; } - else + else if(val&1) { pval = xc->rvat_chain_table[idx] = pval + (val >> 1); @@ -5941,11 +5941,11 @@ do xc->rvat_chain_table[idx++] = 0; } } - + pnt += skiplen; } while (pnt != (chain_cmem + chain_clen)); -free(chain_cmem); +free(chain_cmem); xc->rvat_chain_table[idx] = indx_pos - xc->rvat_vc_start; xc->rvat_chain_table_lengths[pidx] = xc->rvat_chain_table[idx] - xc->rvat_chain_table[pidx]; @@ -5970,7 +5970,7 @@ fprintf(stderr, "\tdecompressed chain idx len: %"PRIu32"\n", idx); xc->rvat_data_valid = 1; -/* all data at this point is loaded or resident in fst cache, process and return appropriate value */ +/* all data at this point is loaded or resident in fst cache, process and return appropriate value */ process_value: if(facidx > xc->rvat_vc_maxhandle) { @@ -6008,17 +6008,17 @@ if(!xc->rvat_chain_mem) unsigned long destlen = xc->rvat_chain_len; unsigned long sourcelen = xc->rvat_chain_table_lengths[facidx]; int rc; - + fstFread(mc, xc->rvat_chain_table_lengths[facidx], 1, xc->f); rc = uncompress(mu, &destlen, mc, sourcelen); free(mc); - + if(rc != Z_OK) { printf("\tclen: %d (rc=%d)\n", (int)xc->rvat_chain_len, rc); exit(255); } - + /* data to process is for(j=0;jrvat_chain_mem = mu; } @@ -6032,7 +6032,7 @@ if(!xc->rvat_chain_mem) } xc->rvat_chain_facidx = facidx; - } + } /* process value chain here */ @@ -6088,7 +6088,7 @@ if(xc->signal_lens[facidx] == 1) if(!(pvli & 1)) { - buf[0] = ((pvli >> 1) & 1) | '0'; + buf[0] = ((pvli >> 1) & 1) | '0'; } else { @@ -6189,7 +6189,7 @@ if(xc->signal_lens[facidx] == 1) ch = ((vdata[0] >> bit) & 1) | '0'; bufd[j] = ch; } - + srcdata = bufd; } else @@ -6219,7 +6219,7 @@ if(xc->signal_lens[facidx] == 1) { return(fstExtractRvatDataFromFrame(xc, facidx, buf)); } - } + } } /* return(NULL); */ @@ -6246,16 +6246,16 @@ For every delta with one or two bits set, and the deltas of all three have at least 1/4 probability of changing. * If mix() is run forward, every bit of c will change between 1/3 and 2/3 of the time. (Well, 22/100 and 78/100 for some 2-bit deltas.) -mix() was built out of 36 single-cycle latency instructions in a +mix() was built out of 36 single-cycle latency instructions in a structure that could supported 2x parallelism, like so: - a -= b; + a -= b; a -= c; x = (c>>13); b -= c; a ^= x; b -= a; x = (a<<8); c -= a; b ^= x; c -= b; x = (b>>13); ... - Unfortunately, superscalar Pentiums and Sparcs can't take advantage + Unfortunately, superscalar Pentiums and Sparcs can't take advantage of that parallelism. They've also turned some of those single-cycle latency instructions into multi-cycle latency instructions. Still, this is the fastest good hash I could find. There were about 2^^68 @@ -6396,8 +6396,8 @@ while(chain) chain = calloc(1, sizeof(struct collchain_t) + length - 1); memcpy(chain->mem, mem, length); -chain->fullhash = hf; -chain->length = length; +chain->fullhash = hf; +chain->length = length; chain->next = ar[h]; ar[h] = chain; return(&(chain->payload)); diff --git a/vpi/fstapi.h b/vpi/fstapi.h index d45a3894e..bc02f66f4 100644 --- a/vpi/fstapi.h +++ b/vpi/fstapi.h @@ -51,7 +51,7 @@ enum fstFileType { FST_FT_VERILOG = 0, FST_FT_VHDL = 1, - FST_FT_VERILOG_VHDL = 2, + FST_FT_VERILOG_VHDL = 2, FST_FT_MAX = 2 }; @@ -118,7 +118,7 @@ enum fstVarType { FST_VT_VCD_REG = 5, FST_VT_VCD_SUPPLY0 = 6, FST_VT_VCD_SUPPLY1 = 7, - FST_VT_VCD_TIME = 8, + FST_VT_VCD_TIME = 8, FST_VT_VCD_TRI = 9, FST_VT_VCD_TRIAND = 10, FST_VT_VCD_TRIOR = 11, diff --git a/vpi/lxt2_write.c b/vpi/lxt2_write.c index c53854d04..38b11f602 100644 --- a/vpi/lxt2_write.c +++ b/vpi/lxt2_write.c @@ -30,18 +30,18 @@ static char *lxt2_wr_vcd_truncate_bitvec(char *s) { -char l, r; +char l, r; r=*s; -if(r=='1') +if(r=='1') { return s; - } + } else { s++; } - + for(;;s++) { l=r; r=*s; @@ -50,7 +50,7 @@ for(;;s++) if(l!=r) { return(((l=='0')&&(r=='1'))?s:s-1); - } + } } } @@ -155,7 +155,7 @@ static lxt2_wr_ds_Tree * lxt2_wr_ds_insert(granmsk_t i, lxt2_wr_ds_Tree * t, int /* Insert i into the tree t, unless it's already there. */ /* Return a pointer to the resulting tree. */ lxt2_wr_ds_Tree * n; - + n = (lxt2_wr_ds_Tree *) calloc (1, sizeof (lxt2_wr_ds_Tree)); if (n == NULL) { fprintf(stderr, "ds_insert: ran out of memory, exiting.\n"); @@ -245,7 +245,7 @@ static lxt2_wr_dslxt_Tree * lxt2_wr_dslxt_insert(char *i, lxt2_wr_dslxt_Tree * t /* Return a pointer to the resulting tree. */ lxt2_wr_dslxt_Tree * n; int dir; - + n = (lxt2_wr_dslxt_Tree *) calloc (1, sizeof (lxt2_wr_dslxt_Tree)); if (n == NULL) { fprintf(stderr, "dslxt_insert: ran out of memory, exiting.\n"); @@ -281,7 +281,7 @@ static lxt2_wr_dslxt_Tree * lxt2_wr_dslxt_insert(char *i, lxt2_wr_dslxt_Tree * t /* * functions which emit various big endian * data to a file - */ + */ static int lxt2_wr_emit_u8(struct lxt2_wr_trace *lt, int value) { unsigned char buf[1]; @@ -340,7 +340,7 @@ return(rc); * data to a file. (lt->position needs to be * fixed up on gzclose so the tables don't * get out of sync!) - */ + */ static int gzwrite_buffered(struct lxt2_wr_trace *lt) { int rc = 1; @@ -446,7 +446,7 @@ return(rc); static int lxt2_wr_emit_stringz(struct lxt2_wr_trace *lt, char *value) { int rc=1; -do +do { rc&=lxt2_wr_emit_u8z(lt, *value); } while(*(value++)); @@ -473,7 +473,7 @@ for(p=s;*p;p++) { h=h^(g>>24); h=h^g; - } + } } h^=h2; /* combine the two hashes */ @@ -500,17 +500,17 @@ struct lxt2_wr_symbol *temp; hv=lxt2_wr_hash(s); if(!(temp=lt->sym[hv])) return(NULL); /* no hash entry, add here wanted to add */ - + while(temp) { if(!strcmp(temp->name,s)) { - return(temp); /* in table already */ + return(temp); /* in table already */ } if(!temp->next) break; temp=temp->next; } - + return(NULL); /* not found, add here if you want to add*/ } @@ -535,13 +535,13 @@ if(lt->compress_fac_str) lxt2_wr_emit_u16z(lt, i); lxt2_wr_emit_stringz(lt, str+i); free(lt->compress_fac_str); - } + } else { lxt2_wr_emit_u16z(lt, 0); lxt2_wr_emit_stringz(lt, str); } - + lt->compress_fac_str = (char *) malloc((lt->compress_fac_len=len)+1); strcpy(lt->compress_fac_str, str); } @@ -567,10 +567,10 @@ while(lastch!=s->name) if(*lastch=='[') { - *lastch=0x00; + *lastch=0x00; return; } - lastch--; + lastch--; } return; } @@ -597,19 +597,19 @@ if((lt)&&(lt->numfacs)) strip_brack(s); s=s->symchain; } - else + else for(i=0;inumfacs;i++) { lt->sorted_facs[lt->numfacs - i - 1] = s; /* facs were chained backwards so reverse to restore bitslicing */ s=s->symchain; - } + } wave_msort(lt->sorted_facs, lt->numfacs); if(lt->partial_preference) { /* move preferenced facs up */ struct lxt2_wr_symbol **prefcache = aliascache; - int prefs_encountered = 0; + int prefs_encountered = 0; facs_encountered = 0; for(i=0;inumfacs;i++) @@ -700,7 +700,7 @@ if((lt)&&(lt->numfacs)) free(lt->compress_fac_str); lt->compress_fac_str=NULL; lt->compress_fac_len=0; lt->zfacname_predec_size = lt->zpackcount; - + gzflush_buffered(lt, 1); fseeko(lt->handle, 0L, SEEK_END); lt->position=ftello(lt->handle); @@ -746,7 +746,7 @@ if((lt)&&(lt->numfacs)) } -/* +/* * initialize the trace and get back an lt context */ struct lxt2_wr_trace *lxt2_wr_init(const char *name) @@ -805,15 +805,15 @@ if(lt) { lt->partial = 1; lt->partial_zip = (zipmode != 0); - lt->partial_iter = LXT2_WR_PARTIAL_SIZE; + lt->partial_iter = LXT2_WR_PARTIAL_SIZE; } } void lxt2_wr_set_partial_preference(struct lxt2_wr_trace *lt, const char *name) { struct lxt2_wr_symbol *s; - -if((lt)&&(name)&&(!lt->sorted_facs)) + +if((lt)&&(name)&&(!lt->sorted_facs)) { s=lxt2_wr_symfind(lt, name); if(s) @@ -852,8 +852,8 @@ if(lt) /* * set initial value of trace (0, 1, x, z) only legal vals */ -void lxt2_wr_set_initial_value(struct lxt2_wr_trace *lt, char value) -{ +void lxt2_wr_set_initial_value(struct lxt2_wr_trace *lt, char value) +{ if(lt) { switch(value) @@ -991,7 +991,7 @@ return(sa); } -/* +/* * set current time/granule updating */ int lxt2_wr_inc_time_by_delta(struct lxt2_wr_trace *lt, unsigned int timeval) @@ -1221,7 +1221,7 @@ if(using_partial) lxt2_wr_emit_u32(lt, partial_length+9); /* size of this section (uncompressed) */ lxt2_wr_emit_u32(lt, iter); /* begin iter of section */ fflush(lt->handle); - + lt->zhandle = gzdopen(dup(fileno(lt->handle)), lt->zmode); lt->zpackcount = 0; } @@ -1331,7 +1331,7 @@ if((lt->timegranule>=lt->maxgranule)||(do_finalize)||(early_flush)) lxt2_wr_emit_u32(lt, 0); /* size of this section (uncompressed) */ lxt2_wr_emit_u32(lt, ~0); /* control section */ fflush(lt->handle); - + lt->zhandle = gzdopen(dup(fileno(lt->handle)), lt->zmode); lt->zpackcount = 0; } @@ -1354,9 +1354,9 @@ if((lt->timegranule>=lt->maxgranule)||(do_finalize)||(early_flush)) exit(255); } - lxt2_wr_emit_stringz(lt, ds->item); + lxt2_wr_emit_stringz(lt, ds->item); ds2 = ds->next; - free(ds->item); + free(ds->item); free(ds); ds = ds2; } @@ -1382,7 +1382,7 @@ if((lt->timegranule>=lt->maxgranule)||(do_finalize)||(early_flush)) #endif dt2 = dt->next; - free(dt); + free(dt); dt = dt2; } lt->mapdict_head = lt->mapdict_curr = lt->mapdict = NULL; @@ -1399,11 +1399,11 @@ if((lt->timegranule>=lt->maxgranule)||(do_finalize)||(early_flush)) if(using_partial_zip) { off_t c_len; - + gzflush_buffered(lt, 1); fseeko(lt->handle, 0L, SEEK_END); lt->position=ftello(lt->handle); - + c_len = lt->position - current_iter_pos - 12; fseeko(lt->handle, current_iter_pos, SEEK_SET); @@ -1467,7 +1467,7 @@ if(lt) { lt->bumptime = 0; - if(!lt->flush_valid) + if(!lt->flush_valid) { lt->timepos++; } @@ -1475,7 +1475,7 @@ if(lt) { lt->flush_valid = 0; } - + if(lt->timepos == LXT2_WR_GRANULE_SIZE) { /* fprintf(stderr, "flushing granule to disk at time %d\n", (unsigned int)timeval); */ @@ -1484,7 +1484,7 @@ if(lt) } /* fprintf(stderr, "updating time to %d (%d dict entries/%d bytes)\n", (unsigned int)timeval, lt->num_dict_entries, lt->dict_string_mem_required); */ - lt->timetable[lt->timepos] = timeval; + lt->timetable[lt->timepos] = timeval; lt->lasttime = timeval; } } @@ -1493,7 +1493,7 @@ if(lt) lt->timeset = 1; lt->mintime = lt->maxtime = timeval; - lt->timetable[lt->timepos] = timeval; + lt->timetable[lt->timepos] = timeval; } if( (!lt->timepos) && (!lt->timegranule) ) @@ -1524,7 +1524,7 @@ if(lt) else if (s->flags&LXT2_WR_SYM_F_DOUBLE) { double value = 0; - + sscanf(s->value, "%lg", &value); errno = 0; lxt2_wr_emit_value_double(lt, s, 0, value); @@ -1625,7 +1625,7 @@ int rc=0; if((!lt)||(lt->blackout)||(!s)||(row)) return(rc); -if(!lt->emitted) +if(!lt->emitted) { lxt2_wr_emitfacs(lt); lt->emitted = 1; @@ -1666,7 +1666,7 @@ if(s->flags&LXT2_WR_SYM_F_DOUBLE) if(lt->dict_curr) { - lt->dict_curr->next = lt->dict; + lt->dict_curr->next = lt->dict; lt->dict_curr = lt->dict; } else @@ -1707,7 +1707,7 @@ int rc=0; if((!lt)||(lt->blackout)||(!s)||(!value)||(row)) return(rc); -if(!lt->emitted) +if(!lt->emitted) { lxt2_wr_emitfacs(lt); lt->emitted = 1; @@ -1746,7 +1746,7 @@ if(s->flags&LXT2_WR_SYM_F_STRING) if(lt->dict_curr) { - lt->dict_curr->next = lt->dict; + lt->dict_curr->next = lt->dict; lt->dict_curr = lt->dict; } else @@ -1791,7 +1791,7 @@ int i; if((!lt)||(lt->blackout)||(!s)||(!value)||(!*value)||(row)) return(rc); -if(!lt->emitted) +if(!lt->emitted) { lxt2_wr_emitfacs(lt); lt->emitted = 1; @@ -1856,12 +1856,12 @@ if(!(s->flags&(LXT2_WR_SYM_F_DOUBLE|LXT2_WR_SYM_F_STRING))) prevch = *vpnt; while(*vpnt) { - if(prevch == *vpnt) + if(prevch == *vpnt) { vpnt++; } else - { + { prevch = 0; break; } @@ -1968,7 +1968,7 @@ idxchk: if(idx<0) if(lt->dict_curr) { - lt->dict_curr->next = lt->dict; + lt->dict_curr->next = lt->dict; lt->dict_curr = lt->dict; } else @@ -2016,15 +2016,15 @@ struct lxt2_wr_symbol *s; if((lt)&&(!lt->blackout)) { - if(!lt->emitted) + if(!lt->emitted) { lxt2_wr_emitfacs(lt); lt->emitted = 1; - + if(!lt->timeset) { lxt2_wr_set_time(lt, 0); - } + } } s = lt->symchain; @@ -2036,7 +2036,7 @@ if((lt)&&(!lt->blackout)) { s->msk |= (LXT2_WR_GRAN_1VAL<timepos); s->chg[s->chgpos] = LXT2_WR_ENC_BLACKOUT; - + s->chgpos++; } else @@ -2158,7 +2158,7 @@ if(lt) { struct lxt2_wr_symbol *s = lt->symchain; struct lxt2_wr_symbol *s2; - + while(s) { free(s->name); @@ -2170,7 +2170,7 @@ if(lt) lt->symchain=NULL; } - + free(lt->lxtname); free(lt->sorted_facs); fclose(lt->handle); @@ -2193,13 +2193,13 @@ if(lt) /* - * time zero offset + * time zero offset */ -void lxt2_wr_set_timezero(struct lxt2_wr_trace *lt, lxtstime_t timeval) -{ +void lxt2_wr_set_timezero(struct lxt2_wr_trace *lt, lxtstime_t timeval) +{ if(lt) - { + { lt->timezero = timeval; - } + } } diff --git a/vpi/lxt2_write.h b/vpi/lxt2_write.h index f1487fb34..8c9a47b68 100644 --- a/vpi/lxt2_write.h +++ b/vpi/lxt2_write.h @@ -3,19 +3,19 @@ * * 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: + * 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 + * 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 + * 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. */ @@ -83,12 +83,12 @@ typedef unsigned long long granmsk_t; #define LXT2_WR_GRAN_1VAL (LXT2_WR_ULLDESC(1)) #else typedef unsigned int granmsk_t; -#define LXT2_WR_GRAN_0VAL (0) +#define LXT2_WR_GRAN_0VAL (0) #define LXT2_WR_GRAN_1VAL (1) #endif -enum LXT2_WR_Encodings { +enum LXT2_WR_Encodings { LXT2_WR_ENC_0, LXT2_WR_ENC_1, LXT2_WR_ENC_INV, @@ -132,12 +132,12 @@ struct lxt2_wr_ds_tree_node { */ typedef struct lxt2_wr_dslxt_tree_node lxt2_wr_dslxt_Tree; struct lxt2_wr_dslxt_tree_node { - lxt2_wr_dslxt_Tree * left, * right; + lxt2_wr_dslxt_Tree * left, * right; char *item; unsigned int val; lxt2_wr_dslxt_Tree * next; }; - + struct lxt2_wr_trace { diff --git a/vpi/lxt_write.c b/vpi/lxt_write.c index 9e9cf2ea9..2ff8bcb5a 100644 --- a/vpi/lxt_write.c +++ b/vpi/lxt_write.c @@ -132,7 +132,7 @@ static dslxt_Tree * dslxt_insert(char *i, dslxt_Tree * t, unsigned int val) { /* Return a pointer to the resulting tree. */ dslxt_Tree * n; int dir; - + n = (dslxt_Tree *) calloc (1, sizeof (dslxt_Tree)); if (n == NULL) { fprintf(stderr, "dslxt_insert: ran out of memory, exiting.\n"); @@ -190,7 +190,7 @@ static dslxt_Tree * dslxt_delete(char *i, dslxt_Tree * t) { /* * functions which emit various big endian * data to a file - */ + */ static int lt_emit_u8(struct lt_trace *lt, int value) { unsigned char buf[1]; @@ -271,7 +271,7 @@ return(nmemb); static int lt_emit_string(struct lt_trace *lt, char *value) { int rc=1; -do +do { rc&=lt_emit_u8(lt, *value); } while(*(value++)); @@ -284,7 +284,7 @@ return(rc); * data to a file. (lt->position needs to be * fixed up on gzclose so the tables don't * get out of sync!) - */ + */ static int lt_emit_u8z(struct lt_trace *lt, int value) { unsigned char buf[1]; @@ -371,7 +371,7 @@ return(nmemb); static int lt_emit_stringz(struct lt_trace *lt, char *value) { int rc=1; -do +do { rc&=lt_emit_u8z(lt, *value); } while(*(value++)); @@ -383,7 +383,7 @@ return(rc); * data to a file. (lt->position needs to be * fixed up on BZ2_bzclose so the tables don't * get out of sync!) - */ + */ static int lt_emit_u8bz(struct lt_trace *lt, int value) { unsigned char buf[1]; @@ -470,7 +470,7 @@ return(nmemb); static int lt_emit_stringbz(struct lt_trace *lt, char *value) { int rc=1; -do +do { rc&=lt_emit_u8bz(lt, *value); } while(*(value++)); @@ -537,7 +537,7 @@ for(p=s;*p;p++) { h=h^(g>>24); h=h^g; - } + } } h^=h2; /* combine the two hashes */ @@ -564,17 +564,17 @@ struct lt_symbol *temp; hv=lt_hash(s); if(!(temp=lt->sym[hv])) return(NULL); /* no hash entry, add here wanted to add */ - + while(temp) { if(!strcmp(temp->name,s)) { - return(temp); /* in table already */ + return(temp); /* in table already */ } if(!temp->next) break; temp=temp->next; } - + return(NULL); /* not found, add here if you want to add*/ } @@ -599,13 +599,13 @@ if(lt->compress_fac_str) lt_emit_u16z(lt, i); lt_emit_stringz(lt, str+i); free(lt->compress_fac_str); - } + } else { lt_emit_u16z(lt, 0); lt_emit_stringz(lt, str); } - + lt->compress_fac_str = (char *) malloc((lt->compress_fac_len=len)+1); strcpy(lt->compress_fac_str, str); } @@ -626,10 +626,10 @@ while(lastch!=s->name) if(*lastch=='[') { - *lastch=0x00; + *lastch=0x00; return; } - lastch--; + lastch--; } return; } @@ -655,12 +655,12 @@ if((lt)&&(lt->numfacs)) strip_brack(s); s=s->symchain; } - else + else for(i=0;inumfacs;i++) { lt->sorted_facs[lt->numfacs - i - 1] = s; /* facs were chained backwards so reverse to restore bitslicing*/ s=s->symchain; - } + } wave_msort(lt->sorted_facs, lt->numfacs); for(i=0;inumfacs;i++) @@ -688,7 +688,7 @@ if((lt)&&(lt->numfacs)) free(lt->compress_fac_str); lt->compress_fac_str=NULL; lt->compress_fac_len=0; lt->zfacname_predec_size = lt->zpackcount; - + gzclose(lt->zhandle); fseeko(lt->handle, 0L, SEEK_END); lt->position=ftello(lt->handle); @@ -723,13 +723,13 @@ if((lt)&&(lt->numfacs)) if(is_interlaced_trace) { lt->zhandle = gzdopen(dup(fileno(lt->handle)), "wb9"); - + lt->sync_table_offset = lt->position; for(i=0;inumfacs;i++) { lt_emit_u32z(lt, lt->sorted_facs[i]->last_change); } - + gzclose(lt->zhandle); lt->zhandle = NULL; fseeko(lt->handle, 0L, SEEK_END); lt->position=ftello(lt->handle); @@ -740,7 +740,7 @@ if((lt)&&(lt->numfacs)) } -/* +/* * initialize the trace and get back an lt context */ struct lt_trace *lt_init(const char *name) @@ -866,7 +866,7 @@ switch(numbytes_trans&3) case 3: lt->lt_emit_u32(lt, numtrans); break; } -/* printf("Clock finish for '%s' at %lld ending with '%c' for %d repeats over a switch delta of %d\n", +/* printf("Clock finish for '%s' at %lld ending with '%c' for %d repeats over a switch delta of %d\n", s->name, lt->timeval, s->clk_prevval, s->clk_numtrans - LT_CLKPACK, s->clk_delta); */ s->clk_prevtrans = ULLDescriptor(~0); s->clk_numtrans = 0; @@ -967,7 +967,7 @@ switch(numbytes_trans&3) case 3: lt->lt_emit_u32(lt, numtrans); break; } -/* printf("Clock finish for '%s' at %lld ending with '%08x' for %d repeats over a switch delta of %lld\n", +/* printf("Clock finish for '%s' at %lld ending with '%08x' for %d repeats over a switch delta of %lld\n", s->name, lt->timeval, s->clk_prevval, s->clk_numtrans - LT_CLKPACK_M, s->clk_delta); */ s->clk_prevtrans = ULLDescriptor(~0); s->clk_numtrans = 0; @@ -1035,7 +1035,7 @@ for(i=0;inum_dict_entries;i++) /* fprintf(stderr, "%8d) '%s'\n", ds->val, ds->item); */ lt_emit_stringz(lt, ds->item+1); } - + gzclose(lt->zhandle); fseeko(lt->handle, 0L, SEEK_END); lt->position=ftello(lt->handle); @@ -1072,13 +1072,13 @@ if(lt) if(s->clk_numtrans > LT_CLKPACK_M) lt_flushclock_m(lt, s); } else - { + { if(s->clk_numtrans > LT_CLKPACK) lt_flushclock(lt, s); } } - + s=s->symchain; - } + } lt_set_dumpon(lt); /* in case it was turned off */ @@ -1134,7 +1134,7 @@ if(lt) while(t) { lt_emit_u32z(lt, t->position - lastposition); lastposition = t->position; - t=t->next; + t=t->next; } t=lt->timehead; @@ -1144,9 +1144,9 @@ if(lt) { lxttime_t delta = t->timeval - lasttime; lt_emit_u64z(lt, (int)(delta>>32), (int)delta); lasttime = t->timeval; - + t2=t->next; - free(t); + free(t); t=t2; } } @@ -1155,12 +1155,12 @@ if(lt) while(t) { lt_emit_u32z(lt, (int)(t->timeval - lasttime)); lasttime = t->timeval; - + t2=t->next; - free(t); + free(t); t=t2; } - + lt->timehead = lt->timecurr = NULL; } @@ -1170,7 +1170,7 @@ if(lt) lt->ztime_table_size = lt->position - lt->ztime_table_size; } - if(lt->initial_value>=0) + if(lt->initial_value>=0) { lt->initial_value_offset = lt->position; lt_emit_u8(lt, lt->initial_value); @@ -1185,7 +1185,7 @@ if(lt) if(lt->double_used) { lt->double_test_offset = lt->position; - lt_emit_double(lt, 3.14159); + lt_emit_double(lt, 3.14159); } if(lt->dumpoffcount) @@ -1201,7 +1201,7 @@ if(lt) lt_emit_u64(lt, (int)((ltt->timeval)>>32), (int)ltt->timeval); ltt2 = ltt; ltt=ltt->next; - free(ltt2); + free(ltt2); } lt->dumpoffhead = lt->dumpoffcurr = NULL; @@ -1253,7 +1253,7 @@ if(lt) { struct lt_symbol *sc = lt->symchain; struct lt_symbol *s2; - + while(sc) { free(sc->name); @@ -1262,7 +1262,7 @@ if(lt) sc=s2; } } - + free(lt->sorted_facs); fclose(lt->handle); free(lt); @@ -1368,7 +1368,7 @@ return(sa); } -/* +/* * set current time */ int lt_inc_time_by_delta(struct lt_trace *lt, unsigned int timeval) @@ -1407,7 +1407,7 @@ if(lt) else { free(trl); - goto bail; + goto bail; } } else @@ -1485,7 +1485,7 @@ if((lt)&&(!lt->emitted)) } /* - * sets change interlace + * sets change interlace */ void lt_set_no_interlace(struct lt_trace *lt) { @@ -1510,12 +1510,12 @@ if((lt)&&(!lt->emitted)&&(!lt->sorted_facs)) strip_brack(s); s=s->symchain; } - else + else for(i=0;inumfacs;i++) { lt->sorted_facs[lt->numfacs - i - 1] = s; /* facs were chained backwards so reverse to restore bitslicing */ s=s->symchain; - } + } wave_msort(lt->sorted_facs, lt->numfacs); for(i=0;inumfacs;i++) @@ -1555,12 +1555,12 @@ if(lt) { int tag; switch(value) - { + { case '0': tag = 0; break; case '1': tag = 1; break; - case 'Z': + case 'Z': case 'z': tag = 2; break; - case 'X': + case 'X': case 'x': tag = 3; break; case 'H': case 'h': tag = 4; break; @@ -1686,7 +1686,7 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) s->clk_mask <<= 1; s->clk_mask |= 1; - if( ((s->clk_mask&0x1f)==0x1f) && + if( ((s->clk_mask&0x1f)==0x1f) && ( (delta1=(ivalue - s->clk_prevval1) & lt_optimask[s->len]) == ((s->clk_prevval1 - s->clk_prevval3) & lt_optimask[s->len]) ) && ( (delta2=(s->clk_prevval - s->clk_prevval2) & lt_optimask[s->len]) == ((s->clk_prevval2 - s->clk_prevval4) & lt_optimask[s->len]) ) && ( (delta1==delta2) || ((!delta1)&&(!delta2)) ) @@ -1862,7 +1862,7 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) { tag = (numbytes<<4); } - + lt->lt_emit_u8(lt, tag); switch(numbytes&3) { @@ -1883,7 +1883,7 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) } lt->lt_emit_u8(lt, optimized ? (3+optimized1) : 0); } - + s->last_change = start_position; if(s->rows>0) @@ -1949,7 +1949,7 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) { if(lt->num_dict_entries==(256*65536)) lt->dict32_offset = lt->position; } - + lt->num_dict_entries++; } @@ -1994,14 +1994,14 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) value <<= (24-len); rc=lt->lt_emit_u24(lt, value); } - else + else { value <<= (32-len); rc=lt->lt_emit_u32(lt, value); } } - } - + } + if(lt->timebuff) { lt->timechangecount++; @@ -2063,7 +2063,7 @@ if((s->flags)<_SYM_F_DOUBLE) { numbytes = 0; } - + start_position = lt->position; s->last_change = start_position; @@ -2119,7 +2119,7 @@ if((s->flags)<_SYM_F_DOUBLE) } rc=lt->lt_emit_double(lt, value); - + if(lt->timebuff) { lt->timechangecount++; @@ -2181,7 +2181,7 @@ if((s->flags)<_SYM_F_STRING) { numbytes = 0; } - + start_position = lt->position; s->last_change = start_position; @@ -2237,7 +2237,7 @@ if((s->flags)<_SYM_F_STRING) } rc=lt->lt_emit_string(lt, value); - + if(lt->timebuff) { lt->timechangecount++; @@ -2318,7 +2318,7 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) s->clk_mask <<= 1; s->clk_mask |= legal; - if( ((s->clk_mask&0x1f)==0x1f) && + if( ((s->clk_mask&0x1f)==0x1f) && ( (delta1=(ivalue - s->clk_prevval1) & lt_optimask[s->len]) == ((s->clk_prevval1 - s->clk_prevval3) & lt_optimask[s->len]) ) && ( (delta2=(s->clk_prevval - s->clk_prevval2) & lt_optimask[s->len]) == ((s->clk_prevval2 - s->clk_prevval4) & lt_optimask[s->len]) ) && ( (delta1==delta2) || ((!delta1)&&(!delta2)) ) @@ -2350,7 +2350,7 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) s->clk_prevval1 = s->clk_prevval; s->clk_prevval = ivalue; - /* printf("Clock value '%08x' for '%s' [len=%d] at %lld (#%d)\n", + /* printf("Clock value '%08x' for '%s' [len=%d] at %lld (#%d)\n", ivalue, s->name, len, lt->timeval, s->clk_numtrans); */ return(1); } @@ -2480,12 +2480,12 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) while((ch=*(pnt++))) { switch(ch) - { + { case '0': case '1': mvl|=LT_MVL_2; break; - case 'Z': - case 'z': - case 'X': + case 'Z': + case 'z': + case 'X': case 'x': mvl|=LT_MVL_4; break; default: mvl|=LT_MVL_9; break; } @@ -2494,13 +2494,13 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) } switch(prevch) - { + { case 0x00: tagadd = 0; break; case '0': tagadd = 3; break; case '1': tagadd = 4; break; - case 'Z': + case 'Z': case 'z': tagadd = 5; break; - case 'X': + case 'X': case 'x': tagadd = 6; break; case 'H': case 'h': tagadd = 7; break; @@ -2597,7 +2597,7 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) int outval = 0; int thisval= 0; - pnt = value; + pnt = value; if((lt->dictmode)&&(len2>lt->mindictwidth)) { @@ -2628,7 +2628,7 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) { if(lt->num_dict_entries==(256*65536)) lt->dict32_offset = lt->position; } - + lt->num_dict_entries++; } @@ -2666,8 +2666,8 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) outval |= (thisval<lt_emit_u8(lt, outval); + { + lt->lt_emit_u8(lt, outval); outval = 0; bitpos = 7; } @@ -2681,7 +2681,7 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) int outval = 0; int thisval= 0; - pnt = value; + pnt = value; for(i=0;iflags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) outval |= (thisval<lt_emit_u8(lt, outval); + { + lt->lt_emit_u8(lt, outval); outval = 0; bitpos = 6; } @@ -2715,7 +2715,7 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) int outval = 0; int thisval= 0; - pnt = value; + pnt = value; for(i=0;iflags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) outval |= (thisval<lt_emit_u8(lt, outval); + { + lt->lt_emit_u8(lt, outval); outval = 0; bitpos = 4; } @@ -2755,7 +2755,7 @@ if(!(s->flags&(LT_SYM_F_DOUBLE|LT_SYM_F_STRING))) rc=1; } - + if(lt->timebuff) { lt->timechangecount++; diff --git a/vpi/lxt_write.h b/vpi/lxt_write.h index 8fbb0a797..48a60fcb0 100644 --- a/vpi/lxt_write.h +++ b/vpi/lxt_write.h @@ -3,19 +3,19 @@ * * 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: + * 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 + * 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 + * 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. */ @@ -47,11 +47,11 @@ extern "C" { typedef struct dslxt_tree_node dslxt_Tree; struct dslxt_tree_node { - dslxt_Tree * left, * right; + dslxt_Tree * left, * right; char *item; unsigned int val; }; - + #define LT_HDRID (0x0138) #define LT_VERSION (0x0004) @@ -180,7 +180,7 @@ unsigned double_used : 1; unsigned do_strip_brackets : 1; unsigned clock_compress : 1; unsigned dictmode : 1; /* dictionary compression enabled */ -unsigned zmode : 2; /* for value changes */ +unsigned zmode : 2; /* for value changes */ unsigned emitted : 1; /* gate off change field zmode changes when set */ }; @@ -252,9 +252,9 @@ void lt_set_dumpoff(struct lt_trace *lt); void lt_set_dumpon(struct lt_trace *lt); /* - * value change functions..note that if the value string len for - * lt_emit_value_bit_string() is shorter than the symbol length - * it will be left justified with the rightmost character used as + * value change functions..note that if the value string len for + * lt_emit_value_bit_string() is shorter than the symbol length + * it will be left justified with the rightmost character used as * a repeat value that will be propagated to pad the value string out: * * "10x" for 8 bits becomes "10xxxxxx" diff --git a/vpi/wavealloca.h b/vpi/wavealloca.h index ac2416d62..4be2e4937 100644 --- a/vpi/wavealloca.h +++ b/vpi/wavealloca.h @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Tony Bybell 1999. * * This program is free software; you can redistribute it and/or @@ -10,7 +10,7 @@ #ifndef WAVE_ALLOCA_H #define WAVE_ALLOCA_H #include -#if HAVE_ALLOCA_H +#ifdef HAVE_ALLOCA_H #include #elif defined(__GNUC__) #ifndef __MINGW32__ @@ -25,5 +25,5 @@ #define alloca _alloca #endif #define wave_alloca alloca -#endif +#endif From 12379ed26acd00344b86c081fc156aad70c024da Mon Sep 17 00:00:00 2001 From: Cary R Date: Sat, 7 Jun 2014 18:20:19 -0700 Subject: [PATCH 050/245] Fix spacing issue. --- synth2.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/synth2.cc b/synth2.cc index 169c216eb..f203cc92a 100644 --- a/synth2.cc +++ b/synth2.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002-2012 Stephen Williams (steve@icarus.com) + * Copyright (c) 2002-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -614,7 +614,7 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, if (mux_width < mux_lwidth && if_ && else_) { if (debug_synth2) { cerr << get_fileline() << ": NetCondit::synth_async: " - << "This MetMux only impacts a few bits of output," + << "This MetMux only impacts a few bits of output," << " so combine nex_out with statement input." << endl; cerr << get_fileline() << ": NetCondit::synth_async: " From 35a8485a44c3aa1bf6e1100bd6c127c3d8fa67db Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Wed, 28 May 2014 09:10:18 -0700 Subject: [PATCH 051/245] Fix some weird lint found by clang Small stuff, no behavior change expected. --- driver/main.c | 2 +- t-dll-api.cc | 2 +- t-dll.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/driver/main.c b/driver/main.c index d0b286c47..79b416bbe 100644 --- a/driver/main.c +++ b/driver/main.c @@ -71,7 +71,7 @@ const char HELP[] = #endif #include -#if HAVE_GETOPT_H +#ifdef HAVE_GETOPT_H #include #endif diff --git a/t-dll-api.cc b/t-dll-api.cc index 4fcd623f8..8966563b3 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -1648,7 +1648,7 @@ extern "C" const char* ivl_nexus_name(ivl_nexus_t net) assert(net); if (net->name_ == 0) { char tmp[2 * sizeof(net) + 5]; - snprintf(tmp, sizeof tmp, "n%p", net); + snprintf(tmp, sizeof tmp, "n%p", (void *)net); net->name_ = api_strings.add(tmp); } return net->name_; diff --git a/t-dll.h b/t-dll.h index f357ab384..d9ae83c74 100644 --- a/t-dll.h +++ b/t-dll.h @@ -625,7 +625,7 @@ struct ivl_parameter_s { */ struct ivl_process_s { ivl_process_type_t type_ : 2; - int analog_flag : 1; + unsigned int analog_flag : 1; ivl_scope_t scope_; ivl_statement_t stmt_; perm_string file; From 855bf9cfe8b479c0da3a842f7740a48aff8c3b71 Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Wed, 28 May 2014 09:25:50 -0700 Subject: [PATCH 052/245] Pick some low-hanging const fruit Makes more of the code const-correct; there are still plenty of difficult-to-fix const problems left. No behavior change expected. --- tgt-stub/expression.c | 2 +- tgt-vlog95/expr.c | 4 ++-- tgt-vlog95/scope.c | 2 +- tgt-vlog95/stmt.c | 5 +++-- tgt-vvp/draw_class.c | 2 +- tgt-vvp/draw_net_input.c | 2 +- tgt-vvp/vvp_scope.c | 2 +- vpi/sys_countdrivers.c | 2 +- vpi/sys_queue.c | 2 +- 9 files changed, 12 insertions(+), 11 deletions(-) diff --git a/tgt-stub/expression.c b/tgt-stub/expression.c index e80857e31..610802a5d 100644 --- a/tgt-stub/expression.c +++ b/tgt-stub/expression.c @@ -231,7 +231,7 @@ static void show_property_expression(ivl_expr_t net, unsigned ind) { ivl_signal_t sig = ivl_expr_signal(net); const char* pnam = ivl_expr_name(net); - char*signed_flag = ivl_expr_signed(net)? "signed" : "unsigned"; + const char*signed_flag = ivl_expr_signed(net)? "signed" : "unsigned"; if (ivl_expr_value(net) == IVL_VT_REAL) { fprintf(out, "%*s\n", ind, "", diff --git a/tgt-vlog95/expr.c b/tgt-vlog95/expr.c index e8f6810ad..e31bd7450 100644 --- a/tgt-vlog95/expr.c +++ b/tgt-vlog95/expr.c @@ -401,7 +401,7 @@ static unsigned calc_can_skip_unsigned(ivl_expr_t oper1, ivl_expr_t oper2) static void emit_expr_binary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid, unsigned is_full_prec) { - char *oper = ""; + const char *oper = ""; ivl_expr_t oper1 = ivl_expr_oper1(expr); ivl_expr_t oper2 = ivl_expr_oper2(expr); unsigned can_skip_unsigned = calc_can_skip_unsigned(oper1, oper2); @@ -976,7 +976,7 @@ static void emit_expr_ternary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid, static void emit_expr_unary(ivl_scope_t scope, ivl_expr_t expr, unsigned wid, unsigned is_full_prec) { - char *oper = "invalid"; + const char *oper = "invalid"; ivl_expr_t oper1 = ivl_expr_oper1(expr); switch (ivl_expr_opcode(expr)) { case '-': oper = "-"; break; diff --git a/tgt-vlog95/scope.c b/tgt-vlog95/scope.c index 43640d497..91cf9797a 100644 --- a/tgt-vlog95/scope.c +++ b/tgt-vlog95/scope.c @@ -24,7 +24,7 @@ const char *func_rtn_name = 0; -static char*get_time_const(int time_value) +static const char*get_time_const(int time_value) { switch (time_value) { case 2: return "100s"; diff --git a/tgt-vlog95/stmt.c b/tgt-vlog95/stmt.c index 530c9e471..d5c2c037d 100644 --- a/tgt-vlog95/stmt.c +++ b/tgt-vlog95/stmt.c @@ -408,7 +408,8 @@ static void emit_assign_and_opt_opcode(ivl_scope_t scope, ivl_statement_t stmt, unsigned allow_opcode) { unsigned wid; - char opcode, *opcode_str; + char opcode; + const char *opcode_str; assert (ivl_statement_type(stmt) == IVL_ST_ASSIGN); // HERE: Do we need to calculate the width? The compiler should have already @@ -941,7 +942,7 @@ static void emit_stmt_block_named(ivl_scope_t scope, ivl_statement_t stmt) static void emit_stmt_case(ivl_scope_t scope, ivl_statement_t stmt) { - char *case_type; + const char *case_type; unsigned idx, default_case, count = ivl_stmt_case_count(stmt); switch (ivl_statement_type(stmt)) { case IVL_ST_CASE: diff --git a/tgt-vvp/draw_class.c b/tgt-vvp/draw_class.c index c0e538831..4fcafd894 100644 --- a/tgt-vvp/draw_class.c +++ b/tgt-vvp/draw_class.c @@ -30,7 +30,7 @@ static void show_prop_type_vector(ivl_type_t ptype) unsigned packed_dimensions = ivl_type_packed_dimensions(ptype); assert(packed_dimensions < 2); - char*signed_flag = ivl_type_signed(ptype)? "s" : ""; + const char*signed_flag = ivl_type_signed(ptype)? "s" : ""; char code = data_type==IVL_VT_BOOL? 'b' : 'L'; if (packed_dimensions == 0) { diff --git a/tgt-vvp/draw_net_input.c b/tgt-vvp/draw_net_input.c index 3ee73d36b..67a4a7849 100644 --- a/tgt-vvp/draw_net_input.c +++ b/tgt-vvp/draw_net_input.c @@ -230,7 +230,7 @@ static void str_repeat(char*buf, const char*str, unsigned rpt) * If the drive strength is strong we can draw a C4<> constant as the * pull value, otherwise we need to draw a C8<> constant. */ -static char* draw_net_pull(ivl_net_logic_t lptr, ivl_drive_t drive, char*level) +static char* draw_net_pull(ivl_net_logic_t lptr, ivl_drive_t drive, const char*level) { char*result; char tmp[32]; diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 7a8632367..99c6fe73f 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -1804,7 +1804,7 @@ static int sfunc_has_modpath_output(ivl_lpm_t lptr) static void draw_sfunc_output_def(ivl_lpm_t net, char type) { ivl_nexus_t nex = ivl_lpm_q(net); - char *suf = (type == 'd') ? "/d" : ""; + const char *suf = (type == 'd') ? "/d" : ""; switch (data_type_of_nexus(nex)) { case IVL_VT_REAL: diff --git a/vpi/sys_countdrivers.c b/vpi/sys_countdrivers.c index 304672ec8..417d20b5a 100644 --- a/vpi/sys_countdrivers.c +++ b/vpi/sys_countdrivers.c @@ -102,7 +102,7 @@ static PLI_INT32 sys_countdrivers_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) /* The optional arguments must be variables. */ for (arg_num = 2; arg_num < 7; arg_num += 1) { - char *arg_name = NULL; + const char *arg_name = NULL; switch (arg_num) { case 2: arg_name = "second"; break; case 3: arg_name = "third"; break; diff --git a/vpi/sys_queue.c b/vpi/sys_queue.c index 4f1dc0e25..7f2d19f6d 100644 --- a/vpi/sys_queue.c +++ b/vpi/sys_queue.c @@ -587,7 +587,7 @@ static unsigned check_numeric_args(vpiHandle argv, unsigned count, /* Check that the first count arguments are numeric. Currently * only three are needed/supported. */ for (idx = 0; idx < count; idx += 1) { - char *loc = NULL; + const char *loc = NULL; vpiHandle arg = vpi_scan(argv); /* Get the name for this argument. */ From 529e029abdcf55304bd6d416eeae4bacc5d414ec Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Mon, 9 Jun 2014 22:40:26 +0100 Subject: [PATCH 053/245] Fix for GitHub issue #28 - Insufficient string escaping in vvp script. " characters in strings must be escaped when the compiler writes a quoted string to a vvp script. This patch fixes up a few places where this wasn't being done. --- tgt-vvp/vvp_scope.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 99c6fe73f..5afdc9fbf 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2012 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -2151,8 +2151,10 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) } fprintf(vvp_out, "S_%p .scope %s%s, \"%s\" \"%s\" %d %d", - net, prefix, type, vvp_mangle_name(ivl_scope_basename(net)), - ivl_scope_tname(net), ivl_file_table_index(ivl_scope_file(net)), + net, prefix, type, + vvp_mangle_name(ivl_scope_basename(net)), + vvp_mangle_name(ivl_scope_tname(net)), + ivl_file_table_index(ivl_scope_file(net)), ivl_scope_lineno(net)); if (parent) { @@ -2177,7 +2179,8 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) if( name == 0 ) name = ""; fprintf( vvp_out, " .port_info %u %s %u \"%s\"\n", - idx, vvp_port_info_type_str(ptype), width, name ); + idx, vvp_port_info_type_str(ptype), width, + vvp_mangle_name(name) ); } } @@ -2187,7 +2190,7 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) switch (ivl_expr_type(pex)) { case IVL_EX_STRING: fprintf(vvp_out, "P_%p .param/str \"%s\" %d %d %d, \"%s\";\n", - par, ivl_parameter_basename(par), + par, vvp_mangle_name(ivl_parameter_basename(par)), ivl_parameter_local(par), ivl_file_table_index(ivl_parameter_file(par)), ivl_parameter_lineno(par), @@ -2195,7 +2198,7 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) break; case IVL_EX_NUMBER: fprintf(vvp_out, "P_%p .param/l \"%s\" %d %d %d, %sC4<", - par, ivl_parameter_basename(par), + par, vvp_mangle_name(ivl_parameter_basename(par)), ivl_parameter_local(par), ivl_file_table_index(ivl_parameter_file(par)), ivl_parameter_lineno(par), @@ -2211,8 +2214,9 @@ int draw_scope(ivl_scope_t net, ivl_scope_t parent) case IVL_EX_REALNUM: { char *res = draw_Cr_to_string(ivl_expr_dvalue(pex)); fprintf(vvp_out, "P_%p .param/real \"%s\" %d %d %d, %s; " - "value=%#g\n", par, ivl_parameter_basename(par), - ivl_parameter_local(par), + "value=%#g\n", par, + vvp_mangle_name(ivl_parameter_basename(par)), + ivl_parameter_local(par), ivl_file_table_index(ivl_parameter_file(par)), ivl_parameter_lineno(par), res, ivl_expr_dvalue(pex)); From 6a45a0d5703f47af85c67dbd73c1de737b0a5dbb Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Mon, 9 Jun 2014 22:21:51 -0700 Subject: [PATCH 054/245] Don't lie to the c++ about some pointer alignment Second try cleaning up cast-alignment problems surrounding need_result_buf(). Clang gave a bunch of warnings like vvp/vpi_const.cc:196:34: warning: cast from 'char *' to 'p_vpi_vecval' (aka 't_vpi_vecval *') increases required alignment from 1 to 4 [-Wcast-align] This version is verbose and changes the prototype for need_result_buf(). But it is semantically (c++) correct, and makes need_result_buf() feel like malloc(). --- vvp/vpi_callback.cc | 4 ++-- vvp/vpi_const.cc | 12 ++++++------ vvp/vpi_priv.cc | 20 ++++++++++---------- vvp/vpi_priv.h | 2 +- vvp/vpi_signal.cc | 24 ++++++++++++------------ vvp/vpi_string.cc | 4 ++-- vvp/vpi_time.cc | 4 ++-- vvp/vpi_vthr_vector.cc | 16 ++++++++-------- 8 files changed, 43 insertions(+), 43 deletions(-) diff --git a/vvp/vpi_callback.cc b/vvp/vpi_callback.cc index 86b549d87..cf12f0850 100644 --- a/vvp/vpi_callback.cc +++ b/vvp/vpi_callback.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -760,7 +760,7 @@ void vvp_signal_value::get_signal_value(struct t_vpi_value*vp) static void real_signal_value(struct t_vpi_value*vp, double rval) { - char*rbuf = need_result_buf(64 + 1, RBUF_VAL); + char*rbuf = (char *) need_result_buf(64 + 1, RBUF_VAL); switch (vp->format) { case vpiObjTypeVal: diff --git a/vvp/vpi_const.cc b/vvp/vpi_const.cc index 8406fade9..438e6cfd8 100644 --- a/vvp/vpi_const.cc +++ b/vvp/vpi_const.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2012 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -131,7 +131,7 @@ void __vpiStringConst::vpi_get_value(p_vpi_value vp) vp->format = vpiStringVal; case vpiStringVal: - rbuf = need_result_buf(size + 1, RBUF_VAL); + rbuf = (char *) need_result_buf(size + 1, RBUF_VAL); strcpy(rbuf, value_); vp->value.str = rbuf; break; @@ -143,7 +143,7 @@ void __vpiStringConst::vpi_get_value(p_vpi_value vp) fprintf(stderr, "Warning (vpi_const.cc): %%d on constant strings only looks " "at first 4 bytes!\n"); } - rbuf = need_result_buf(size + 1, RBUF_VAL); + rbuf = (char *) need_result_buf(size + 1, RBUF_VAL); uint_value = 0; for(unsigned i=0; i=0; bit -= 1){ @@ -166,7 +166,7 @@ void __vpiStringConst::vpi_get_value(p_vpi_value vp) break; case vpiHexStrVal: - rbuf = need_result_buf(2 * size + 1, RBUF_VAL); + rbuf = (char *) need_result_buf(2 * size + 1, RBUF_VAL); cp = rbuf; for(unsigned i=0; i=0; nibble -= 1){ @@ -571,7 +571,7 @@ int __vpiDecConst::vpi_get(int code) void __vpiDecConst::vpi_get_value(p_vpi_value vp) { - char*rbuf = need_result_buf(64 + 1, RBUF_VAL); + char*rbuf = (char *) need_result_buf(64 + 1, RBUF_VAL); char*cp = rbuf; switch (vp->format) { diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index 043320dc6..5b1cc0975 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2008-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -584,7 +584,7 @@ static void vec4_get_value_string(const vvp_vector4_t&word_val, unsigned width, unsigned nchar = width / 8; unsigned tail = width % 8; - char*rbuf = need_result_buf(nchar + 1, RBUF_VAL); + char*rbuf = (char *) need_result_buf(nchar + 1, RBUF_VAL); char*cp = rbuf; if (tail > 0) { @@ -636,7 +636,7 @@ void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width, break; case vpiBinStrVal: - rbuf = need_result_buf(width+1, RBUF_VAL); + rbuf = (char *) need_result_buf(width+1, RBUF_VAL); for (unsigned idx = 0 ; idx < width ; idx += 1) { vvp_bit4_t bit = word_val.value(idx); rbuf[width-idx-1] = vvp_bit4_to_ascii(bit); @@ -647,7 +647,7 @@ void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width, case vpiOctStrVal: { unsigned hwid = ((width+2) / 3) + 1; - rbuf = need_result_buf(hwid, RBUF_VAL); + rbuf = (char *) need_result_buf(hwid, RBUF_VAL); vpip_vec4_to_oct_str(word_val, rbuf, hwid); vp->value.str = rbuf; break; @@ -655,7 +655,7 @@ void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width, case vpiDecStrVal: { // HERE need a better estimate. - rbuf = need_result_buf(width+1, RBUF_VAL); + rbuf = (char *) need_result_buf(width+1, RBUF_VAL); vpip_vec4_to_dec_str(word_val, rbuf, width+1, signed_flag); vp->value.str = rbuf; break; @@ -663,7 +663,7 @@ void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width, case vpiHexStrVal: { unsigned hwid = ((width + 3) / 4) + 1; - rbuf = need_result_buf(hwid, RBUF_VAL); + rbuf = (char *) need_result_buf(hwid, RBUF_VAL); vpip_vec4_to_hex_str(word_val, rbuf, hwid); vp->value.str = rbuf; break; @@ -714,7 +714,7 @@ void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width, case vpiVectorVal: { unsigned hwid = (width + 31)/32; - rbuf = need_result_buf(hwid * sizeof(s_vpi_vecval), RBUF_VAL); + rbuf = (char *) need_result_buf(hwid * sizeof(s_vpi_vecval), RBUF_VAL); s_vpi_vecval *op = (p_vpi_vecval)rbuf; vp->value.vector = op; @@ -779,7 +779,7 @@ void vpip_vec2_get_value(const vvp_vector2_t&word_val, unsigned width, case vpiVectorVal: { unsigned hwid = (width + 31)/32; - rbuf = need_result_buf(hwid * sizeof(s_vpi_vecval), RBUF_VAL); + rbuf = (char *) need_result_buf(hwid * sizeof(s_vpi_vecval), RBUF_VAL); s_vpi_vecval *op = (p_vpi_vecval)rbuf; vp->value.vector = op; @@ -860,7 +860,7 @@ void vpip_real_get_value(double real, s_vpi_value*vp) break; case vpiDecStrVal: - rbuf = need_result_buf(1025, RBUF_VAL); + rbuf = (char *) need_result_buf(1025, RBUF_VAL); vpip_vec4_to_dec_str(vvp_vector4_t(1024, real), rbuf, 1025, true); vp->value.str = rbuf; break; @@ -934,7 +934,7 @@ void vpip_string_get_value(const string&val, s_vpi_value*vp) vp->format = vpiStringVal; case vpiStringVal: - rbuf = need_result_buf(val.size() + 1, RBUF_VAL); + rbuf = (char *) need_result_buf(val.size() + 1, RBUF_VAL); strcpy(rbuf, val.c_str()); vp->value.str = rbuf; break; diff --git a/vvp/vpi_priv.h b/vvp/vpi_priv.h index 0f6c0b693..8e6c9b2ad 100644 --- a/vvp/vpi_priv.h +++ b/vvp/vpi_priv.h @@ -789,7 +789,7 @@ enum vpi_rbuf_t { RBUF_DEL /* Delete the storage for both buffers. */ }; -extern char *need_result_buf(unsigned cnt, vpi_rbuf_t type); +extern void *need_result_buf(unsigned cnt, vpi_rbuf_t type); /* following two routines use need_result_buf(, RBUF_STR) */ extern char *simple_set_rbuf_str(const char *s1); extern char *generic_get_str(int code, vpiHandle ref, const char *name, const char *index); diff --git a/vvp/vpi_signal.cc b/vvp/vpi_signal.cc index edd39adf9..22005b27c 100644 --- a/vvp/vpi_signal.cc +++ b/vvp/vpi_signal.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -62,9 +62,9 @@ extern const char oct_digits[64]; * buffer can be reused for that purpose. Whenever I have a need, the * need_result_buf function makes sure that need can be met. */ -char *need_result_buf(unsigned cnt, vpi_rbuf_t type) +void *need_result_buf(unsigned cnt, vpi_rbuf_t type) { - static char*result_buf[2] = {0, 0}; + static void*result_buf[2] = {0, 0}; static size_t result_buf_size[2] = {0, 0}; if (type == RBUF_DEL) { @@ -82,10 +82,10 @@ char *need_result_buf(unsigned cnt, vpi_rbuf_t type) cnt = (cnt + 0x0fff) & ~0x0fff; if (result_buf_size[type] == 0) { - result_buf[type] = (char*)malloc(cnt); + result_buf[type] = malloc(cnt); result_buf_size[type] = cnt; } else if (result_buf_size[type] < cnt) { - result_buf[type] = (char*)realloc(result_buf[type], cnt); + result_buf[type] = realloc(result_buf[type], cnt); result_buf_size[type] = cnt; } @@ -94,7 +94,7 @@ char *need_result_buf(unsigned cnt, vpi_rbuf_t type) char *simple_set_rbuf_str(const char *s1) { - char *res = need_result_buf(strlen(s1)+1, RBUF_STR); + char *res = (char *) need_result_buf(strlen(s1)+1, RBUF_STR); if (res) strcpy(res,s1); return res; } @@ -109,7 +109,7 @@ char *generic_get_str(int code, vpiHandle ref, const char *name, const char *ind } if (index != NULL) len += strlen(index) + 2; /* include space for brackets */ - char *res = need_result_buf(len, RBUF_STR); + char *res = (char *) need_result_buf(len, RBUF_STR); if (!res) { free(bn); return NULL; @@ -143,7 +143,7 @@ static vpiHandle fill_in_net4(struct __vpiSignal*obj, static void format_vpiBinStrVal(vvp_signal_value*sig, int base, unsigned wid, s_vpi_value*vp) { - char *rbuf = need_result_buf(wid+1, RBUF_VAL); + char *rbuf = (char *) need_result_buf(wid+1, RBUF_VAL); long end = base + (signed)wid; long offset = end - 1; long ssize = (signed)sig->value_size(); @@ -164,7 +164,7 @@ static void format_vpiOctStrVal(vvp_signal_value*sig, int base, unsigned wid, s_vpi_value*vp) { unsigned dwid = (wid + 2) / 3; - char *rbuf = need_result_buf(dwid+1, RBUF_VAL); + char *rbuf = (char *) need_result_buf(dwid+1, RBUF_VAL); long end = base + (signed)wid; long ssize = (signed)sig->value_size(); unsigned val = 0; @@ -220,7 +220,7 @@ static void format_vpiHexStrVal(vvp_signal_value*sig, int base, unsigned wid, s_vpi_value*vp) { unsigned dwid = (wid + 3) / 4; - char *rbuf = need_result_buf(dwid+1, RBUF_VAL); + char *rbuf = (char *) need_result_buf(dwid+1, RBUF_VAL); long end = base + (signed)wid; long ssize = (signed)sig->value_size(); unsigned val = 0; @@ -280,7 +280,7 @@ static void format_vpiDecStrVal(vvp_signal_value*sig, int base, unsigned wid, int signed_flag, s_vpi_value*vp) { unsigned hwid = (sig->value_size()+2) / 3 + 1; - char *rbuf = need_result_buf(hwid, RBUF_VAL); + char *rbuf = (char *) need_result_buf(hwid, RBUF_VAL); long ssize = (signed)sig->value_size(); long end = base + (signed)wid; @@ -366,7 +366,7 @@ static void format_vpiStringVal(vvp_signal_value*sig, int base, unsigned wid, /* The result will use a character for each 8 bits of the vector. Add one extra character for the highest bits that don't form an 8 bit group. */ - char *rbuf = need_result_buf(wid/8 + ((wid&7)!=0) + 1, RBUF_VAL); + char *rbuf = (char *) need_result_buf(wid/8 + ((wid&7)!=0) + 1, RBUF_VAL); char *cp = rbuf; char tmp = 0; diff --git a/vvp/vpi_string.cc b/vvp/vpi_string.cc index 6a1bd10d4..58aa6a664 100644 --- a/vvp/vpi_string.cc +++ b/vvp/vpi_string.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012 Stephen Williams (steve@icarus.com) + * Copyright (c) 2012-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -63,7 +63,7 @@ void __vpiStringVar::vpi_get_value(p_vpi_value val) string str = fun->get_string(); if (val->format == vpiStringVal || val->format == vpiObjTypeVal) { - char*rbuf = need_result_buf(str.size()+1, RBUF_VAL); + char*rbuf = (char *) need_result_buf(str.size()+1, RBUF_VAL); strcpy(rbuf, str.c_str()); val->format = vpiStringVal; val->value.str = rbuf; diff --git a/vvp/vpi_time.cc b/vvp/vpi_time.cc index 78b314caa..ab7c66fac 100644 --- a/vvp/vpi_time.cc +++ b/vvp/vpi_time.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2012 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -106,7 +106,7 @@ static void timevar_get_value(vpiHandle ref, s_vpi_value*vp, bool is_int_func, vvp_time64_t x, simtime = schedule_simtime(); int units = rfp->scope? rfp->scope->time_units : vpi_time_precision; - char*rbuf = need_result_buf(128, RBUF_VAL); + char*rbuf = (char *) need_result_buf(128, RBUF_VAL); /* Calculate the divisor needed to scale the simulation time (in time_precision units) to time units of the scope. */ diff --git a/vvp/vpi_vthr_vector.cc b/vvp/vpi_vthr_vector.cc index cfae01cbf..fae93ab90 100644 --- a/vvp/vpi_vthr_vector.cc +++ b/vvp/vpi_vthr_vector.cc @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2001-2014 Stephen Williams (steve@icarus.com) * Copyright (c) 2001 Stephan Boettcher * * This source code is free software; you can redistribute it @@ -124,7 +124,7 @@ static char* vthr_vec_get_str(int code, vpiHandle ref) static void vthr_vec_DecStrVal(struct __vpiVThrVec*rfp, s_vpi_value*vp) { int nbuf = (rfp->wid+2)/3 + 1; - char *rbuf = need_result_buf(nbuf, RBUF_VAL); + char *rbuf = (char *) need_result_buf(nbuf, RBUF_VAL); vvp_vector4_t tmp (rfp->wid); for (unsigned idx = 0 ; idx < rfp->wid ; idx += 1) @@ -139,7 +139,7 @@ static void vthr_vec_DecStrVal(struct __vpiVThrVec*rfp, s_vpi_value*vp) static void vthr_vec_StringVal(struct __vpiVThrVec*rfp, s_vpi_value*vp) { char tmp = 0; - char *rbuf = need_result_buf((rfp->wid / 8) + 1, RBUF_VAL); + char *rbuf = (char *) need_result_buf((rfp->wid / 8) + 1, RBUF_VAL); char *cp = rbuf; for(int bitnr=rfp->wid-1; bitnr>=0; bitnr--){ @@ -186,7 +186,7 @@ static void vthr_vec_get_value(vpiHandle ref, s_vpi_value*vp) switch (vp->format) { case vpiBinStrVal: - rbuf = need_result_buf(wid+1, RBUF_VAL); + rbuf = (char *) need_result_buf(wid+1, RBUF_VAL); for (unsigned idx = 0 ; idx < wid ; idx += 1) { rbuf[wid-idx-1] = vvp_bit4_to_ascii(get_bit(rfp, idx)); } @@ -197,7 +197,7 @@ static void vthr_vec_get_value(vpiHandle ref, s_vpi_value*vp) case vpiHexStrVal: { unsigned hval, hwid; hwid = (wid + 3) / 4; - rbuf = need_result_buf(hwid+1, RBUF_VAL); + rbuf = (char *) need_result_buf(hwid+1, RBUF_VAL); rbuf[hwid] = 0; hval = 0; for (unsigned idx = 0 ; idx < wid ; idx += 1) { @@ -237,7 +237,7 @@ static void vthr_vec_get_value(vpiHandle ref, s_vpi_value*vp) case vpiOctStrVal: { unsigned hval, hwid; hwid = (wid + 2) / 3; - rbuf = need_result_buf(hwid+1, RBUF_VAL); + rbuf = (char *) need_result_buf(hwid+1, RBUF_VAL); rbuf[hwid] = 0; hval = 0; for (unsigned idx = 0 ; idx < wid ; idx += 1) { @@ -521,7 +521,7 @@ static int vthr_word_get(int code, vpiHandle ref) static void vthr_real_get_value(vpiHandle ref, s_vpi_value*vp) { struct __vpiVThrWord*obj = dynamic_cast<__vpiVThrWord*>(ref); - char *rbuf = need_result_buf(66, RBUF_VAL); + char *rbuf = (char *) need_result_buf(66, RBUF_VAL); double val = 0.0; @@ -689,7 +689,7 @@ void __vpiVThrStrStack::vpi_get_value(p_vpi_value vp) case vpiObjTypeVal: vp->format = vpiStringVal; case vpiStringVal: - rbuf = need_result_buf(val.size()+1, RBUF_VAL); + rbuf = (char *) need_result_buf(val.size()+1, RBUF_VAL); strcpy(rbuf, val.c_str()); vp->value.str = rbuf; break; From 1e18d431073d15c0355bb8e9822252be8e1d5ade Mon Sep 17 00:00:00 2001 From: Larry Doolittle Date: Tue, 10 Jun 2014 10:58:38 -0700 Subject: [PATCH 055/245] Tie up simple loose ends for need_result_buf() vvp/ is now free of -Wcast-align errors --- vvp/vpi_priv.cc | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/vvp/vpi_priv.cc b/vvp/vpi_priv.cc index 5b1cc0975..9cf1b97a6 100644 --- a/vvp/vpi_priv.cc +++ b/vvp/vpi_priv.cc @@ -714,8 +714,8 @@ void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width, case vpiVectorVal: { unsigned hwid = (width + 31)/32; - rbuf = (char *) need_result_buf(hwid * sizeof(s_vpi_vecval), RBUF_VAL); - s_vpi_vecval *op = (p_vpi_vecval)rbuf; + s_vpi_vecval *op = (p_vpi_vecval) + need_result_buf(hwid * sizeof(s_vpi_vecval), RBUF_VAL); vp->value.vector = op; op->aval = op->bval = 0; @@ -759,8 +759,6 @@ void vpip_vec4_get_value(const vvp_vector4_t&word_val, unsigned width, void vpip_vec2_get_value(const vvp_vector2_t&word_val, unsigned width, bool signed_flag, s_vpi_value*vp) { - char *rbuf = 0; - switch (vp->format) { default: fprintf(stderr, "sorry: Format %d not implemented for " @@ -779,8 +777,8 @@ void vpip_vec2_get_value(const vvp_vector2_t&word_val, unsigned width, case vpiVectorVal: { unsigned hwid = (width + 31)/32; - rbuf = (char *) need_result_buf(hwid * sizeof(s_vpi_vecval), RBUF_VAL); - s_vpi_vecval *op = (p_vpi_vecval)rbuf; + s_vpi_vecval *op = (p_vpi_vecval) + need_result_buf(hwid * sizeof(s_vpi_vecval), RBUF_VAL); vp->value.vector = op; op->aval = op->bval = 0; From 2bc9cb90ddfd86f8f8d1c5ff1e9bf32501d472ea Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 11 Jun 2014 08:37:24 -0700 Subject: [PATCH 056/245] Update fstapi files to latest ones from GTKWave --- vpi/fstapi.c | 7037 +++++++++++++++++++++++++------------------------- vpi/fstapi.h | 270 +- 2 files changed, 3654 insertions(+), 3653 deletions(-) diff --git a/vpi/fstapi.c b/vpi/fstapi.c index 331879741..05c2a82b2 100644 --- a/vpi/fstapi.c +++ b/vpi/fstapi.c @@ -82,7 +82,7 @@ #include #else /* should be more than enough for fstWriterSetSourceStem() */ -#define FST_PATH_HASHMASK ((1UL << 16) - 1) +#define FST_PATH_HASHMASK ((1UL << 16) - 1) typedef const void *Pcvoid_t; typedef void *Pvoid_t; typedef void **PPvoid_t; @@ -94,7 +94,7 @@ void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint3 #ifndef FST_WRITEX_DISABLE -#define FST_WRITEX_MAX (64 * 1024) +#define FST_WRITEX_MAX (64 * 1024) #else #define fstWritex(a,b,c) fstFwrite((b), (c), 1, fv) #endif @@ -103,22 +103,22 @@ void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint3 /* these defines have a large impact on writer speed when a model has a */ /* huge number of symbols. as a default, use 128MB and increment when */ /* every 1M signals are defined. */ -#define FST_BREAK_SIZE (1UL << 27) -#define FST_BREAK_ADD_SIZE (1UL << 22) -#define FST_BREAK_SIZE_MAX (1UL << 31) -#define FST_ACTIVATE_HUGE_BREAK (1000000) -#define FST_ACTIVATE_HUGE_INC (1000000) +#define FST_BREAK_SIZE (1UL << 27) +#define FST_BREAK_ADD_SIZE (1UL << 22) +#define FST_BREAK_SIZE_MAX (1UL << 31) +#define FST_ACTIVATE_HUGE_BREAK (1000000) +#define FST_ACTIVATE_HUGE_INC (1000000) -#define FST_WRITER_STR "fstWriter" -#define FST_ID_NAM_SIZ (512) -#define FST_ID_NAM_ATTR_SIZ (65536+4096) -#define FST_DOUBLE_ENDTEST (2.7182818284590452354) -#define FST_HDR_SIM_VERSION_SIZE (128) -#define FST_HDR_DATE_SIZE (119) -#define FST_HDR_FILETYPE_SIZE (1) -#define FST_HDR_TIMEZERO_SIZE (8) -#define FST_GZIO_LEN (32768) -#define FST_HDR_FOURPACK_DUO_SIZE (4*1024*1024) +#define FST_WRITER_STR "fstWriter" +#define FST_ID_NAM_SIZ (512) +#define FST_ID_NAM_ATTR_SIZ (65536+4096) +#define FST_DOUBLE_ENDTEST (2.7182818284590452354) +#define FST_HDR_SIM_VERSION_SIZE (128) +#define FST_HDR_DATE_SIZE (119) +#define FST_HDR_FILETYPE_SIZE (1) +#define FST_HDR_TIMEZERO_SIZE (8) +#define FST_GZIO_LEN (32768) +#define FST_HDR_FOURPACK_DUO_SIZE (4*1024*1024) #if defined(__i386__) || defined(__x86_64__) || defined(_AIX) #define FST_DO_MISALIGNED_OPS @@ -190,33 +190,33 @@ UINT uRetVal = 0; FILE *fh = NULL; 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__); - exit(255); - } - else - { - uRetVal = GetTempFileName(lpTempPathBuffer, TEXT("FSTW"), 0, szTempFileName); - if (uRetVal == 0) - { - fprintf(stderr, "GetTempFileName() failed in "__FILE__" line %d, exiting.\n", __LINE__); - exit(255); - } - else - { - fname = strdup(szTempFileName); - } - } + { + dwRetVal = GetTempPath(MAX_PATH, lpTempPathBuffer); + if((dwRetVal > MAX_PATH) || (dwRetVal == 0)) + { + fprintf(stderr, "GetTempPath() failed in "__FILE__" line %d, exiting.\n", __LINE__); + exit(255); + } + else + { + uRetVal = GetTempFileName(lpTempPathBuffer, TEXT("FSTW"), 0, szTempFileName); + if (uRetVal == 0) + { + fprintf(stderr, "GetTempFileName() failed in "__FILE__" line %d, exiting.\n", __LINE__); + exit(255); + } + else + { + fname = strdup(szTempFileName); + } + } - if(fname) - { - *nam = fname; - fh = unlink_fopen(fname, "w+b"); - } - } + if(fname) + { + *nam = fname; + fh = unlink_fopen(fname, "w+b"); + } + } return(fh); } @@ -236,19 +236,19 @@ return(f); static void tmpfile_close(FILE **f, char **nam) { if(f) - { - if(*f) { fclose(*f); *f = NULL; } - } + { + if(*f) { fclose(*f); *f = NULL; } + } if(nam) - { - if(*nam) - { - unlink(*nam); - free(*nam); - *nam = NULL; - } - } + { + if(*nam) + { + unlink(*nam); + free(*nam); + *nam = NULL; + } + } } /*****************************************/ @@ -310,7 +310,7 @@ return(NULL); #if defined __CYGWIN__ || defined __MINGW32__ #include #define fstMmap(__addr,__len,__prot,__flags,__fd,__off) fstMmap2((__len), (__fd), (__off)) -#define fstMunmap(__addr,__len) free(__addr) +#define fstMunmap(__addr,__len) free(__addr) static void *fstMmap2(size_t __len, int __fd, off_t __off) { @@ -320,9 +320,9 @@ size_t i; lseek(__fd, 0, SEEK_SET); for(i=0;i<__len;i+=SSIZE_MAX) - { - read(__fd, pnt + i, ((__len - i) >= SSIZE_MAX) ? SSIZE_MAX : (__len - i)); - } + { + read(__fd, pnt + i, ((__len - i) >= SSIZE_MAX) ? SSIZE_MAX : (__len - i)); + } lseek(__fd, cur_offs, SEEK_SET); return(pnt); } @@ -334,7 +334,7 @@ return(pnt); #define FST_CADDR_T_CAST #endif #define fstMmap(__addr,__len,__prot,__flags,__fd,__off) (void*)mmap(FST_CADDR_T_CAST (__addr),(__len),(__prot),(__flags),(__fd),(__off)) -#define fstMunmap(__addr,__len) { if(__addr) munmap(FST_CADDR_T_CAST (__addr),(__len)); } +#define fstMunmap(__addr,__len) { if(__addr) munmap(FST_CADDR_T_CAST (__addr),(__len)); } #endif @@ -365,10 +365,10 @@ unsigned char buf[8]; int i; for(i=7;i>=0;i--) - { - buf[i] = v & 0xff; - v >>= 8; - } + { + buf[i] = v & 0xff; + v >>= 8; + } fstFwrite(buf, 8, 1, handle); return(8); @@ -379,14 +379,14 @@ static uint64_t fstReaderUint64(FILE *f) { uint64_t val = 0; unsigned char buf[sizeof(uint64_t)]; -int i; +unsigned int i; fstFread(buf, sizeof(uint64_t), 1, f); for(i=0;i>7)) /* determine len to avoid temp buffer copying to cut down on load-hit-store */ { - cnt++; + cnt++; } pnt -= cnt; @@ -472,7 +472,7 @@ cnt--; for(i=0;i>7; + nxt = v>>7; *(spnt++) = ((unsigned char)v) | 0x80; v = nxt; } @@ -530,10 +530,10 @@ uint32_t rc = 0; int ch; do - { - ch = fgetc(f); - *(mem++) = ch; - } while(ch & 0x80); + { + ch = fgetc(f); + *(mem++) = ch; + } while(ch & 0x80); mem--; for(;;) @@ -559,10 +559,10 @@ uint32_t rc = 0; int ch; do - { - ch = fgetc(f); - *(mem++) = ch; - } while(ch & 0x80); + { + ch = fgetc(f); + *(mem++) = ch; + } while(ch & 0x80); *skiplen = mem - buf; mem--; @@ -589,10 +589,10 @@ uint64_t rc = 0; int ch; do - { - ch = fgetc(f); - *(mem++) = ch; - } while(ch & 0x80); + { + ch = fgetc(f); + *(mem++) = ch; + } while(ch & 0x80); mem--; for(;;) @@ -798,13 +798,13 @@ static int fstWriterFseeko(struct fstWriterContext *xc, FILE *stream, off_t offs int rc = fseeko(stream, offset, whence); if(rc<0) - { - xc->fseek_failed = 1; + { + xc->fseek_failed = 1; #ifdef FST_DEBUG - fprintf(stderr, "Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence); - perror("Why"); + fprintf(stderr, "Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence); + perror("Why"); #endif - } + } return(rc); } @@ -884,60 +884,60 @@ char dbuf[FST_HDR_DATE_SIZE]; double endtest = FST_DOUBLE_ENDTEST; time_t walltime; -#define FST_HDR_OFFS_TAG (0) -fputc(FST_BL_HDR, xc->handle); /* +0 tag */ +#define FST_HDR_OFFS_TAG (0) +fputc(FST_BL_HDR, xc->handle); /* +0 tag */ -#define FST_HDR_OFFS_SECLEN (FST_HDR_OFFS_TAG + 1) -fstWriterUint64(xc->handle, 329); /* +1 section length */ +#define FST_HDR_OFFS_SECLEN (FST_HDR_OFFS_TAG + 1) +fstWriterUint64(xc->handle, 329); /* +1 section length */ -#define FST_HDR_OFFS_START_TIME (FST_HDR_OFFS_SECLEN + 8) -fstWriterUint64(xc->handle, 0); /* +9 start time */ +#define FST_HDR_OFFS_START_TIME (FST_HDR_OFFS_SECLEN + 8) +fstWriterUint64(xc->handle, 0); /* +9 start time */ -#define FST_HDR_OFFS_END_TIME (FST_HDR_OFFS_START_TIME + 8) -fstWriterUint64(xc->handle, 0); /* +17 end time */ +#define FST_HDR_OFFS_END_TIME (FST_HDR_OFFS_START_TIME + 8) +fstWriterUint64(xc->handle, 0); /* +17 end time */ -#define FST_HDR_OFFS_ENDIAN_TEST (FST_HDR_OFFS_END_TIME + 8) -fstFwrite(&endtest, 8, 1, xc->handle); /* +25 endian test for reals */ +#define FST_HDR_OFFS_ENDIAN_TEST (FST_HDR_OFFS_END_TIME + 8) +fstFwrite(&endtest, 8, 1, xc->handle); /* +25 endian test for reals */ -#define FST_HDR_OFFS_MEM_USED (FST_HDR_OFFS_ENDIAN_TEST + 8) +#define FST_HDR_OFFS_MEM_USED (FST_HDR_OFFS_ENDIAN_TEST + 8) fstWriterUint64(xc->handle, xc->fst_break_size);/* +33 memory used by writer */ -#define FST_HDR_OFFS_NUM_SCOPES (FST_HDR_OFFS_MEM_USED + 8) -fstWriterUint64(xc->handle, 0); /* +41 scope creation count */ +#define FST_HDR_OFFS_NUM_SCOPES (FST_HDR_OFFS_MEM_USED + 8) +fstWriterUint64(xc->handle, 0); /* +41 scope creation count */ -#define FST_HDR_OFFS_NUM_VARS (FST_HDR_OFFS_NUM_SCOPES + 8) -fstWriterUint64(xc->handle, 0); /* +49 var creation count */ +#define FST_HDR_OFFS_NUM_VARS (FST_HDR_OFFS_NUM_SCOPES + 8) +fstWriterUint64(xc->handle, 0); /* +49 var creation count */ -#define FST_HDR_OFFS_MAXHANDLE (FST_HDR_OFFS_NUM_VARS + 8) -fstWriterUint64(xc->handle, 0); /* +57 max var idcode */ +#define FST_HDR_OFFS_MAXHANDLE (FST_HDR_OFFS_NUM_VARS + 8) +fstWriterUint64(xc->handle, 0); /* +57 max var idcode */ -#define FST_HDR_OFFS_SECTION_CNT (FST_HDR_OFFS_MAXHANDLE + 8) -fstWriterUint64(xc->handle, 0); /* +65 vc section count */ +#define FST_HDR_OFFS_SECTION_CNT (FST_HDR_OFFS_MAXHANDLE + 8) +fstWriterUint64(xc->handle, 0); /* +65 vc section count */ -#define FST_HDR_OFFS_TIMESCALE (FST_HDR_OFFS_SECTION_CNT + 8) -fputc((-9)&255, xc->handle); /* +73 timescale 1ns */ +#define FST_HDR_OFFS_TIMESCALE (FST_HDR_OFFS_SECTION_CNT + 8) +fputc((-9)&255, xc->handle); /* +73 timescale 1ns */ -#define FST_HDR_OFFS_SIM_VERSION (FST_HDR_OFFS_TIMESCALE + 1) +#define FST_HDR_OFFS_SIM_VERSION (FST_HDR_OFFS_TIMESCALE + 1) memset(vbuf, 0, FST_HDR_SIM_VERSION_SIZE); strcpy(vbuf, FST_WRITER_STR); fstFwrite(vbuf, FST_HDR_SIM_VERSION_SIZE, 1, xc->handle); /* +74 version */ -#define FST_HDR_OFFS_DATE (FST_HDR_OFFS_SIM_VERSION + FST_HDR_SIM_VERSION_SIZE) +#define FST_HDR_OFFS_DATE (FST_HDR_OFFS_SIM_VERSION + FST_HDR_SIM_VERSION_SIZE) memset(dbuf, 0, FST_HDR_DATE_SIZE); time(&walltime); strcpy(dbuf, asctime(localtime(&walltime))); -fstFwrite(dbuf, FST_HDR_DATE_SIZE, 1, xc->handle); /* +202 date */ +fstFwrite(dbuf, FST_HDR_DATE_SIZE, 1, xc->handle); /* +202 date */ /* date size is deliberately overspecified at 119 bytes (originally 128) in order to provide backfill for new args */ -#define FST_HDR_OFFS_FILETYPE (FST_HDR_OFFS_DATE + FST_HDR_DATE_SIZE) -fputc(xc->filetype, xc->handle); /* +321 filetype */ +#define FST_HDR_OFFS_FILETYPE (FST_HDR_OFFS_DATE + FST_HDR_DATE_SIZE) +fputc(xc->filetype, xc->handle); /* +321 filetype */ -#define FST_HDR_OFFS_TIMEZERO (FST_HDR_OFFS_FILETYPE + FST_HDR_FILETYPE_SIZE) -fstWriterUint64(xc->handle, xc->timezero); /* +322 timezero */ +#define FST_HDR_OFFS_TIMEZERO (FST_HDR_OFFS_FILETYPE + FST_HDR_FILETYPE_SIZE) +fstWriterUint64(xc->handle, xc->timezero); /* +322 timezero */ -#define FST_HDR_LENGTH (FST_HDR_OFFS_TIMEZERO + FST_HDR_TIMEZERO_SIZE) - /* +330 next section starts here */ +#define FST_HDR_LENGTH (FST_HDR_OFFS_TIMEZERO + FST_HDR_TIMEZERO_SIZE) + /* +330 next section starts here */ fflush(xc->handle); } @@ -965,15 +965,15 @@ fflush(xc->handle); /* do mappings */ 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); - } + { + 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); + } 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); - } + { + fflush(xc->curval_handle); + xc->curval_mem = fstMmap(NULL, xc->maxvalpos, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->curval_handle), 0); + } } @@ -984,23 +984,23 @@ xc->valpos_mem = NULL; #if defined __CYGWIN__ || defined __MINGW32__ if(xc->curval_mem) - { - if(!is_closing) /* need to flush out for next emulated mmap() read */ - { - unsigned char *pnt = xc->curval_mem; - int __fd = fileno(xc->curval_handle); - off_t cur_offs = lseek(__fd, 0, SEEK_CUR); - size_t i; - size_t __len = xc->maxvalpos; + { + if(!is_closing) /* need to flush out for next emulated mmap() read */ + { + unsigned char *pnt = xc->curval_mem; + int __fd = fileno(xc->curval_handle); + off_t cur_offs = lseek(__fd, 0, SEEK_CUR); + size_t i; + size_t __len = xc->maxvalpos; - lseek(__fd, 0, SEEK_SET); - for(i=0;i<__len;i+=SSIZE_MAX) - { - write(__fd, pnt + i, ((__len - i) >= SSIZE_MAX) ? SSIZE_MAX : (__len - i)); - } - lseek(__fd, cur_offs, SEEK_SET); - } - } + lseek(__fd, 0, SEEK_SET); + for(i=0;i<__len;i+=SSIZE_MAX) + { + write(__fd, pnt + i, ((__len - i) >= SSIZE_MAX) ? SSIZE_MAX : (__len - i)); + } + lseek(__fd, cur_offs, SEEK_SET); + } + } #endif fstMunmap(xc->curval_mem, xc->maxvalpos); @@ -1021,42 +1021,42 @@ int was_set = 0; FILE *f = fopen("/proc/meminfo", "rb"); if(f) - { - char buf[257]; - char *s; - while(!feof(f)) - { - buf[0] = 0; - s = fgets(buf, 256, f); - if(s && *s) - { - if(!strncmp(s, "MemTotal:", 9)) - { - size_t v = atol(s+10); - v *= 1024; /* convert to bytes */ - v /= 8; /* chop down to 1/8 physical memory */ - if(v > FST_BREAK_SIZE) - { - if(v > FST_BREAK_SIZE_MAX) - { - v = FST_BREAK_SIZE_MAX; - } + { + char buf[257]; + char *s; + while(!feof(f)) + { + buf[0] = 0; + s = fgets(buf, 256, f); + if(s && *s) + { + if(!strncmp(s, "MemTotal:", 9)) + { + size_t v = atol(s+10); + v *= 1024; /* convert to bytes */ + v /= 8; /* chop down to 1/8 physical memory */ + if(v > FST_BREAK_SIZE) + { + if(v > FST_BREAK_SIZE_MAX) + { + v = FST_BREAK_SIZE_MAX; + } - xc->fst_huge_break_size = v; - was_set = 1; - break; - } - } - } - } + xc->fst_huge_break_size = v; + was_set = 1; + break; + } + } + } + } - fclose(f); - } + fclose(f); + } if(!was_set) - { - xc->fst_huge_break_size = FST_BREAK_SIZE; - } + { + xc->fst_huge_break_size = FST_BREAK_SIZE; + } #else int mib[2]; int64_t v; @@ -1066,25 +1066,25 @@ mib[0] = CTL_HW; mib[1] = HW_MEMSIZE; length = sizeof(int64_t); if(!sysctl(mib, 2, &v, &length, NULL, 0)) - { - v /= 8; + { + v /= 8; - if(v > FST_BREAK_SIZE) - { - if(v > FST_BREAK_SIZE_MAX) - { - v = FST_BREAK_SIZE_MAX; - } + if(v > FST_BREAK_SIZE) + { + if(v > FST_BREAK_SIZE_MAX) + { + v = FST_BREAK_SIZE_MAX; + } - xc->fst_huge_break_size = v; - was_set = 1; - } - } + xc->fst_huge_break_size = v; + was_set = 1; + } + } if(!was_set) - { - xc->fst_huge_break_size = FST_BREAK_SIZE; - } + { + xc->fst_huge_break_size = FST_BREAK_SIZE; + } #endif #else xc->fst_huge_break_size = FST_BREAK_SIZE; @@ -1107,55 +1107,55 @@ xc->compress_hier = use_compressed_hier; fstDetermineBreakSize(xc); if((!nam)|| - (!(xc->handle=unlink_fopen(nam, "w+b")))) + (!(xc->handle=unlink_fopen(nam, "w+b")))) { free(xc); xc=NULL; } else { - int flen = strlen(nam); - char *hf = calloc(1, flen + 6); + int flen = strlen(nam); + char *hf = calloc(1, flen + 6); - memcpy(hf, nam, flen); - strcpy(hf + flen, ".hier"); - xc->hier_handle = unlink_fopen(hf, "w+b"); + memcpy(hf, nam, flen); + strcpy(hf + flen, ".hier"); + xc->hier_handle = unlink_fopen(hf, "w+b"); - xc->geom_handle = tmpfile_open(&xc->geom_handle_nam); /* .geom */ - xc->valpos_handle = tmpfile_open(&xc->valpos_handle_nam); /* .offs */ - 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->geom_handle = tmpfile_open(&xc->geom_handle_nam); /* .geom */ + xc->valpos_handle = tmpfile_open(&xc->valpos_handle_nam); /* .offs */ + 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); - if(xc->hier_handle && xc->geom_handle && xc->valpos_handle && xc->curval_handle && xc->vchg_mem && xc->tchn_handle) - { - xc->filename = strdup(nam); - xc->is_initial_time = 1; + if(xc->hier_handle && xc->geom_handle && xc->valpos_handle && xc->curval_handle && xc->vchg_mem && xc->tchn_handle) + { + xc->filename = strdup(nam); + xc->is_initial_time = 1; - fstWriterEmitHdrBytes(xc); - xc->nan = strtod("NaN", NULL); + fstWriterEmitHdrBytes(xc); + xc->nan = strtod("NaN", NULL); #ifdef FST_WRITER_PARALLEL - pthread_mutex_init(&xc->mutex, NULL); - pthread_attr_init(&xc->thread_attr); - pthread_attr_setdetachstate(&xc->thread_attr, PTHREAD_CREATE_DETACHED); + pthread_mutex_init(&xc->mutex, NULL); + pthread_attr_init(&xc->thread_attr); + pthread_attr_setdetachstate(&xc->thread_attr, PTHREAD_CREATE_DETACHED); #endif - } - else - { - fclose(xc->handle); - if(xc->hier_handle) { fclose(xc->hier_handle); unlink(hf); } - tmpfile_close(&xc->geom_handle, &xc->geom_handle_nam); - tmpfile_close(&xc->valpos_handle, &xc->valpos_handle_nam); - tmpfile_close(&xc->curval_handle, &xc->curval_handle_nam); - tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam); - free(xc->vchg_mem); - free(xc); - xc=NULL; - } + } + else + { + fclose(xc->handle); + if(xc->hier_handle) { fclose(xc->hier_handle); unlink(hf); } + tmpfile_close(&xc->geom_handle, &xc->geom_handle_nam); + tmpfile_close(&xc->valpos_handle, &xc->valpos_handle_nam); + tmpfile_close(&xc->curval_handle, &xc->curval_handle_nam); + tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam); + free(xc->vchg_mem); + free(xc); + xc=NULL; + } - free(hf); - } + free(hf); + } return(xc); } @@ -1169,48 +1169,48 @@ static void fstWriterEmitSectionHeader(void *ctx) struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) - { - unsigned long destlen; - unsigned char *dmem; + { + unsigned long destlen; + unsigned char *dmem; int rc; - destlen = xc->maxvalpos; - dmem = malloc(compressBound(destlen)); + destlen = xc->maxvalpos; + dmem = 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 */ - xc->section_start = ftello(xc->handle); + fputc(FST_BL_SKIP, xc->handle); /* temporarily tag the section, use FST_BL_VCDATA on finalize */ + xc->section_start = ftello(xc->handle); #ifdef FST_WRITER_PARALLEL - if(xc->xc_parent) xc->xc_parent->section_start = xc->section_start; + if(xc->xc_parent) xc->xc_parent->section_start = xc->section_start; #endif - xc->section_header_only = 1; /* indicates truncate might be needed */ - fstWriterUint64(xc->handle, 0); /* placeholder = section length */ - fstWriterUint64(xc->handle, xc->is_initial_time ? xc->firsttime : xc->curtime); /* begin time of section */ - fstWriterUint64(xc->handle, xc->curtime); /* end time of section (placeholder) */ - fstWriterUint64(xc->handle, 0); /* placeholder = amount of buffer memory required in reader for full vc traversal */ - fstWriterVarint(xc->handle, xc->maxvalpos); /* maxvalpos = length of uncompressed data */ + xc->section_header_only = 1; /* indicates truncate might be needed */ + fstWriterUint64(xc->handle, 0); /* placeholder = section length */ + fstWriterUint64(xc->handle, xc->is_initial_time ? xc->firsttime : xc->curtime); /* begin time of section */ + fstWriterUint64(xc->handle, xc->curtime); /* end time of section (placeholder) */ + fstWriterUint64(xc->handle, 0); /* placeholder = amount of buffer memory required in reader for full vc traversal */ + fstWriterVarint(xc->handle, xc->maxvalpos); /* maxvalpos = length of uncompressed data */ - if((rc == Z_OK) && (destlen < xc->maxvalpos)) - { - fstWriterVarint(xc->handle, destlen); /* length of compressed data */ - } - else - { - fstWriterVarint(xc->handle, xc->maxvalpos); /* length of (unable to be) compressed data */ - } - fstWriterVarint(xc->handle, xc->maxhandle); /* max handle associated with this data (in case of dynamic facility adds) */ + if((rc == Z_OK) && (destlen < xc->maxvalpos)) + { + fstWriterVarint(xc->handle, destlen); /* length of compressed data */ + } + else + { + fstWriterVarint(xc->handle, xc->maxvalpos); /* length of (unable to be) compressed data */ + } + fstWriterVarint(xc->handle, xc->maxhandle); /* max handle associated with this data (in case of dynamic facility adds) */ - if((rc == Z_OK) && (destlen < xc->maxvalpos)) - { - fstFwrite(dmem, destlen, 1, xc->handle); - } - else /* comparison between compressed / decompressed len tells if compressed */ - { - fstFwrite(xc->curval_mem, xc->maxvalpos, 1, xc->handle); - } + if((rc == Z_OK) && (destlen < xc->maxvalpos)) + { + fstFwrite(dmem, destlen, 1, xc->handle); + } + else /* comparison between compressed / decompressed len tells if compressed */ + { + fstFwrite(xc->curval_mem, xc->maxvalpos, 1, xc->handle); + } - free(dmem); - } + free(dmem); + } } @@ -1227,7 +1227,7 @@ static void fstWriterFlushContextPrivate(void *ctx) #ifdef FST_DEBUG int cnt = 0; #endif -int i; +unsigned int i; unsigned char *vchg_mem; FILE *f; off_t fpos, indxpos, endpos; @@ -1269,141 +1269,141 @@ scratchpad = malloc(xc->vchg_siz); vchg_mem = xc->vchg_mem; f = xc->handle; -fstWriterVarint(f, xc->maxhandle); /* emit current number of handles */ +fstWriterVarint(f, xc->maxhandle); /* emit current number of handles */ 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 */ +packmemlen = 1024; /* maintain a running "longest" allocation to */ +packmem = malloc(packmemlen); /* prevent continual malloc...free every loop iter */ for(i=0;imaxhandle;i++) - { - vm4ip = &(xc->valpos_mem[4*i]); + { + vm4ip = &(xc->valpos_mem[4*i]); - if(vm4ip[2]) - { - uint32_t offs = vm4ip[2]; - uint32_t next_offs; - int wrlen; + if(vm4ip[2]) + { + uint32_t offs = vm4ip[2]; + uint32_t next_offs; + unsigned int wrlen; - vm4ip[2] = fpos; + vm4ip[2] = fpos; - scratchpnt = scratchpad + xc->vchg_siz; /* build this buffer backwards */ - if(vm4ip[1] <= 1) - { - if(vm4ip[1] == 1) - { - wrlen = fstGetVarint32Length(vchg_mem + offs + 4); /* used to advance and determine wrlen */ + scratchpnt = scratchpad + xc->vchg_siz; /* build this buffer backwards */ + if(vm4ip[1] <= 1) + { + if(vm4ip[1] == 1) + { + wrlen = fstGetVarint32Length(vchg_mem + offs + 4); /* used to advance and determine wrlen */ #ifndef FST_REMOVE_DUPLICATE_VC - xc->curval_mem[vm4ip[0]] = vchg_mem[offs + 4 + wrlen]; /* checkpoint variable */ + xc->curval_mem[vm4ip[0]] = vchg_mem[offs + 4 + wrlen]; /* checkpoint variable */ #endif - while(offs) - { - unsigned char val; - uint32_t time_delta, rcv; - next_offs = fstGetUint32(vchg_mem + offs); - offs += 4; + while(offs) + { + unsigned char val; + uint32_t time_delta, rcv; + next_offs = fstGetUint32(vchg_mem + offs); + offs += 4; - time_delta = fstGetVarint32(vchg_mem + offs, &wrlen); - val = vchg_mem[offs+wrlen]; - offs = next_offs; + time_delta = fstGetVarint32(vchg_mem + offs, (int *)&wrlen); + val = vchg_mem[offs+wrlen]; + offs = next_offs; - switch(val) - { - case '0': - case '1': rcv = ((val&1)<<1) | (time_delta<<2); - break; /* pack more delta bits in for 0/1 vchs */ + switch(val) + { + case '0': + case '1': rcv = ((val&1)<<1) | (time_delta<<2); + break; /* pack more delta bits in for 0/1 vchs */ - case 'x': case 'X': rcv = FST_RCV_X | (time_delta<<4); break; - case 'z': case 'Z': rcv = FST_RCV_Z | (time_delta<<4); break; - case 'h': case 'H': rcv = FST_RCV_H | (time_delta<<4); break; - case 'u': case 'U': rcv = FST_RCV_U | (time_delta<<4); break; - case 'w': case 'W': rcv = FST_RCV_W | (time_delta<<4); break; - case 'l': case 'L': rcv = FST_RCV_L | (time_delta<<4); break; - default: rcv = FST_RCV_D | (time_delta<<4); break; - } + case 'x': case 'X': rcv = FST_RCV_X | (time_delta<<4); break; + case 'z': case 'Z': rcv = FST_RCV_Z | (time_delta<<4); break; + case 'h': case 'H': rcv = FST_RCV_H | (time_delta<<4); break; + case 'u': case 'U': rcv = FST_RCV_U | (time_delta<<4); break; + case 'w': case 'W': rcv = FST_RCV_W | (time_delta<<4); break; + case 'l': case 'L': rcv = FST_RCV_L | (time_delta<<4); break; + default: rcv = FST_RCV_D | (time_delta<<4); break; + } - scratchpnt = fstCopyVarint32ToLeft(scratchpnt, rcv); - } - } - else - { - /* variable length */ - /* fstGetUint32 (next_offs) + fstGetVarint32 (time_delta) + fstGetVarint32 (len) + payload */ - unsigned char *pnt; - uint32_t record_len; - uint32_t time_delta; + scratchpnt = fstCopyVarint32ToLeft(scratchpnt, rcv); + } + } + else + { + /* variable length */ + /* fstGetUint32 (next_offs) + fstGetVarint32 (time_delta) + fstGetVarint32 (len) + payload */ + unsigned char *pnt; + uint32_t record_len; + uint32_t time_delta; - while(offs) - { - next_offs = fstGetUint32(vchg_mem + offs); - offs += 4; - pnt = vchg_mem + offs; - offs = next_offs; - time_delta = fstGetVarint32(pnt, &wrlen); - pnt += wrlen; - record_len = fstGetVarint32(pnt, &wrlen); - pnt += wrlen; + while(offs) + { + next_offs = fstGetUint32(vchg_mem + offs); + offs += 4; + pnt = vchg_mem + offs; + offs = next_offs; + time_delta = fstGetVarint32(pnt, (int *)&wrlen); + pnt += wrlen; + record_len = fstGetVarint32(pnt, (int *)&wrlen); + pnt += wrlen; - scratchpnt -= record_len; - memcpy(scratchpnt, pnt, record_len); + scratchpnt -= record_len; + memcpy(scratchpnt, pnt, record_len); - scratchpnt = fstCopyVarint32ToLeft(scratchpnt, record_len); - scratchpnt = fstCopyVarint32ToLeft(scratchpnt, (time_delta << 1)); /* reserve | 1 case for future expansion */ - } - } - } - else - { - wrlen = fstGetVarint32Length(vchg_mem + offs + 4); /* used to advance and determine wrlen */ + scratchpnt = fstCopyVarint32ToLeft(scratchpnt, record_len); + scratchpnt = fstCopyVarint32ToLeft(scratchpnt, (time_delta << 1)); /* reserve | 1 case for future expansion */ + } + } + } + else + { + wrlen = fstGetVarint32Length(vchg_mem + offs + 4); /* used to advance and determine wrlen */ #ifndef FST_REMOVE_DUPLICATE_VC - memcpy(xc->curval_mem + vm4ip[0], vchg_mem + offs + 4 + wrlen, vm4ip[1]); /* checkpoint variable */ + memcpy(xc->curval_mem + vm4ip[0], vchg_mem + offs + 4 + wrlen, vm4ip[1]); /* checkpoint variable */ #endif - while(offs) - { - int idx; - char is_binary = 1; - unsigned char *pnt; - uint32_t time_delta; + while(offs) + { + unsigned int idx; + char is_binary = 1; + unsigned char *pnt; + uint32_t time_delta; - next_offs = fstGetUint32(vchg_mem + offs); - offs += 4; + next_offs = fstGetUint32(vchg_mem + offs); + offs += 4; - time_delta = fstGetVarint32(vchg_mem + offs, &wrlen); + time_delta = fstGetVarint32(vchg_mem + offs, (int *)&wrlen); - pnt = vchg_mem+offs+wrlen; - offs = next_offs; + pnt = vchg_mem+offs+wrlen; + offs = next_offs; - for(idx=0;idx=0;idx--) - { - acc |= (pnt[idx] & 1) << shift; - shift++; - if(shift == 8) - { - *(--scratchpnt) = acc; - shift = 0; - acc = 0; - } - } + /* old algorithm */ + int shift = 7 - ((vm4ip[1]-1) & 7); + for(idx=vm4ip[1]-1;idx>=0;idx--) + { + acc |= (pnt[idx] & 1) << shift; + shift++; + if(shift == 8) + { + *(--scratchpnt) = acc; + shift = 0; + acc = 0; + } + } #else /* new algorithm */ idx = ((vm4ip[1]+7) & ~7); @@ -1423,163 +1423,163 @@ for(i=0;imaxhandle;i++) } #endif - scratchpnt = fstCopyVarint32ToLeft(scratchpnt, (time_delta << 1)); - } - else - { - scratchpnt -= vm4ip[1]; - memcpy(scratchpnt, pnt, vm4ip[1]); + scratchpnt = fstCopyVarint32ToLeft(scratchpnt, (time_delta << 1)); + } + else + { + scratchpnt -= vm4ip[1]; + memcpy(scratchpnt, pnt, vm4ip[1]); - scratchpnt = fstCopyVarint32ToLeft(scratchpnt, (time_delta << 1) | 1); - } - } - } + scratchpnt = fstCopyVarint32ToLeft(scratchpnt, (time_delta << 1) | 1); + } + } + } - wrlen = scratchpad + xc->vchg_siz - scratchpnt; - unc_memreq += wrlen; - if(wrlen > 32) - { - unsigned long destlen = wrlen; - unsigned char *dmem; - int rc; + wrlen = scratchpad + xc->vchg_siz - scratchpnt; + unc_memreq += wrlen; + if(wrlen > 32) + { + unsigned long destlen = wrlen; + unsigned char *dmem; + unsigned int rc; - if(!xc->fastpack) - { - if(wrlen <= packmemlen) - { - dmem = packmem; - } - else - { - free(packmem); - dmem = packmem = malloc(compressBound(packmemlen = wrlen)); - } + if(!xc->fastpack) + { + if(wrlen <= packmemlen) + { + dmem = packmem; + } + else + { + free(packmem); + dmem = packmem = malloc(compressBound(packmemlen = wrlen)); + } - rc = compress2(dmem, &destlen, scratchpnt, wrlen, 4); - if(rc == Z_OK) - { + rc = compress2(dmem, &destlen, scratchpnt, wrlen, 4); + if(rc == Z_OK) + { #ifndef FST_DYNAMIC_ALIAS_DISABLE - PPvoid_t pv = JudyHSIns(&PJHSArray, dmem, destlen, NULL); - if(*pv) - { - uint32_t pvi = (long)(*pv); - vm4ip[2] = -pvi; - } - else - { - *pv = (void *)(long)(i+1); + PPvoid_t pv = JudyHSIns(&PJHSArray, dmem, destlen, NULL); + if(*pv) + { + uint32_t pvi = (long)(*pv); + vm4ip[2] = -pvi; + } + else + { + *pv = (void *)(long)(i+1); #endif - fpos += fstWriterVarint(f, wrlen); - fpos += destlen; - fstFwrite(dmem, destlen, 1, f); + fpos += fstWriterVarint(f, wrlen); + fpos += destlen; + fstFwrite(dmem, destlen, 1, f); #ifndef FST_DYNAMIC_ALIAS_DISABLE - } + } #endif - } - else - { + } + else + { #ifndef FST_DYNAMIC_ALIAS_DISABLE - PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL); - if(*pv) - { - uint32_t pvi = (long)(*pv); - vm4ip[2] = -pvi; - } - else - { - *pv = (void *)(long)(i+1); + PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL); + if(*pv) + { + uint32_t pvi = (long)(*pv); + vm4ip[2] = -pvi; + } + else + { + *pv = (void *)(long)(i+1); #endif - fpos += fstWriterVarint(f, 0); - fpos += wrlen; - fstFwrite(scratchpnt, wrlen, 1, f); + fpos += fstWriterVarint(f, 0); + fpos += wrlen; + fstFwrite(scratchpnt, wrlen, 1, f); #ifndef FST_DYNAMIC_ALIAS_DISABLE - } + } #endif - } - } - else - { - /* this is extremely conservative: fastlz needs +5% for worst case, lz4 needs siz+(siz/255)+16 */ - if(((wrlen * 2) + 2) <= packmemlen) - { - dmem = packmem; - } - else - { - free(packmem); - dmem = packmem = malloc(packmemlen = (wrlen * 2) + 2); - } + } + } + else + { + /* this is extremely conservative: fastlz needs +5% for worst case, lz4 needs siz+(siz/255)+16 */ + if(((wrlen * 2) + 2) <= packmemlen) + { + dmem = packmem; + } + else + { + free(packmem); + dmem = packmem = malloc(packmemlen = (wrlen * 2) + 2); + } - rc = (xc->fourpack) ? LZ4_compress((char *)scratchpnt, (char *)dmem, wrlen) : fastlz_compress(scratchpnt, wrlen, dmem); - if(rc < destlen) - { + rc = (xc->fourpack) ? LZ4_compress((char *)scratchpnt, (char *)dmem, wrlen) : fastlz_compress(scratchpnt, wrlen, dmem); + if(rc < destlen) + { #ifndef FST_DYNAMIC_ALIAS_DISABLE - PPvoid_t pv = JudyHSIns(&PJHSArray, dmem, rc, NULL); - if(*pv) - { - uint32_t pvi = (long)(*pv); - vm4ip[2] = -pvi; - } - else - { - *pv = (void *)(long)(i+1); + PPvoid_t pv = JudyHSIns(&PJHSArray, dmem, rc, NULL); + if(*pv) + { + uint32_t pvi = (long)(*pv); + vm4ip[2] = -pvi; + } + else + { + *pv = (void *)(long)(i+1); #endif - fpos += fstWriterVarint(f, wrlen); - fpos += rc; - fstFwrite(dmem, rc, 1, f); + fpos += fstWriterVarint(f, wrlen); + fpos += rc; + fstFwrite(dmem, rc, 1, f); #ifndef FST_DYNAMIC_ALIAS_DISABLE - } + } #endif - } - else - { + } + else + { #ifndef FST_DYNAMIC_ALIAS_DISABLE - PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL); - if(*pv) - { - uint32_t pvi = (long)(*pv); - vm4ip[2] = -pvi; - } - else - { - *pv = (void *)(long)(i+1); + PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL); + if(*pv) + { + uint32_t pvi = (long)(*pv); + vm4ip[2] = -pvi; + } + else + { + *pv = (void *)(long)(i+1); #endif - fpos += fstWriterVarint(f, 0); - fpos += wrlen; - fstFwrite(scratchpnt, wrlen, 1, f); + fpos += fstWriterVarint(f, 0); + fpos += wrlen; + fstFwrite(scratchpnt, wrlen, 1, f); #ifndef FST_DYNAMIC_ALIAS_DISABLE - } + } #endif - } - } - } - else - { + } + } + } + else + { #ifndef FST_DYNAMIC_ALIAS_DISABLE - PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL); - if(*pv) - { - uint32_t pvi = (long)(*pv); - vm4ip[2] = -pvi; - } - else - { - *pv = (void *)(long)(i+1); + PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL); + if(*pv) + { + uint32_t pvi = (long)(*pv); + vm4ip[2] = -pvi; + } + else + { + *pv = (void *)(long)(i+1); #endif - fpos += fstWriterVarint(f, 0); - fpos += wrlen; - fstFwrite(scratchpnt, wrlen, 1, f); + fpos += fstWriterVarint(f, 0); + fpos += wrlen; + fstFwrite(scratchpnt, wrlen, 1, f); #ifndef FST_DYNAMIC_ALIAS_DISABLE - } + } #endif - } + } - /* vm4ip[3] = 0; ...redundant with clearing below */ + /* vm4ip[3] = 0; ...redundant with clearing below */ #ifdef FST_DEBUG - cnt++; + cnt++; #endif - } - } + } + } #ifndef FST_DYNAMIC_ALIAS_DISABLE JudyHSFreeArray(&PJHSArray, NULL); @@ -1595,85 +1595,85 @@ xc->secnum++; #ifndef FST_DYNAMIC_ALIAS2_DISABLE if(1) - { - uint32_t prev_alias = 0; + { + uint32_t prev_alias = 0; - for(i=0;imaxhandle;i++) - { - vm4ip = &(xc->valpos_mem[4*i]); + for(i=0;imaxhandle;i++) + { + vm4ip = &(xc->valpos_mem[4*i]); - if(vm4ip[2]) - { - if(zerocnt) - { - fpos += fstWriterVarint(f, (zerocnt << 1)); - zerocnt = 0; - } + if(vm4ip[2]) + { + if(zerocnt) + { + fpos += fstWriterVarint(f, (zerocnt << 1)); + zerocnt = 0; + } - if(vm4ip[2] & 0x80000000) - { - if(vm4ip[2] != prev_alias) - { - fpos += fstWriterSVarint(f, (((int64_t)((int32_t)(prev_alias = vm4ip[2]))) << 1) | 1); - } - else - { - fpos += fstWriterSVarint(f, (0 << 1) | 1); - } - } - else - { - fpos += fstWriterSVarint(f, ((vm4ip[2] - prevpos) << 1) | 1); - prevpos = vm4ip[2]; - } - vm4ip[2] = 0; - vm4ip[3] = 0; /* clear out tchn idx */ - } - else - { - zerocnt++; - } - } - } - else + if(vm4ip[2] & 0x80000000) + { + if(vm4ip[2] != prev_alias) + { + fpos += fstWriterSVarint(f, (((int64_t)((int32_t)(prev_alias = vm4ip[2]))) << 1) | 1); + } + else + { + fpos += fstWriterSVarint(f, (0 << 1) | 1); + } + } + else + { + fpos += fstWriterSVarint(f, ((vm4ip[2] - prevpos) << 1) | 1); + prevpos = vm4ip[2]; + } + vm4ip[2] = 0; + vm4ip[3] = 0; /* clear out tchn idx */ + } + else + { + zerocnt++; + } + } + } + else #endif - { - for(i=0;imaxhandle;i++) - { - vm4ip = &(xc->valpos_mem[4*i]); + { + for(i=0;imaxhandle;i++) + { + vm4ip = &(xc->valpos_mem[4*i]); - if(vm4ip[2]) - { - if(zerocnt) - { - fpos += fstWriterVarint(f, (zerocnt << 1)); - zerocnt = 0; - } + if(vm4ip[2]) + { + if(zerocnt) + { + fpos += fstWriterVarint(f, (zerocnt << 1)); + zerocnt = 0; + } - if(vm4ip[2] & 0x80000000) - { - fpos += fstWriterVarint(f, 0); /* signal, note that using a *signed* varint would be more efficient than this byte escape! */ - fpos += fstWriterVarint(f, (-(int32_t)vm4ip[2])); - } - else - { - fpos += fstWriterVarint(f, ((vm4ip[2] - prevpos) << 1) | 1); - prevpos = vm4ip[2]; - } - vm4ip[2] = 0; - vm4ip[3] = 0; /* clear out tchn idx */ - } - else - { - zerocnt++; - } - } - } + if(vm4ip[2] & 0x80000000) + { + fpos += fstWriterVarint(f, 0); /* signal, note that using a *signed* varint would be more efficient than this byte escape! */ + fpos += fstWriterVarint(f, (-(int32_t)vm4ip[2])); + } + else + { + fpos += fstWriterVarint(f, ((vm4ip[2] - prevpos) << 1) | 1); + prevpos = vm4ip[2]; + } + vm4ip[2] = 0; + vm4ip[3] = 0; /* clear out tchn idx */ + } + else + { + zerocnt++; + } + } + } if(zerocnt) - { - /* fpos += */ fstWriterVarint(f, (zerocnt << 1)); /* scan-build */ - } + { + /* fpos += */ fstWriterVarint(f, (zerocnt << 1)); /* scan-build */ + } #ifdef FST_DEBUG fprintf(stderr, "value chains: %d\n", cnt); #endif @@ -1682,7 +1682,7 @@ xc->vchg_mem[0] = '!'; xc->vchg_siz = 1; endpos = ftello(xc->handle); -fstWriterUint64(xc->handle, endpos-indxpos); /* write delta index position at very end of block */ +fstWriterUint64(xc->handle, endpos-indxpos); /* write delta index position at very end of block */ /*emit time changes for block */ fflush(xc->tchn_handle); @@ -1691,26 +1691,26 @@ fstWriterFseeko(xc, xc->tchn_handle, 0, SEEK_SET); tmem = 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 long destlen = tlen; + unsigned char *dmem = malloc(compressBound(destlen)); int rc = compress2(dmem, &destlen, tmem, tlen, 9); - if((rc == Z_OK) && (destlen < tlen)) - { - fstFwrite(dmem, destlen, 1, xc->handle); - } - else /* comparison between compressed / decompressed len tells if compressed */ - { - fstFwrite(tmem, tlen, 1, xc->handle); - destlen = tlen; - } - free(dmem); - fstMunmap(tmem, tlen); - fstWriterUint64(xc->handle, tlen); /* uncompressed */ - fstWriterUint64(xc->handle, destlen); /* compressed */ - fstWriterUint64(xc->handle, xc->tchn_cnt); /* number of time items */ - } + if((rc == Z_OK) && (destlen < tlen)) + { + fstFwrite(dmem, destlen, 1, xc->handle); + } + else /* comparison between compressed / decompressed len tells if compressed */ + { + fstFwrite(tmem, tlen, 1, xc->handle); + destlen = tlen; + } + free(dmem); + fstMunmap(tmem, tlen); + fstWriterUint64(xc->handle, tlen); /* uncompressed */ + fstWriterUint64(xc->handle, destlen); /* compressed */ + fstWriterUint64(xc->handle, xc->tchn_cnt); /* number of time items */ + } xc->tchn_cnt = xc->tchn_idx = 0; fstWriterFseeko(xc, xc->tchn_handle, 0, SEEK_SET); @@ -1719,13 +1719,13 @@ fstFtruncate(fileno(xc->tchn_handle), 0); /* write block trailer */ endpos = ftello(xc->handle); fstWriterFseeko(xc, xc->handle, xc->section_start, SEEK_SET); -fstWriterUint64(xc->handle, endpos - xc->section_start); /* write block length */ -fstWriterFseeko(xc, xc->handle, 8, SEEK_CUR); /* skip begin time */ -fstWriterUint64(xc->handle, xc->curtime); /* write end time for section */ -fstWriterUint64(xc->handle, unc_memreq); /* amount of buffer memory required in reader for full traversal */ +fstWriterUint64(xc->handle, endpos - xc->section_start); /* write block length */ +fstWriterFseeko(xc, xc->handle, 8, SEEK_CUR); /* skip begin time */ +fstWriterUint64(xc->handle, xc->curtime); /* write end time for section */ +fstWriterUint64(xc->handle, unc_memreq); /* amount of buffer memory required in reader for full traversal */ fflush(xc->handle); -fstWriterFseeko(xc, xc->handle, xc->section_start-1, SEEK_SET); /* write out FST_BL_VCDATA over FST_BL_SKIP */ +fstWriterFseeko(xc, xc->handle, xc->section_start-1, SEEK_SET); /* write out FST_BL_VCDATA over FST_BL_SKIP */ #ifndef FST_DYNAMIC_ALIAS_DISABLE #ifndef FST_DYNAMIC_ALIAS2_DISABLE @@ -1739,26 +1739,26 @@ fputc(FST_BL_VCDATA, xc->handle); fflush(xc->handle); -fstWriterFseeko(xc, xc->handle, endpos, SEEK_SET); /* seek to end of file */ +fstWriterFseeko(xc, xc->handle, endpos, SEEK_SET); /* seek to end of file */ -xc2->section_header_truncpos = endpos; /* cache in case of need to truncate */ +xc2->section_header_truncpos = endpos; /* cache in case of need to truncate */ if(xc->dump_size_limit) - { - if(endpos >= xc->dump_size_limit) - { - xc2->skip_writing_section_hdr = 1; - xc2->size_limit_locked = 1; - xc2->is_initial_time = 1; /* to trick emit value and emit time change */ + { + if(endpos >= ((off_t)xc->dump_size_limit)) + { + xc2->skip_writing_section_hdr = 1; + 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, "<< dump file size limit reached, stopping dumping >>\n"); #endif - } - } + } + } if(!xc2->skip_writing_section_hdr) - { - fstWriterEmitSectionHeader(xc); /* emit next section header */ - } + { + fstWriterEmitSectionHeader(xc); /* emit next section header */ + } fflush(xc->handle); xc->already_in_flush = 0; @@ -1791,59 +1791,59 @@ static void fstWriterFlushContextPrivate(void *ctx) struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc->parallel_enabled) - { - struct fstWriterContext *xc2 = malloc(sizeof(struct fstWriterContext)); - int i; + { + struct fstWriterContext *xc2 = malloc(sizeof(struct fstWriterContext)); + unsigned int i; - pthread_mutex_lock(&xc->mutex); - pthread_mutex_unlock(&xc->mutex); + pthread_mutex_lock(&xc->mutex); + pthread_mutex_unlock(&xc->mutex); - xc->xc_parent = xc; - memcpy(xc2, xc, sizeof(struct fstWriterContext)); + xc->xc_parent = xc; + memcpy(xc2, xc, sizeof(struct fstWriterContext)); - xc2->valpos_mem = malloc(xc->maxhandle * 4 * sizeof(uint32_t)); - memcpy(xc2->valpos_mem, xc->valpos_mem, xc->maxhandle * 4 * sizeof(uint32_t)); + xc2->valpos_mem = 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 */ + /* curval mem is updated in the thread */ #ifdef FST_REMOVE_DUPLICATE_VC - xc2->curval_mem = malloc(xc->maxvalpos); - memcpy(xc2->curval_mem, xc->curval_mem, xc->maxvalpos); + xc2->curval_mem = malloc(xc->maxvalpos); + memcpy(xc2->curval_mem, xc->curval_mem, xc->maxvalpos); #endif - xc->vchg_mem = malloc(xc->vchg_alloc_siz); - xc->vchg_mem[0] = '!'; - xc->vchg_siz = 1; + xc->vchg_mem = malloc(xc->vchg_alloc_siz); + xc->vchg_mem[0] = '!'; + xc->vchg_siz = 1; - for(i=0;imaxhandle;i++) - { - uint32_t *vm4ip = &(xc->valpos_mem[4*i]); - vm4ip[2] = 0; /* zero out offset val */ - vm4ip[3] = 0; /* zero out last time change val */ - } + for(i=0;imaxhandle;i++) + { + uint32_t *vm4ip = &(xc->valpos_mem[4*i]); + vm4ip[2] = 0; /* zero out offset val */ + vm4ip[3] = 0; /* zero out last time change val */ + } - xc->tchn_cnt = xc->tchn_idx = 0; - xc->tchn_handle = tmpfile_open(&xc->tchn_handle_nam); /* child thread will deallocate file/name */ - fstWriterFseeko(xc, xc->tchn_handle, 0, SEEK_SET); - fstFtruncate(fileno(xc->tchn_handle), 0); + xc->tchn_cnt = xc->tchn_idx = 0; + xc->tchn_handle = tmpfile_open(&xc->tchn_handle_nam); /* child thread will deallocate file/name */ + fstWriterFseeko(xc, xc->tchn_handle, 0, SEEK_SET); + fstFtruncate(fileno(xc->tchn_handle), 0); - xc->section_header_only = 0; - xc->secnum++; + xc->section_header_only = 0; + xc->secnum++; - pthread_mutex_lock(&xc->mutex); + pthread_mutex_lock(&xc->mutex); - pthread_create(&xc->thread, &xc->thread_attr, fstWriterFlushContextPrivate1, xc2); - } - else - { - if(xc->parallel_was_enabled) /* conservatively block */ - { - pthread_mutex_lock(&xc->mutex); - pthread_mutex_unlock(&xc->mutex); - } + pthread_create(&xc->thread, &xc->thread_attr, fstWriterFlushContextPrivate1, xc2); + } + else + { + if(xc->parallel_was_enabled) /* conservatively block */ + { + pthread_mutex_lock(&xc->mutex); + pthread_mutex_unlock(&xc->mutex); + } - xc->xc_parent = xc; - fstWriterFlushContextPrivate2(xc); - } + xc->xc_parent = xc; + fstWriterFlushContextPrivate2(xc); + } } #endif @@ -1856,11 +1856,11 @@ void fstWriterFlushContext(void *ctx) struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) { - if(xc->tchn_idx > 1) - { - xc->flush_context_pending = 1; - } - } + if(xc->tchn_idx > 1) + { + xc->flush_context_pending = 1; + } + } } @@ -1873,333 +1873,333 @@ struct fstWriterContext *xc = (struct fstWriterContext *)ctx; #ifdef FST_WRITER_PARALLEL if(xc) - { - pthread_mutex_lock(&xc->mutex); - pthread_mutex_unlock(&xc->mutex); - } + { + pthread_mutex_lock(&xc->mutex); + pthread_mutex_unlock(&xc->mutex); + } #endif if(xc && !xc->already_in_close && !xc->already_in_flush) - { - unsigned char *tmem; - off_t fixup_offs, tlen, hlen; + { + unsigned char *tmem; + off_t fixup_offs, tlen, hlen; - xc->already_in_close = 1; /* never need to zero this out as it is freed at bottom */ + xc->already_in_close = 1; /* never need to zero this out as it is freed at bottom */ - if(xc->section_header_only && xc->section_header_truncpos && (xc->vchg_siz <= 1) && (!xc->is_initial_time)) - { - fstFtruncate(fileno(xc->handle), xc->section_header_truncpos); - fstWriterFseeko(xc, xc->handle, xc->section_header_truncpos, SEEK_SET); - xc->section_header_only = 0; - } - else - { - xc->skip_writing_section_hdr = 1; - if(!xc->size_limit_locked) - { - if(xc->is_initial_time) /* simulation time never advanced so mock up the changes as time zero ones */ - { - fstHandle dupe_idx; + if(xc->section_header_only && xc->section_header_truncpos && (xc->vchg_siz <= 1) && (!xc->is_initial_time)) + { + fstFtruncate(fileno(xc->handle), xc->section_header_truncpos); + fstWriterFseeko(xc, xc->handle, xc->section_header_truncpos, SEEK_SET); + xc->section_header_only = 0; + } + else + { + xc->skip_writing_section_hdr = 1; + if(!xc->size_limit_locked) + { + if(xc->is_initial_time) /* simulation time never advanced so mock up the changes as time zero ones */ + { + fstHandle dupe_idx; - fstWriterEmitTimeChange(xc, 0); /* emit some time change just to have one */ - for(dupe_idx = 0; dupe_idx < xc->maxhandle; dupe_idx++) /* now clone the values */ - { - fstWriterEmitValueChange(xc, dupe_idx+1, xc->curval_mem + xc->valpos_mem[4*dupe_idx]); - } - } - fstWriterFlushContextPrivate(xc); + fstWriterEmitTimeChange(xc, 0); /* emit some time change just to have one */ + for(dupe_idx = 0; dupe_idx < xc->maxhandle; dupe_idx++) /* now clone the values */ + { + fstWriterEmitValueChange(xc, dupe_idx+1, xc->curval_mem + xc->valpos_mem[4*dupe_idx]); + } + } + fstWriterFlushContextPrivate(xc); #ifdef FST_WRITER_PARALLEL - pthread_mutex_lock(&xc->mutex); - pthread_mutex_unlock(&xc->mutex); + pthread_mutex_lock(&xc->mutex); + pthread_mutex_unlock(&xc->mutex); #endif - } - } - fstDestroyMmaps(xc, 1); + } + } + fstDestroyMmaps(xc, 1); - /* 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); - if(tmem) - { - unsigned long destlen = tlen; - unsigned char *dmem = malloc(compressBound(destlen)); - int rc = compress2(dmem, &destlen, tmem, tlen, 9); + /* 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); + if(tmem) + { + unsigned long destlen = tlen; + unsigned char *dmem = malloc(compressBound(destlen)); + int rc = compress2(dmem, &destlen, tmem, tlen, 9); - if((rc != Z_OK) || (destlen > tlen)) - { - destlen = tlen; - } + if((rc != Z_OK) || (destlen > tlen)) + { + destlen = tlen; + } - fixup_offs = ftello(xc->handle); - fputc(FST_BL_SKIP, xc->handle); /* temporary tag */ - fstWriterUint64(xc->handle, destlen + 24); /* section length */ - fstWriterUint64(xc->handle, tlen); /* uncompressed */ - /* compressed len is section length - 24 */ - fstWriterUint64(xc->handle, xc->maxhandle); /* maxhandle */ - fstFwrite((destlen != tlen) ? dmem : tmem, destlen, 1, xc->handle); - fflush(xc->handle); + fixup_offs = ftello(xc->handle); + fputc(FST_BL_SKIP, xc->handle); /* temporary tag */ + fstWriterUint64(xc->handle, destlen + 24); /* section length */ + fstWriterUint64(xc->handle, tlen); /* uncompressed */ + /* compressed len is section length - 24 */ + fstWriterUint64(xc->handle, xc->maxhandle); /* maxhandle */ + fstFwrite((destlen != tlen) ? dmem : tmem, destlen, 1, xc->handle); + fflush(xc->handle); - fstWriterFseeko(xc, xc->handle, fixup_offs, SEEK_SET); - fputc(FST_BL_GEOM, xc->handle); /* actual tag */ + fstWriterFseeko(xc, xc->handle, fixup_offs, SEEK_SET); + fputc(FST_BL_GEOM, xc->handle); /* actual tag */ - fstWriterFseeko(xc, xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */ - fflush(xc->handle); + fstWriterFseeko(xc, xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */ + fflush(xc->handle); - free(dmem); - fstMunmap(tmem, tlen); - } + free(dmem); + fstMunmap(tmem, tlen); + } - if(xc->num_blackouts) - { - uint64_t cur_bl = 0; - off_t bpos, eos; - uint32_t i; + if(xc->num_blackouts) + { + uint64_t cur_bl = 0; + off_t bpos, eos; + uint32_t i; - fixup_offs = ftello(xc->handle); - fputc(FST_BL_SKIP, xc->handle); /* temporary tag */ - bpos = fixup_offs + 1; - fstWriterUint64(xc->handle, 0); /* section length */ - fstWriterVarint(xc->handle, xc->num_blackouts); + fixup_offs = ftello(xc->handle); + fputc(FST_BL_SKIP, xc->handle); /* temporary tag */ + bpos = fixup_offs + 1; + fstWriterUint64(xc->handle, 0); /* section length */ + fstWriterVarint(xc->handle, xc->num_blackouts); - for(i=0;inum_blackouts;i++) - { - fputc(xc->blackout_head->active, xc->handle); - fstWriterVarint(xc->handle, xc->blackout_head->tim - cur_bl); - cur_bl = xc->blackout_head->tim; - xc->blackout_curr = xc->blackout_head->next; - free(xc->blackout_head); - xc->blackout_head = xc->blackout_curr; - } + for(i=0;inum_blackouts;i++) + { + fputc(xc->blackout_head->active, xc->handle); + fstWriterVarint(xc->handle, xc->blackout_head->tim - cur_bl); + cur_bl = xc->blackout_head->tim; + xc->blackout_curr = xc->blackout_head->next; + free(xc->blackout_head); + xc->blackout_head = xc->blackout_curr; + } - eos = ftello(xc->handle); - fstWriterFseeko(xc, xc->handle, bpos, SEEK_SET); - fstWriterUint64(xc->handle, eos - bpos); - fflush(xc->handle); + eos = ftello(xc->handle); + fstWriterFseeko(xc, xc->handle, bpos, SEEK_SET); + fstWriterUint64(xc->handle, eos - bpos); + fflush(xc->handle); - fstWriterFseeko(xc, xc->handle, fixup_offs, SEEK_SET); - fputc(FST_BL_BLACKOUT, xc->handle); /* actual tag */ + fstWriterFseeko(xc, xc->handle, fixup_offs, SEEK_SET); + fputc(FST_BL_BLACKOUT, xc->handle); /* actual tag */ - fstWriterFseeko(xc, xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */ - fflush(xc->handle); - } + fstWriterFseeko(xc, xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */ + fflush(xc->handle); + } - if(xc->compress_hier) - { - off_t hl, eos; - gzFile zhandle; - int zfd; - int fourpack_duo = 0; + if(xc->compress_hier) + { + off_t hl, eos; + gzFile zhandle; + int zfd; + int fourpack_duo = 0; #ifndef __MINGW32__ - char *fnam = malloc(strlen(xc->filename) + 5 + 1); + char *fnam = malloc(strlen(xc->filename) + 5 + 1); #endif - fixup_offs = ftello(xc->handle); - fputc(FST_BL_SKIP, xc->handle); /* temporary tag */ - hlen = ftello(xc->handle); - fstWriterUint64(xc->handle, 0); /* section length */ - fstWriterUint64(xc->handle, xc->hier_file_len); /* uncompressed length */ + fixup_offs = ftello(xc->handle); + fputc(FST_BL_SKIP, xc->handle); /* temporary tag */ + hlen = ftello(xc->handle); + fstWriterUint64(xc->handle, 0); /* section length */ + fstWriterUint64(xc->handle, xc->hier_file_len); /* uncompressed length */ - if(!xc->fourpack) - { - unsigned char *mem = malloc(FST_GZIO_LEN); - zfd = dup(fileno(xc->handle)); - fflush(xc->handle); - zhandle = gzdopen(zfd, "wb4"); - if(zhandle) - { - fstWriterFseeko(xc, xc->hier_handle, 0, SEEK_SET); - for(hl = 0; hl < xc->hier_file_len; hl += FST_GZIO_LEN) - { - unsigned len = ((xc->hier_file_len - hl) > FST_GZIO_LEN) ? FST_GZIO_LEN : (xc->hier_file_len - hl); - fstFread(mem, len, 1, xc->hier_handle); - gzwrite(zhandle, mem, len); - } - gzclose(zhandle); - } - else - { - close(zfd); - } - free(mem); - } - else - { - int lz4_maxlen; - unsigned char *mem; - unsigned char *hmem; - int packed_len; + if(!xc->fourpack) + { + unsigned char *mem = malloc(FST_GZIO_LEN); + zfd = dup(fileno(xc->handle)); + fflush(xc->handle); + zhandle = gzdopen(zfd, "wb4"); + if(zhandle) + { + fstWriterFseeko(xc, xc->hier_handle, 0, SEEK_SET); + for(hl = 0; hl < xc->hier_file_len; hl += FST_GZIO_LEN) + { + unsigned len = ((xc->hier_file_len - hl) > FST_GZIO_LEN) ? FST_GZIO_LEN : (xc->hier_file_len - hl); + fstFread(mem, len, 1, xc->hier_handle); + gzwrite(zhandle, mem, len); + } + gzclose(zhandle); + } + else + { + close(zfd); + } + free(mem); + } + else + { + int lz4_maxlen; + unsigned char *mem; + unsigned char *hmem; + int packed_len; - fflush(xc->handle); + 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); - packed_len = LZ4_compress((char *)hmem, (char *)mem, xc->hier_file_len); - fstMunmap(hmem, xc->hier_file_len); + 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); + packed_len = LZ4_compress((char *)hmem, (char *)mem, xc->hier_file_len); + fstMunmap(hmem, xc->hier_file_len); - fourpack_duo = (!xc->repack_on_close) && (xc->hier_file_len > FST_HDR_FOURPACK_DUO_SIZE); /* double pack when hierarchy is large */ + fourpack_duo = (!xc->repack_on_close) && (xc->hier_file_len > FST_HDR_FOURPACK_DUO_SIZE); /* double pack when hierarchy is large */ - if(fourpack_duo) /* double packing with LZ4 is faster than gzip */ - { - unsigned char *mem_duo; - int lz4_maxlen_duo; - int packed_len_duo; + if(fourpack_duo) /* double packing with LZ4 is faster than gzip */ + { + unsigned char *mem_duo; + int lz4_maxlen_duo; + int packed_len_duo; - lz4_maxlen_duo = LZ4_compressBound(packed_len); - mem_duo = malloc(lz4_maxlen_duo); - packed_len_duo = LZ4_compress((char *)mem, (char *)mem_duo, packed_len); + lz4_maxlen_duo = LZ4_compressBound(packed_len); + mem_duo = 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 */ - fstFwrite(mem_duo, packed_len_duo, 1, xc->handle); - free(mem_duo); - } - else - { - fstFwrite(mem, packed_len, 1, xc->handle); - } + fstWriterVarint(xc->handle, packed_len); /* 1st round compressed length */ + fstFwrite(mem_duo, packed_len_duo, 1, xc->handle); + free(mem_duo); + } + else + { + fstFwrite(mem, packed_len, 1, xc->handle); + } - free(mem); - } + free(mem); + } - fstWriterFseeko(xc, xc->handle, 0, SEEK_END); - eos = ftello(xc->handle); - fstWriterFseeko(xc, xc->handle, hlen, SEEK_SET); - fstWriterUint64(xc->handle, eos - hlen); - fflush(xc->handle); + fstWriterFseeko(xc, xc->handle, 0, SEEK_END); + eos = ftello(xc->handle); + fstWriterFseeko(xc, xc->handle, hlen, SEEK_SET); + fstWriterUint64(xc->handle, eos - hlen); + fflush(xc->handle); - fstWriterFseeko(xc, xc->handle, fixup_offs, SEEK_SET); - fputc(xc->fourpack ? - ( fourpack_duo ? FST_BL_HIER_LZ4DUO : FST_BL_HIER_LZ4) : - FST_BL_HIER, xc->handle); /* actual tag now also == compression type */ + fstWriterFseeko(xc, xc->handle, fixup_offs, SEEK_SET); + fputc(xc->fourpack ? + ( fourpack_duo ? FST_BL_HIER_LZ4DUO : FST_BL_HIER_LZ4) : + FST_BL_HIER, xc->handle); /* actual tag now also == compression type */ - fstWriterFseeko(xc, xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */ - fflush(xc->handle); + fstWriterFseeko(xc, xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */ + fflush(xc->handle); #ifndef __MINGW32__ - sprintf(fnam, "%s.hier", xc->filename); - unlink(fnam); - free(fnam); + sprintf(fnam, "%s.hier", xc->filename); + unlink(fnam); + free(fnam); #endif - } + } - /* finalize out header */ - fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_START_TIME, SEEK_SET); - fstWriterUint64(xc->handle, xc->firsttime); - fstWriterUint64(xc->handle, xc->curtime); - fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_NUM_SCOPES, SEEK_SET); - fstWriterUint64(xc->handle, xc->numscopes); - fstWriterUint64(xc->handle, xc->numsigs); - fstWriterUint64(xc->handle, xc->maxhandle); - fstWriterUint64(xc->handle, xc->secnum); - fflush(xc->handle); + /* finalize out header */ + fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_START_TIME, SEEK_SET); + fstWriterUint64(xc->handle, xc->firsttime); + fstWriterUint64(xc->handle, xc->curtime); + fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_NUM_SCOPES, SEEK_SET); + fstWriterUint64(xc->handle, xc->numscopes); + fstWriterUint64(xc->handle, xc->numsigs); + fstWriterUint64(xc->handle, xc->maxhandle); + fstWriterUint64(xc->handle, xc->secnum); + fflush(xc->handle); - tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam); - free(xc->vchg_mem); xc->vchg_mem = NULL; - tmpfile_close(&xc->curval_handle, &xc->curval_handle_nam); - tmpfile_close(&xc->valpos_handle, &xc->valpos_handle_nam); - tmpfile_close(&xc->geom_handle, &xc->geom_handle_nam); - if(xc->hier_handle) { fclose(xc->hier_handle); xc->hier_handle = NULL; } - if(xc->handle) - { - if(xc->repack_on_close) - { - FILE *fp; - off_t offpnt, uclen; - int flen = strlen(xc->filename); - char *hf = calloc(1, flen + 5); + tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam); + free(xc->vchg_mem); xc->vchg_mem = NULL; + tmpfile_close(&xc->curval_handle, &xc->curval_handle_nam); + tmpfile_close(&xc->valpos_handle, &xc->valpos_handle_nam); + tmpfile_close(&xc->geom_handle, &xc->geom_handle_nam); + if(xc->hier_handle) { fclose(xc->hier_handle); xc->hier_handle = NULL; } + if(xc->handle) + { + if(xc->repack_on_close) + { + FILE *fp; + off_t offpnt, uclen; + int flen = strlen(xc->filename); + char *hf = calloc(1, flen + 5); - strcpy(hf, xc->filename); - strcpy(hf+flen, ".pak"); - fp = fopen(hf, "wb"); + strcpy(hf, xc->filename); + strcpy(hf+flen, ".pak"); + fp = fopen(hf, "wb"); - if(fp) - { - void *dsth; - int zfd; - char gz_membuf[FST_GZIO_LEN]; + if(fp) + { + void *dsth; + int zfd; + char gz_membuf[FST_GZIO_LEN]; - fstWriterFseeko(xc, xc->handle, 0, SEEK_END); - uclen = ftello(xc->handle); + fstWriterFseeko(xc, xc->handle, 0, SEEK_END); + uclen = ftello(xc->handle); - fputc(FST_BL_ZWRAPPER, fp); - fstWriterUint64(fp, 0); - fstWriterUint64(fp, uclen); - fflush(fp); + fputc(FST_BL_ZWRAPPER, fp); + fstWriterUint64(fp, 0); + fstWriterUint64(fp, uclen); + fflush(fp); - fstWriterFseeko(xc, xc->handle, 0, SEEK_SET); - zfd = dup(fileno(fp)); - dsth = gzdopen(zfd, "wb4"); - if(dsth) - { - for(offpnt = 0; offpnt < uclen; offpnt += FST_GZIO_LEN) - { - size_t this_len = ((uclen - offpnt) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - offpnt); - fstFread(gz_membuf, this_len, 1, xc->handle); - gzwrite(dsth, gz_membuf, this_len); - } - gzclose(dsth); - } - else - { - close(zfd); - } - fstWriterFseeko(xc, fp, 0, SEEK_END); - offpnt = ftello(fp); - fstWriterFseeko(xc, fp, 1, SEEK_SET); - fstWriterUint64(fp, offpnt - 1); - fclose(fp); - fclose(xc->handle); xc->handle = NULL; + fstWriterFseeko(xc, xc->handle, 0, SEEK_SET); + zfd = dup(fileno(fp)); + dsth = gzdopen(zfd, "wb4"); + if(dsth) + { + for(offpnt = 0; offpnt < uclen; offpnt += FST_GZIO_LEN) + { + size_t this_len = ((uclen - offpnt) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - offpnt); + fstFread(gz_membuf, this_len, 1, xc->handle); + gzwrite(dsth, gz_membuf, this_len); + } + gzclose(dsth); + } + else + { + close(zfd); + } + fstWriterFseeko(xc, fp, 0, SEEK_END); + offpnt = ftello(fp); + fstWriterFseeko(xc, fp, 1, SEEK_SET); + fstWriterUint64(fp, offpnt - 1); + fclose(fp); + fclose(xc->handle); xc->handle = NULL; - unlink(xc->filename); - rename(hf, xc->filename); - } - else - { - xc->repack_on_close = 0; - fclose(xc->handle); xc->handle = NULL; - } + unlink(xc->filename); + rename(hf, xc->filename); + } + else + { + xc->repack_on_close = 0; + fclose(xc->handle); xc->handle = NULL; + } - free(hf); - } - else - { - fclose(xc->handle); xc->handle = NULL; - } - } + free(hf); + } + else + { + fclose(xc->handle); xc->handle = NULL; + } + } #ifdef __MINGW32__ - { - int flen = strlen(xc->filename); - char *hf = calloc(1, flen + 6); - strcpy(hf, xc->filename); + { + int flen = strlen(xc->filename); + char *hf = calloc(1, flen + 6); + strcpy(hf, xc->filename); - if(xc->compress_hier) - { - strcpy(hf + flen, ".hier"); - unlink(hf); /* no longer needed as a section now exists for this */ - } + if(xc->compress_hier) + { + strcpy(hf + flen, ".hier"); + unlink(hf); /* no longer needed as a section now exists for this */ + } - free(hf); - } + free(hf); + } #endif #ifdef FST_WRITER_PARALLEL - pthread_mutex_destroy(&xc->mutex); - pthread_attr_destroy(&xc->thread_attr); + pthread_mutex_destroy(&xc->mutex); + pthread_attr_destroy(&xc->thread_attr); #endif - if(xc->path_array) - { + if(xc->path_array) + { #ifndef _WAVE_HAVE_JUDY - const uint32_t hashmask = FST_PATH_HASHMASK; + const uint32_t hashmask = FST_PATH_HASHMASK; #endif - JudyHSFreeArray(&(xc->path_array), NULL); - } + JudyHSFreeArray(&(xc->path_array), NULL); + } - free(xc->filename); xc->filename = NULL; - free(xc); - } + free(xc->filename); xc->filename = NULL; + free(xc); + } } @@ -2211,17 +2211,17 @@ void fstWriterSetDate(void *ctx, const char *dat) struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) { - char s[FST_HDR_DATE_SIZE]; - off_t fpos = ftello(xc->handle); - int len = strlen(dat); + char s[FST_HDR_DATE_SIZE]; + off_t fpos = ftello(xc->handle); + int len = strlen(dat); - fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_DATE, SEEK_SET); - memset(s, 0, FST_HDR_DATE_SIZE); - memcpy(s, dat, (len < FST_HDR_DATE_SIZE) ? len : FST_HDR_DATE_SIZE); - fstFwrite(s, FST_HDR_DATE_SIZE, 1, xc->handle); - fflush(xc->handle); - fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET); - } + fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_DATE, SEEK_SET); + memset(s, 0, FST_HDR_DATE_SIZE); + memcpy(s, dat, (len < FST_HDR_DATE_SIZE) ? len : FST_HDR_DATE_SIZE); + fstFwrite(s, FST_HDR_DATE_SIZE, 1, xc->handle); + fflush(xc->handle); + fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET); + } } @@ -2230,17 +2230,17 @@ void fstWriterSetVersion(void *ctx, const char *vers) struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc && vers) { - char s[FST_HDR_SIM_VERSION_SIZE]; - off_t fpos = ftello(xc->handle); - int len = strlen(vers); + char s[FST_HDR_SIM_VERSION_SIZE]; + off_t fpos = ftello(xc->handle); + int len = strlen(vers); - fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_SIM_VERSION, SEEK_SET); - memset(s, 0, FST_HDR_SIM_VERSION_SIZE); - memcpy(s, vers, (len < FST_HDR_SIM_VERSION_SIZE) ? len : FST_HDR_SIM_VERSION_SIZE); - fstFwrite(s, FST_HDR_SIM_VERSION_SIZE, 1, xc->handle); - fflush(xc->handle); - fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET); - } + fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_SIM_VERSION, SEEK_SET); + memset(s, 0, FST_HDR_SIM_VERSION_SIZE); + memcpy(s, vers, (len < FST_HDR_SIM_VERSION_SIZE) ? len : FST_HDR_SIM_VERSION_SIZE); + fstFwrite(s, FST_HDR_SIM_VERSION_SIZE, 1, xc->handle); + fflush(xc->handle); + fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET); + } } @@ -2249,18 +2249,18 @@ void fstWriterSetFileType(void *ctx, enum fstFileType filetype) struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) { - if((filetype >= FST_FT_MIN) && (filetype <= FST_FT_MAX)) - { - off_t fpos = ftello(xc->handle); + if((filetype >= FST_FT_MIN) && (filetype <= FST_FT_MAX)) + { + off_t fpos = ftello(xc->handle); - xc->filetype = filetype; + xc->filetype = filetype; - fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_FILETYPE, SEEK_SET); - fputc(xc->filetype, xc->handle); - fflush(xc->handle); - fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET); - } - } + fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_FILETYPE, SEEK_SET); + fputc(xc->filetype, xc->handle); + fflush(xc->handle); + fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET); + } + } } @@ -2269,15 +2269,15 @@ static void fstWriterSetAttrDoubleArgGeneric(void *ctx, int typ, uint64_t arg1, struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) { - unsigned char buf[11]; /* ceil(64/7) = 10 + null term */ - unsigned char *pnt = fstCopyVarint64ToRight(buf, arg1); - if(arg1) - { - *pnt = 0; /* this converts any *nonzero* arg1 when made a varint into a null-term string */ - } + unsigned char buf[11]; /* ceil(64/7) = 10 + null term */ + unsigned char *pnt = fstCopyVarint64ToRight(buf, arg1); + if(arg1) + { + *pnt = 0; /* this converts any *nonzero* arg1 when made a varint into a null-term string */ + } - fstWriterSetAttrBegin(xc, FST_AT_MISC, typ, (char *)buf, arg2); - } + fstWriterSetAttrBegin(xc, FST_AT_MISC, typ, (char *)buf, arg2); + } } @@ -2286,18 +2286,18 @@ static void fstWriterSetAttrGeneric(void *ctx, const char *comm, int typ, uint64 struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc && comm) { - char *s = strdup(comm); - char *sf = s; + char *s = strdup(comm); + char *sf = s; - while(*s) - { - if((*s == '\n') || (*s == '\r')) *s = ' '; - s++; - } + while(*s) + { + if((*s == '\n') || (*s == '\r')) *s = ' '; + s++; + } - fstWriterSetAttrBegin(xc, FST_AT_MISC, typ, sf, arg); - free(sf); - } + fstWriterSetAttrBegin(xc, FST_AT_MISC, typ, sf, arg); + free(sf); + } } @@ -2306,52 +2306,52 @@ static void fstWriterSetSourceStem_2(void *ctx, const char *path, unsigned int l struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc && path && path[0]) - { - uint64_t sidx = 0; - int slen = strlen(path); + { + uint64_t sidx = 0; + int slen = strlen(path); #ifndef _WAVE_HAVE_JUDY - const uint32_t hashmask = FST_PATH_HASHMASK; - const unsigned char *path2 = (const unsigned char *)path; + const uint32_t hashmask = FST_PATH_HASHMASK; + const unsigned char *path2 = (const unsigned char *)path; #else - char *path2 = alloca(slen + 1); /* judy lacks const qualifier in its JudyHSIns definition */ - strcpy(path2, path); + char *path2 = alloca(slen + 1); /* judy lacks const qualifier in its JudyHSIns definition */ + strcpy(path2, path); #endif - PPvoid_t pv = JudyHSIns(&(xc->path_array), path2, slen, NULL); + PPvoid_t pv = JudyHSIns(&(xc->path_array), path2, slen, NULL); if(*pv) - { + { sidx = (long)(*pv); } else - { - char *rp = NULL; + { + char *rp = NULL; - sidx = ++xc->path_array_count; - *pv = (void *)(long)(xc->path_array_count); + sidx = ++xc->path_array_count; + *pv = (void *)(long)(xc->path_array_count); - if(use_realpath) - { - rp = fstRealpath( + if(use_realpath) + { + rp = fstRealpath( #ifndef _WAVE_HAVE_JUDY - (const char *) + (const char *) #endif - path2, NULL); - } + path2, NULL); + } - fstWriterSetAttrGeneric(xc, rp ? rp : + fstWriterSetAttrGeneric(xc, rp ? rp : #ifndef _WAVE_HAVE_JUDY - (const char *) + (const char *) #endif - path2, FST_MT_PATHNAME, sidx); + path2, FST_MT_PATHNAME, sidx); - if(rp) - { - free(rp); - } - } + if(rp) + { + free(rp); + } + } - fstWriterSetAttrDoubleArgGeneric(xc, typ, sidx, line); - } + fstWriterSetAttrDoubleArgGeneric(xc, typ, sidx, line); + } } @@ -2384,12 +2384,12 @@ void fstWriterSetTimescale(void *ctx, int ts) struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) { - off_t fpos = ftello(xc->handle); - fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_TIMESCALE, SEEK_SET); - fputc(ts & 255, xc->handle); - fflush(xc->handle); - fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET); - } + off_t fpos = ftello(xc->handle); + fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_TIMESCALE, SEEK_SET); + fputc(ts & 255, xc->handle); + fflush(xc->handle); + fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET); + } } @@ -2399,14 +2399,14 @@ struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc && s) { int mat = 0; - int seconds_exp = -9; - int tv = atoi(s); - const char *pnt = s; + int seconds_exp = -9; + int tv = atoi(s); + const char *pnt = s; - while(*pnt) - { + while(*pnt) + { switch(*pnt) - { + { case 'm': seconds_exp = -3; mat = 1; break; case 'u': seconds_exp = -6; mat = 1; break; case 'n': seconds_exp = -9; mat = 1; break; @@ -2418,21 +2418,21 @@ if(xc && s) default: break; } - if(mat) break; + if(mat) break; pnt++; } - if(tv == 10) - { + if(tv == 10) + { seconds_exp++; } else if(tv == 100) - { + { seconds_exp+=2; } - fstWriterSetTimescale(ctx, seconds_exp); + fstWriterSetTimescale(ctx, seconds_exp); } } @@ -2442,12 +2442,12 @@ void fstWriterSetTimezero(void *ctx, int64_t tim) struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) { - off_t fpos = ftello(xc->handle); - fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_TIMEZERO, SEEK_SET); - fstWriterUint64(xc->handle, (xc->timezero = tim)); - fflush(xc->handle); - fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET); - } + off_t fpos = ftello(xc->handle); + fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_TIMEZERO, SEEK_SET); + fstWriterUint64(xc->handle, (xc->timezero = tim)); + fflush(xc->handle); + fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET); + } } @@ -2455,10 +2455,10 @@ void fstWriterSetPackType(void *ctx, enum fstWriterPackType typ) { struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) - { - xc->fastpack = (typ != FST_WR_PT_ZLIB); - xc->fourpack = (typ == FST_WR_PT_LZ4); - } + { + xc->fastpack = (typ != FST_WR_PT_ZLIB); + xc->fourpack = (typ == FST_WR_PT_LZ4); + } } @@ -2466,9 +2466,9 @@ void fstWriterSetRepackOnClose(void *ctx, int enable) { struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) - { - xc->repack_on_close = (enable != 0); - } + { + xc->repack_on_close = (enable != 0); + } } @@ -2476,17 +2476,17 @@ void fstWriterSetParallelMode(void *ctx, int enable) { struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) - { - xc->parallel_was_enabled |= xc->parallel_enabled; /* make sticky */ - xc->parallel_enabled = (enable != 0); + { + xc->parallel_was_enabled |= xc->parallel_enabled; /* make sticky */ + xc->parallel_enabled = (enable != 0); #ifndef FST_WRITER_PARALLEL - if(xc->parallel_enabled) - { - fprintf(stderr, "ERROR: fstWriterSetParallelMode(), FST_WRITER_PARALLEL not enabled during compile, exiting.\n"); - exit(255); - } + if(xc->parallel_enabled) + { + fprintf(stderr, "ERROR: fstWriterSetParallelMode(), FST_WRITER_PARALLEL not enabled during compile, exiting.\n"); + exit(255); + } #endif - } + } } @@ -2494,9 +2494,9 @@ void fstWriterSetDumpSizeLimit(void *ctx, uint64_t numbytes) { struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) - { - xc->dump_size_limit = numbytes; - } + { + xc->dump_size_limit = numbytes; + } } @@ -2542,96 +2542,97 @@ fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir vd, uint32_t len, const char *nam, fstHandle aliasHandle) { struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -int i, nlen, is_real; +unsigned int i; +int nlen, is_real; if(xc && nam) { - if(xc->valpos_mem) - { - fstDestroyMmaps(xc, 0); - } + if(xc->valpos_mem) + { + fstDestroyMmaps(xc, 0); + } - fputc(vt, xc->hier_handle); - fputc(vd, xc->hier_handle); - nlen = strlen(nam); - fstFwrite(nam, nlen, 1, xc->hier_handle); - fputc(0, xc->hier_handle); - xc->hier_file_len += (nlen+3); + fputc(vt, xc->hier_handle); + fputc(vd, xc->hier_handle); + nlen = strlen(nam); + fstFwrite(nam, nlen, 1, xc->hier_handle); + fputc(0, xc->hier_handle); + xc->hier_file_len += (nlen+3); - if((vt == FST_VT_VCD_REAL) || (vt == FST_VT_VCD_REAL_PARAMETER) || (vt == FST_VT_VCD_REALTIME) || (vt == FST_VT_SV_SHORTREAL)) - { - is_real = 1; - len = 8; /* recast number of bytes to that of what a double is */ - } - else - { - is_real = 0; - if(vt == FST_VT_GEN_STRING) - { - len = 0; - } - } + if((vt == FST_VT_VCD_REAL) || (vt == FST_VT_VCD_REAL_PARAMETER) || (vt == FST_VT_VCD_REALTIME) || (vt == FST_VT_SV_SHORTREAL)) + { + is_real = 1; + len = 8; /* recast number of bytes to that of what a double is */ + } + else + { + is_real = 0; + if(vt == FST_VT_GEN_STRING) + { + len = 0; + } + } - xc->hier_file_len += fstWriterVarint(xc->hier_handle, len); + xc->hier_file_len += fstWriterVarint(xc->hier_handle, len); - if(aliasHandle > xc->maxhandle) aliasHandle = 0; - xc->hier_file_len += fstWriterVarint(xc->hier_handle, aliasHandle); - xc->numsigs++; - if(xc->numsigs == xc->next_huge_break) - { - if(xc->fst_break_size < xc->fst_huge_break_size) - { - xc->next_huge_break += FST_ACTIVATE_HUGE_INC; - xc->fst_break_size += xc->fst_orig_break_size; - xc->fst_break_add_size += xc->fst_orig_break_add_size; + if(aliasHandle > xc->maxhandle) aliasHandle = 0; + xc->hier_file_len += fstWriterVarint(xc->hier_handle, aliasHandle); + xc->numsigs++; + if(xc->numsigs == xc->next_huge_break) + { + if(xc->fst_break_size < xc->fst_huge_break_size) + { + xc->next_huge_break += FST_ACTIVATE_HUGE_INC; + xc->fst_break_size += xc->fst_orig_break_size; + xc->fst_break_add_size += xc->fst_orig_break_add_size; - 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_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); + } + } + } - if(!aliasHandle) - { - uint32_t zero = 0; + if(!aliasHandle) + { + uint32_t zero = 0; - if(len) - { - fstWriterVarint(xc->geom_handle, !is_real ? len : 0); /* geom section encodes reals as zero byte */ - } - else - { - fstWriterVarint(xc->geom_handle, 0xFFFFFFFF); /* geom section encodes zero len as 32b -1 */ - } + if(len) + { + fstWriterVarint(xc->geom_handle, !is_real ? len : 0); /* geom section encodes reals as zero byte */ + } + else + { + fstWriterVarint(xc->geom_handle, 0xFFFFFFFF); /* geom section encodes zero len as 32b -1 */ + } - fstFwrite(&xc->maxvalpos, sizeof(uint32_t), 1, xc->valpos_handle); - fstFwrite(&len, sizeof(uint32_t), 1, xc->valpos_handle); - fstFwrite(&zero, sizeof(uint32_t), 1, xc->valpos_handle); - fstFwrite(&zero, sizeof(uint32_t), 1, xc->valpos_handle); + fstFwrite(&xc->maxvalpos, sizeof(uint32_t), 1, xc->valpos_handle); + fstFwrite(&len, sizeof(uint32_t), 1, xc->valpos_handle); + fstFwrite(&zero, sizeof(uint32_t), 1, xc->valpos_handle); + fstFwrite(&zero, sizeof(uint32_t), 1, xc->valpos_handle); - if(!is_real) - { - for(i=0;icurval_handle); - } - } - else - { - fstFwrite(&xc->nan, 8, 1, xc->curval_handle); /* initialize doubles to NaN rather than x */ - } + if(!is_real) + { + for(i=0;icurval_handle); + } + } + else + { + fstFwrite(&xc->nan, 8, 1, xc->curval_handle); /* initialize doubles to NaN rather than x */ + } - xc->maxvalpos+=len; - xc->maxhandle++; - return(xc->maxhandle); - } - else - { - return(aliasHandle); - } - } + xc->maxvalpos+=len; + xc->maxhandle++; + return(xc->maxhandle); + } + else + { + return(aliasHandle); + } + } return(0); } @@ -2643,26 +2644,26 @@ void fstWriterSetScope(void *ctx, enum fstScopeType scopetype, struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) - { - fputc(FST_ST_VCD_SCOPE, xc->hier_handle); - if((scopetype < FST_ST_VCD_MODULE) || (scopetype > FST_ST_MAX)) { scopetype = FST_ST_VCD_MODULE; } - fputc(scopetype, xc->hier_handle); - fprintf(xc->hier_handle, "%s%c%s%c", - scopename ? scopename : "", 0, - scopecomp ? scopecomp : "", 0); + { + fputc(FST_ST_VCD_SCOPE, xc->hier_handle); + if((scopetype < FST_ST_VCD_MODULE) || (scopetype > FST_ST_MAX)) { scopetype = FST_ST_VCD_MODULE; } + fputc(scopetype, xc->hier_handle); + fprintf(xc->hier_handle, "%s%c%s%c", + scopename ? scopename : "", 0, + scopecomp ? scopecomp : "", 0); - if(scopename) - { - xc->hier_file_len += strlen(scopename); - } - if(scopecomp) - { - xc->hier_file_len += strlen(scopecomp); - } + if(scopename) + { + xc->hier_file_len += strlen(scopename); + } + if(scopecomp) + { + xc->hier_file_len += strlen(scopecomp); + } - xc->hier_file_len += 4; /* FST_ST_VCD_SCOPE + scopetype + two string terminating zeros */ - xc->numscopes++; - } + xc->hier_file_len += 4; /* FST_ST_VCD_SCOPE + scopetype + two string terminating zeros */ + xc->numscopes++; + } } @@ -2671,10 +2672,10 @@ void fstWriterSetUpscope(void *ctx) struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) - { - fputc(FST_ST_VCD_UPSCOPE, xc->hier_handle); - xc->hier_file_len++; - } + { + fputc(FST_ST_VCD_UPSCOPE, xc->hier_handle); + xc->hier_file_len++; + } } @@ -2684,33 +2685,33 @@ void fstWriterSetAttrBegin(void *ctx, enum fstAttrType attrtype, int subtype, struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) - { - fputc(FST_ST_GEN_ATTRBEGIN, xc->hier_handle); - if((attrtype < FST_AT_MISC) || (attrtype > FST_AT_MAX)) { attrtype = FST_AT_MISC; subtype = FST_MT_UNKNOWN; } - fputc(attrtype, xc->hier_handle); + { + fputc(FST_ST_GEN_ATTRBEGIN, xc->hier_handle); + if((attrtype < FST_AT_MISC) || (attrtype > FST_AT_MAX)) { attrtype = FST_AT_MISC; subtype = FST_MT_UNKNOWN; } + fputc(attrtype, xc->hier_handle); - switch(attrtype) - { - case FST_AT_ARRAY: if((subtype < FST_AR_NONE) || (subtype > FST_AR_MAX)) subtype = FST_AR_NONE; break; - case FST_AT_ENUM: if((subtype < FST_EV_SV_INTEGER) || (subtype > FST_EV_MAX)) subtype = FST_EV_SV_INTEGER; break; - case FST_AT_PACK: if((subtype < FST_PT_NONE) || (subtype > FST_PT_MAX)) subtype = FST_PT_NONE; break; + switch(attrtype) + { + case FST_AT_ARRAY: if((subtype < FST_AR_NONE) || (subtype > FST_AR_MAX)) subtype = FST_AR_NONE; break; + case FST_AT_ENUM: if((subtype < FST_EV_SV_INTEGER) || (subtype > FST_EV_MAX)) subtype = FST_EV_SV_INTEGER; break; + case FST_AT_PACK: if((subtype < FST_PT_NONE) || (subtype > FST_PT_MAX)) subtype = FST_PT_NONE; break; - case FST_AT_MISC: - default: break; - } + case FST_AT_MISC: + default: break; + } - fputc(subtype, xc->hier_handle); - fprintf(xc->hier_handle, "%s%c", - attrname ? attrname : "", 0); + fputc(subtype, xc->hier_handle); + fprintf(xc->hier_handle, "%s%c", + attrname ? attrname : "", 0); - if(attrname) - { - xc->hier_file_len += strlen(attrname); - } + if(attrname) + { + xc->hier_file_len += strlen(attrname); + } - xc->hier_file_len += 4; /* FST_ST_GEN_ATTRBEGIN + type + subtype + string terminating zero */ - xc->hier_file_len += fstWriterVarint(xc->hier_handle, arg); - } + xc->hier_file_len += 4; /* FST_ST_GEN_ATTRBEGIN + type + subtype + string terminating zero */ + xc->hier_file_len += fstWriterVarint(xc->hier_handle, arg); + } } @@ -2719,10 +2720,10 @@ void fstWriterSetAttrEnd(void *ctx) struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) - { - fputc(FST_ST_GEN_ATTREND, xc->hier_handle); - xc->hier_file_len++; - } + { + fputc(FST_ST_GEN_ATTREND, xc->hier_handle); + xc->hier_file_len++; + } } @@ -2737,113 +2738,113 @@ uint32_t offs; int len; if((xc) && (handle <= xc->maxhandle)) - { - uint32_t fpos; - uint32_t *vm4ip; + { + uint32_t fpos; + uint32_t *vm4ip; - if(!xc->valpos_mem) - { - xc->vc_emitted = 1; - fstWriterCreateMmaps(xc); - } + if(!xc->valpos_mem) + { + xc->vc_emitted = 1; + fstWriterCreateMmaps(xc); + } - handle--; /* move starting at 1 index to starting at 0 */ - vm4ip = &(xc->valpos_mem[4*handle]); + handle--; /* move starting at 1 index to starting at 0 */ + vm4ip = &(xc->valpos_mem[4*handle]); - len = vm4ip[1]; - if(len) /* len of zero = variable length, use fstWriterEmitVariableLengthValueChange */ - { - if(!xc->is_initial_time) - { - fpos = xc->vchg_siz; + len = vm4ip[1]; + if(len) /* len of zero = variable length, use fstWriterEmitVariableLengthValueChange */ + { + if(!xc->is_initial_time) + { + fpos = xc->vchg_siz; - 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); - if(!xc->vchg_mem) - { - fprintf(stderr, "FATAL ERROR, could not realloc() in fstWriterEmitValueChange, exiting.\n"); - exit(255); - } - } + 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); + if(!xc->vchg_mem) + { + fprintf(stderr, "FATAL ERROR, could not realloc() in fstWriterEmitValueChange, exiting.\n"); + exit(255); + } + } #ifdef FST_REMOVE_DUPLICATE_VC - offs = vm4ip[0]; + offs = vm4ip[0]; - if(len != 1) - { - if((vm4ip[3]==xc->tchn_idx)&&(vm4ip[2])) - { - unsigned char *old_value = xc->vchg_mem + vm4ip[2] + 4; /* the +4 skips old vm4ip[2] value */ - while(*(old_value++) & 0x80) { /* skips over varint encoded "xc->tchn_idx - vm4ip[3]" */ } - memcpy(old_value, buf, len); /* overlay new value */ + if(len != 1) + { + if((vm4ip[3]==xc->tchn_idx)&&(vm4ip[2])) + { + unsigned char *old_value = xc->vchg_mem + vm4ip[2] + 4; /* the +4 skips old vm4ip[2] value */ + while(*(old_value++) & 0x80) { /* skips over varint encoded "xc->tchn_idx - vm4ip[3]" */ } + memcpy(old_value, buf, len); /* overlay new value */ - memcpy(xc->curval_mem + offs, buf, len); - return; - } - else - { - if(!memcmp(xc->curval_mem + offs, buf, len)) - { - if(!xc->curtime) - { - int i; - for(i=0;icurval_mem + offs, buf, len); + return; + } + else + { + if(!memcmp(xc->curval_mem + offs, buf, len)) + { + if(!xc->curtime) + { + int i; + for(i=0;icurval_mem + offs, buf, len); - } - else - { - if((vm4ip[3]==xc->tchn_idx)&&(vm4ip[2])) - { - unsigned char *old_value = xc->vchg_mem + vm4ip[2] + 4; /* the +4 skips old vm4ip[2] value */ - while(*(old_value++) & 0x80) { /* skips over varint encoded "xc->tchn_idx - vm4ip[3]" */ } - *old_value = *buf; /* overlay new value */ + memcpy(xc->curval_mem + offs, buf, len); + } + else + { + if((vm4ip[3]==xc->tchn_idx)&&(vm4ip[2])) + { + unsigned char *old_value = xc->vchg_mem + vm4ip[2] + 4; /* the +4 skips old vm4ip[2] value */ + while(*(old_value++) & 0x80) { /* skips over varint encoded "xc->tchn_idx - vm4ip[3]" */ } + *old_value = *buf; /* overlay new value */ - *(xc->curval_mem + offs) = *buf; - return; - } - else - { - if((*(xc->curval_mem + offs)) == (*buf)) - { - if(!xc->curtime) - { - if(*buf != 'x') return; - } - else - { - return; - } - } - } + *(xc->curval_mem + offs) = *buf; + return; + } + else + { + if((*(xc->curval_mem + offs)) == (*buf)) + { + if(!xc->curtime) + { + if(*buf != 'x') return; + } + else + { + return; + } + } + } - *(xc->curval_mem + offs) = *buf; - } + *(xc->curval_mem + offs) = *buf; + } #endif - xc->vchg_siz += fstWriterUint32WithVarint32(xc, &vm4ip[2], xc->tchn_idx - vm4ip[3], buf, len); /* do one fwrite op only */ - vm4ip[3] = xc->tchn_idx; - vm4ip[2] = fpos; - } - else - { - offs = vm4ip[0]; - memcpy(xc->curval_mem + offs, buf, len); - } - } - } + xc->vchg_siz += fstWriterUint32WithVarint32(xc, &vm4ip[2], xc->tchn_idx - vm4ip[3], buf, len); /* do one fwrite op only */ + vm4ip[3] = xc->tchn_idx; + vm4ip[2] = fpos; + } + else + { + offs = vm4ip[0]; + memcpy(xc->curval_mem + offs, buf, len); + } + } + } } @@ -2853,95 +2854,95 @@ struct fstWriterContext *xc = (struct fstWriterContext *)ctx; const unsigned char *buf = (const unsigned char *)val; if((xc) && (handle <= xc->maxhandle)) - { - uint32_t fpos; - uint32_t *vm4ip; + { + uint32_t fpos; + uint32_t *vm4ip; - if(!xc->valpos_mem) - { - xc->vc_emitted = 1; - fstWriterCreateMmaps(xc); - } + if(!xc->valpos_mem) + { + xc->vc_emitted = 1; + fstWriterCreateMmaps(xc); + } - handle--; /* move starting at 1 index to starting at 0 */ - vm4ip = &(xc->valpos_mem[4*handle]); + handle--; /* move starting at 1 index to starting at 0 */ + vm4ip = &(xc->valpos_mem[4*handle]); - /* there is no initial time dump for variable length value changes */ - if(!vm4ip[1]) /* len of zero = variable length */ - { - fpos = xc->vchg_siz; + /* there is no initial time dump for variable length value changes */ + if(!vm4ip[1]) /* len of zero = variable length */ + { + fpos = xc->vchg_siz; - 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); - if(!xc->vchg_mem) - { - fprintf(stderr, "FATAL ERROR, could not realloc() in fstWriterEmitVariableLengthValueChange, exiting.\n"); - exit(255); - } - } + 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); + if(!xc->vchg_mem) + { + fprintf(stderr, "FATAL ERROR, could not realloc() in fstWriterEmitVariableLengthValueChange, exiting.\n"); + exit(255); + } + } - xc->vchg_siz += fstWriterUint32WithVarint32AndLength(xc, &vm4ip[2], xc->tchn_idx - vm4ip[3], buf, len); /* do one fwrite op only */ - vm4ip[3] = xc->tchn_idx; - vm4ip[2] = fpos; - } - } + xc->vchg_siz += fstWriterUint32WithVarint32AndLength(xc, &vm4ip[2], xc->tchn_idx - vm4ip[3], buf, len); /* do one fwrite op only */ + vm4ip[3] = xc->tchn_idx; + vm4ip[2] = fpos; + } + } } void fstWriterEmitTimeChange(void *ctx, uint64_t tim) { struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -int i; +unsigned int i; int skip = 0; if(xc) - { - if(xc->is_initial_time) - { - if(xc->size_limit_locked) /* this resets xc->is_initial_time to one */ - { - return; - } + { + if(xc->is_initial_time) + { + if(xc->size_limit_locked) /* this resets xc->is_initial_time to one */ + { + return; + } - if(!xc->valpos_mem) - { - fstWriterCreateMmaps(xc); - } + if(!xc->valpos_mem) + { + fstWriterCreateMmaps(xc); + } - skip = 1; + skip = 1; - xc->firsttime = (xc->vc_emitted) ? 0: tim; - xc->curtime = 0; - xc->vchg_mem[0] = '!'; - xc->vchg_siz = 1; - fstWriterEmitSectionHeader(xc); - for(i=0;imaxhandle;i++) - { - xc->valpos_mem[4*i+2] = 0; /* zero out offset val */ - xc->valpos_mem[4*i+3] = 0; /* zero out last time change val */ - } - xc->is_initial_time = 0; - } - else - { - if((xc->vchg_siz >= xc->fst_break_size) || (xc->flush_context_pending)) - { - xc->flush_context_pending = 0; - fstWriterFlushContextPrivate(xc); - xc->tchn_cnt++; - fstWriterVarint(xc->tchn_handle, xc->curtime); - } - } + xc->firsttime = (xc->vc_emitted) ? 0: tim; + xc->curtime = 0; + xc->vchg_mem[0] = '!'; + xc->vchg_siz = 1; + fstWriterEmitSectionHeader(xc); + for(i=0;imaxhandle;i++) + { + xc->valpos_mem[4*i+2] = 0; /* zero out offset val */ + xc->valpos_mem[4*i+3] = 0; /* zero out last time change val */ + } + xc->is_initial_time = 0; + } + else + { + if((xc->vchg_siz >= xc->fst_break_size) || (xc->flush_context_pending)) + { + xc->flush_context_pending = 0; + fstWriterFlushContextPrivate(xc); + xc->tchn_cnt++; + fstWriterVarint(xc->tchn_handle, xc->curtime); + } + } - if(!skip) - { - xc->tchn_idx++; - } - fstWriterVarint(xc->tchn_handle, tim - xc->curtime); - xc->tchn_cnt++; - xc->curtime = tim; - } + if(!skip) + { + xc->tchn_idx++; + } + fstWriterVarint(xc->tchn_handle, tim - xc->curtime); + xc->tchn_cnt++; + xc->curtime = tim; + } } @@ -2950,24 +2951,24 @@ void fstWriterEmitDumpActive(void *ctx, int enable) struct fstWriterContext *xc = (struct fstWriterContext *)ctx; if(xc) - { - struct fstBlackoutChain *b = calloc(1, sizeof(struct fstBlackoutChain)); + { + struct fstBlackoutChain *b = calloc(1, sizeof(struct fstBlackoutChain)); - b->tim = xc->curtime; - b->active = (enable != 0); + b->tim = xc->curtime; + b->active = (enable != 0); - xc->num_blackouts++; - if(xc->blackout_curr) - { - xc->blackout_curr->next = b; - xc->blackout_curr = b; - } - else - { - xc->blackout_head = b; - xc->blackout_curr = b; - } - } + xc->num_blackouts++; + if(xc->blackout_curr) + { + xc->blackout_curr->next = b; + xc->blackout_curr = b; + } + else + { + xc->blackout_head = b; + xc->blackout_curr = b; + } + } } @@ -2981,35 +2982,35 @@ if(xc) * private structs */ static const char *vartypes[] = { - "event", "integer", "parameter", "real", "real_parameter", - "reg", "supply0", "supply1", "time", "tri", - "triand", "trior", "trireg", "tri0", "tri1", - "wand", "wire", "wor", "port", "sparray", "realtime", - "string", - "bit", "logic", "int", "shortint", "longint", "byte", "enum", "shortreal" - }; + "event", "integer", "parameter", "real", "real_parameter", + "reg", "supply0", "supply1", "time", "tri", + "triand", "trior", "trireg", "tri0", "tri1", + "wand", "wire", "wor", "port", "sparray", "realtime", + "string", + "bit", "logic", "int", "shortint", "longint", "byte", "enum", "shortreal" + }; static const char *modtypes[] = { - "module", "task", "function", "begin", "fork", "generate", "struct", "union", "class", "interface", "package", "program", + "module", "task", "function", "begin", "fork", "generate", "struct", "union", "class", "interface", "package", "program", "vhdl_architecture", "vhdl_procedure", "vhdl_function", "vhdl_record", "vhdl_process", "vhdl_block", "vhdl_for_generate", "vhdl_if_generate", "vhdl_generate", "vhdl_package" - }; + }; static const char *attrtypes[] = { - "misc", "array", "enum", "class" - }; + "misc", "array", "enum", "class" + }; static const char *arraytypes[] = { - "none", "unpacked", "packed", "sparse" - }; + "none", "unpacked", "packed", "sparse" + }; static const char *enumvaluetypes[] = { - "integer", "bit", "logic", "int", "shortint", "longint", "byte", - "unsigned_integer", "unsigned_bit", "unsigned_logic", "unsigned_int", "unsigned_shortint", "unsigned_longint", "unsigned_byte" - }; + "integer", "bit", "logic", "int", "shortint", "longint", "byte", + "unsigned_integer", "unsigned_bit", "unsigned_logic", "unsigned_int", "unsigned_shortint", "unsigned_longint", "unsigned_byte" + }; static const char *packtypes[] = { - "none", "unpacked", "packed", "tagged_packed" - }; + "none", "unpacked", "packed", "tagged_packed" + }; struct fstCurrHier @@ -3034,11 +3035,11 @@ fstHandle maxhandle; uint64_t num_alias; uint64_t vc_section_count; -uint32_t *signal_lens; /* maxhandle sized */ -unsigned char *signal_typs; /* maxhandle sized */ -unsigned char *process_mask; /* maxhandle-based, bitwise sized */ -uint32_t longest_signal_value_len; /* longest len value encountered */ -unsigned char *temp_signal_value_buf; /* malloced for len in longest_signal_value_len */ +uint32_t *signal_lens; /* maxhandle sized */ +unsigned char *signal_typs; /* maxhandle sized */ +unsigned char *process_mask; /* maxhandle-based, bitwise sized */ +uint32_t longest_signal_value_len; /* longest len value encountered */ +unsigned char *temp_signal_value_buf; /* malloced for len in longest_signal_value_len */ signed char timescale; unsigned char filetype; @@ -3047,10 +3048,10 @@ unsigned use_vcd_extensions : 1; unsigned double_endian_match : 1; unsigned native_doubles_for_cb : 1; unsigned contains_geom_section : 1; -unsigned contains_hier_section : 1; /* valid for hier_pos */ +unsigned contains_hier_section : 1; /* valid for hier_pos */ unsigned contains_hier_section_lz4duo : 1; /* valid for hier_pos (contains_hier_section_lz4 always also set) */ -unsigned contains_hier_section_lz4 : 1; /* valid for hier_pos */ -unsigned limit_range_valid : 1; /* valid for limit_range_start, limit_range_end */ +unsigned contains_hier_section_lz4 : 1; /* valid for hier_pos */ +unsigned limit_range_valid : 1; /* valid for limit_range_start, limit_range_end */ char version[FST_HDR_SIM_VERSION_SIZE + 1]; char date[FST_HDR_DATE_SIZE + 1]; @@ -3118,13 +3119,13 @@ int fstReaderFseeko(struct fstReaderContext *xc, FILE *stream, off_t offset, int int rc = fseeko(stream, offset, whence); if(rc<0) - { - xc->fseek_failed = 1; + { + xc->fseek_failed = 1; #ifdef FST_DEBUG - fprintf(stderr, "Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence); - perror("Why"); + fprintf(stderr, "Seek to #%"PRId64" (whence = %d) failed!\n", offset, whence); + perror("Why"); #endif - } + } return(rc); } @@ -3136,31 +3137,31 @@ static void fstWritex(struct fstReaderContext *xc, void *v, int len) unsigned char *s = (unsigned char *)v; if(len) - { - if(len < FST_WRITEX_MAX) - { - if(xc->writex_pos + len >= FST_WRITEX_MAX) - { - fstWritex(xc, NULL, 0); - } + { + if(len < FST_WRITEX_MAX) + { + if(xc->writex_pos + len >= FST_WRITEX_MAX) + { + fstWritex(xc, NULL, 0); + } - memcpy(xc->writex_buf + xc->writex_pos, s, len); - xc->writex_pos += len; - } - else - { - fstWritex(xc, NULL, 0); - if (write(xc->writex_fd, s, len)) { }; - } - } - else - { - if(xc->writex_pos) - { - if(write(xc->writex_fd, xc->writex_buf, xc->writex_pos)) { }; - xc->writex_pos = 0; - } - } + memcpy(xc->writex_buf + xc->writex_pos, s, len); + xc->writex_pos += len; + } + else + { + fstWritex(xc, NULL, 0); + if (write(xc->writex_fd, s, len)) { }; + } + } + else + { + if(xc->writex_pos) + { + if(write(xc->writex_fd, xc->writex_buf, xc->writex_pos)) { }; + xc->writex_pos = 0; + } + } } #endif @@ -3174,11 +3175,11 @@ struct fstCurrHier *chp; free(xc->curr_flat_hier_nam); xc->curr_flat_hier_nam = NULL; while(xc->curr_hier) - { - chp = xc->curr_hier->prev; - free(xc->curr_hier); - xc->curr_hier = chp; - } + { + chp = xc->curr_hier->prev; + free(xc->curr_hier); + xc->curr_hier = chp; + } } @@ -3186,13 +3187,13 @@ const char *fstReaderGetCurrentFlatScope(void *ctx) { struct fstReaderContext *xc = (struct fstReaderContext *)ctx; if(xc) - { - return(xc->curr_flat_hier_nam ? xc->curr_flat_hier_nam : ""); - } - else - { - return(NULL); - } + { + return(xc->curr_flat_hier_nam ? xc->curr_flat_hier_nam : ""); + } + else + { + return(NULL); + } } @@ -3200,13 +3201,13 @@ void *fstReaderGetCurrentScopeUserInfo(void *ctx) { struct fstReaderContext *xc = (struct fstReaderContext *)ctx; if(xc) - { - return(xc->curr_hier ? xc->curr_hier->user_info : NULL); - } - else - { - return(NULL); - } + { + return(xc->curr_hier ? xc->curr_hier->user_info : NULL); + } + else + { + return(NULL); + } } @@ -3215,19 +3216,19 @@ const char *fstReaderPopScope(void *ctx) struct fstReaderContext *xc = (struct fstReaderContext *)ctx; if(xc && xc->curr_hier) { - struct fstCurrHier *ch = xc->curr_hier; - if(xc->curr_hier->prev) - { - xc->curr_flat_hier_nam[xc->curr_hier->prev->len] = 0; - } - else - { - *xc->curr_flat_hier_nam = 0; - } - xc->curr_hier = xc->curr_hier->prev; - free(ch); - return(xc->curr_flat_hier_nam ? xc->curr_flat_hier_nam : ""); - } + struct fstCurrHier *ch = xc->curr_hier; + if(xc->curr_hier->prev) + { + xc->curr_flat_hier_nam[xc->curr_hier->prev->len] = 0; + } + else + { + *xc->curr_flat_hier_nam = 0; + } + xc->curr_hier = xc->curr_hier->prev; + free(ch); + return(xc->curr_flat_hier_nam ? xc->curr_flat_hier_nam : ""); + } return(NULL); } @@ -3238,9 +3239,9 @@ void fstReaderResetScope(void *ctx) struct fstReaderContext *xc = (struct fstReaderContext *)ctx; if(xc) - { - while(fstReaderPopScope(xc)); /* remove any already-built scoping info */ - } + { + while(fstReaderPopScope(xc)); /* remove any already-built scoping info */ + } } @@ -3248,32 +3249,32 @@ 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)); - 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); - } + { + struct fstCurrHier *ch = 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); + } - if(chl) - { - xc->curr_flat_hier_nam[chl] = '.'; - strcpy(xc->curr_flat_hier_nam + chl + 1, nam); - } - else - { - strcpy(xc->curr_flat_hier_nam, nam); - len--; - } + if(chl) + { + xc->curr_flat_hier_nam[chl] = '.'; + strcpy(xc->curr_flat_hier_nam + chl + 1, nam); + } + else + { + strcpy(xc->curr_flat_hier_nam, nam); + len--; + } - ch->len = len; - ch->prev = xc->curr_hier; - ch->user_info = user_info; - xc->curr_hier = ch; - return(xc->curr_flat_hier_nam); - } + ch->len = len; + ch->prev = xc->curr_hier; + ch->user_info = user_info; + xc->curr_hier = ch; + return(xc->curr_flat_hier_nam); + } return(NULL); } @@ -3284,9 +3285,9 @@ int fstReaderGetCurrentScopeLen(void *ctx) struct fstReaderContext *xc = (struct fstReaderContext *)ctx; if(xc && xc->curr_hier) - { - return(xc->curr_hier->len); - } + { + return(xc->curr_hier->len); + } return(0); } @@ -3313,15 +3314,15 @@ struct fstReaderContext *xc = (struct fstReaderContext *)ctx; if(xc) { - facidx--; - if(facidxmaxhandle) - { - int process_idx = facidx/8; - int process_bit = facidx&7; + facidx--; + if(facidxmaxhandle) + { + int process_idx = facidx/8; + int process_bit = facidx&7; - return( (xc->process_mask[process_idx]&(1<process_mask[process_idx]&(1<maxhandle) - { - int idx = facidx/8; - int bitpos = facidx&7; + facidx--; + if(facidxmaxhandle) + { + int idx = facidx/8; + int bitpos = facidx&7; - xc->process_mask[idx] |= (1<process_mask[idx] |= (1<maxhandle) - { - int idx = facidx/8; - int bitpos = facidx&7; + facidx--; + if(facidxmaxhandle) + { + int idx = facidx/8; + int bitpos = facidx&7; - xc->process_mask[idx] &= (~(1<process_mask[idx] &= (~(1<process_mask, 0xff, (xc->maxhandle+7)/8); - } + memset(xc->process_mask, 0xff, (xc->maxhandle+7)/8); + } } @@ -3379,8 +3380,8 @@ struct fstReaderContext *xc = (struct fstReaderContext *)ctx; if(xc) { - memset(xc->process_mask, 0x00, (xc->maxhandle+7)/8); - } + memset(xc->process_mask, 0x00, (xc->maxhandle+7)/8); + } } @@ -3497,13 +3498,13 @@ uint64_t fstReaderGetDumpActivityChangeTime(void *ctx, uint32_t idx) struct fstReaderContext *xc = (struct fstReaderContext *)ctx; if(xc && (idx < xc->num_blackouts) && (xc->blackout_times)) - { - return(xc->blackout_times[idx]); - } - else - { - return(0); - } + { + return(xc->blackout_times[idx]); + } + else + { + return(0); + } } @@ -3512,13 +3513,13 @@ unsigned char fstReaderGetDumpActivityChangeValue(void *ctx, uint32_t idx) struct fstReaderContext *xc = (struct fstReaderContext *)ctx; if(xc && (idx < xc->num_blackouts) && (xc->blackout_activity)) - { - return(xc->blackout_activity[idx]); - } - else - { - return(0); - } + { + return(xc->blackout_activity[idx]); + } + else + { + return(0); + } } @@ -3527,11 +3528,11 @@ void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_tim struct fstReaderContext *xc = (struct fstReaderContext *)ctx; if(xc) - { - xc->limit_range_valid = 1; - xc->limit_range_start = start_time; - xc->limit_range_end = end_time; - } + { + xc->limit_range_valid = 1; + xc->limit_range_start = start_time; + xc->limit_range_end = end_time; + } } @@ -3540,9 +3541,9 @@ void fstReaderSetUnlimitedTimeRange(void *ctx) struct fstReaderContext *xc = (struct fstReaderContext *)ctx; if(xc) - { - xc->limit_range_valid = 0; - } + { + xc->limit_range_valid = 0; + } } @@ -3551,9 +3552,9 @@ void fstReaderSetVcdExtensions(void *ctx, int enable) struct fstReaderContext *xc = (struct fstReaderContext *)ctx; if(xc) - { - xc->use_vcd_extensions = (enable != 0); - } + { + xc->use_vcd_extensions = (enable != 0); + } } @@ -3561,9 +3562,9 @@ void fstReaderIterBlocksSetNativeDoublesOnCallback(void *ctx, int enable) { struct fstReaderContext *xc = (struct fstReaderContext *)ctx; if(xc) - { - xc->native_doubles_for_cb = (enable != 0); - } + { + xc->native_doubles_for_cb = (enable != 0); + } } /* @@ -3605,158 +3606,158 @@ static int fstReaderRecreateHierFile(struct fstReaderContext *xc) 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); - off_t hl, uclen; - off_t clen = 0; - gzFile zhandle = NULL; - int zfd; - int htyp = FST_BL_SKIP; + { + off_t offs_cache = ftello(xc->f); + char *fnam = malloc(strlen(xc->filename) + 6 + 16 + 32 + 1); + unsigned char *mem = malloc(FST_GZIO_LEN); + off_t hl, uclen; + off_t clen = 0; + gzFile zhandle = NULL; + int zfd; + int htyp = FST_BL_SKIP; - /* can't handle both set at once should never happen in a real file */ - if(!xc->contains_hier_section_lz4 && xc->contains_hier_section) - { - htyp = FST_BL_HIER; - } - else - if(xc->contains_hier_section_lz4 && !xc->contains_hier_section) - { - htyp = xc->contains_hier_section_lz4duo ? FST_BL_HIER_LZ4DUO : FST_BL_HIER_LZ4; - } + /* can't handle both set at once should never happen in a real file */ + if(!xc->contains_hier_section_lz4 && xc->contains_hier_section) + { + htyp = FST_BL_HIER; + } + else + if(xc->contains_hier_section_lz4 && !xc->contains_hier_section) + { + htyp = xc->contains_hier_section_lz4duo ? FST_BL_HIER_LZ4DUO : FST_BL_HIER_LZ4; + } - sprintf(fnam, "%s.hier_%d_%p", xc->filename, getpid(), (void *)xc); - fstReaderFseeko(xc, xc->f, xc->hier_pos, SEEK_SET); - uclen = fstReaderUint64(xc->f); + sprintf(fnam, "%s.hier_%d_%p", xc->filename, getpid(), (void *)xc); + fstReaderFseeko(xc, xc->f, xc->hier_pos, SEEK_SET); + uclen = fstReaderUint64(xc->f); #ifndef __MINGW32__ - fflush(xc->f); + fflush(xc->f); #endif - if(htyp == FST_BL_HIER) - { - fstReaderFseeko(xc, xc->f, xc->hier_pos, SEEK_SET); - uclen = fstReaderUint64(xc->f); + if(htyp == FST_BL_HIER) + { + fstReaderFseeko(xc, xc->f, xc->hier_pos, SEEK_SET); + uclen = fstReaderUint64(xc->f); #ifndef __MINGW32__ - fflush(xc->f); + fflush(xc->f); #endif - zfd = dup(fileno(xc->f)); - zhandle = gzdopen(zfd, "rb"); - if(!zhandle) - { - close(zfd); - free(mem); - free(fnam); - return(0); - } - } - else - if((htyp == FST_BL_HIER_LZ4) || (htyp == FST_BL_HIER_LZ4DUO)) - { - fstReaderFseeko(xc, xc->f, xc->hier_pos - 8, SEEK_SET); /* get section len */ - clen = fstReaderUint64(xc->f) - 16; - uclen = fstReaderUint64(xc->f); + zfd = dup(fileno(xc->f)); + zhandle = gzdopen(zfd, "rb"); + if(!zhandle) + { + close(zfd); + free(mem); + free(fnam); + return(0); + } + } + else + if((htyp == FST_BL_HIER_LZ4) || (htyp == FST_BL_HIER_LZ4DUO)) + { + fstReaderFseeko(xc, xc->f, xc->hier_pos - 8, SEEK_SET); /* get section len */ + clen = fstReaderUint64(xc->f) - 16; + uclen = fstReaderUint64(xc->f); #ifndef __MINGW32__ - fflush(xc->f); + fflush(xc->f); #endif - } + } #ifndef __MINGW32__ - xc->fh = fopen(fnam, "w+b"); + xc->fh = fopen(fnam, "w+b"); if(!xc->fh) #endif { xc->fh = tmpfile_open(&xc->fh_nam); free(fnam); fnam = NULL; if(!xc->fh) - { - tmpfile_close(&xc->fh, &xc->fh_nam); - free(mem); - return(0); - } + { + tmpfile_close(&xc->fh, &xc->fh_nam); + free(mem); + return(0); + } } #ifndef __MINGW32__ - if(fnam) unlink(fnam); + if(fnam) unlink(fnam); #endif - if(htyp == FST_BL_HIER) - { - for(hl = 0; hl < uclen; hl += FST_GZIO_LEN) - { - size_t len = ((uclen - hl) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - hl); - size_t gzreadlen = gzread(zhandle, mem, len); /* rc should equal len... */ - size_t fwlen; + if(htyp == FST_BL_HIER) + { + for(hl = 0; hl < uclen; hl += FST_GZIO_LEN) + { + size_t len = ((uclen - hl) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - hl); + size_t gzreadlen = gzread(zhandle, mem, len); /* rc should equal len... */ + size_t fwlen; - if(gzreadlen != len) - { - pass_status = 0; - break; - } + if(gzreadlen != len) + { + pass_status = 0; + break; + } - fwlen = fstFwrite(mem, len, 1, xc->fh); - if(fwlen != 1) - { - pass_status = 0; - break; - } - } - gzclose(zhandle); - } - else - if(htyp == FST_BL_HIER_LZ4DUO) - { - unsigned char *lz4_cmem = malloc(clen); - unsigned char *lz4_ucmem = malloc(uclen); - unsigned char *lz4_ucmem2; - uint64_t uclen2; - int skiplen2 = 0; + fwlen = fstFwrite(mem, len, 1, xc->fh); + if(fwlen != 1) + { + pass_status = 0; + break; + } + } + gzclose(zhandle); + } + else + if(htyp == FST_BL_HIER_LZ4DUO) + { + unsigned char *lz4_cmem = malloc(clen); + unsigned char *lz4_ucmem = malloc(uclen); + unsigned char *lz4_ucmem2; + uint64_t uclen2; + int skiplen2 = 0; - fstFread(lz4_cmem, clen, 1, xc->f); + fstFread(lz4_cmem, clen, 1, xc->f); - uclen2 = fstGetVarint64(lz4_cmem, &skiplen2); - lz4_ucmem2 = malloc(uclen2); - pass_status = (uclen2 == LZ4_decompress_safe_partial ((char *)lz4_cmem + skiplen2, (char *)lz4_ucmem2, clen - skiplen2, uclen2, uclen2)); - if(pass_status) - { - pass_status = (uclen == LZ4_decompress_safe_partial ((char *)lz4_ucmem2, (char *)lz4_ucmem, uclen2, uclen, uclen)); + uclen2 = fstGetVarint64(lz4_cmem, &skiplen2); + lz4_ucmem2 = 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) + { + pass_status = (uclen == LZ4_decompress_safe_partial ((char *)lz4_ucmem2, (char *)lz4_ucmem, uclen2, uclen, uclen)); - if(fstFwrite(lz4_ucmem, uclen, 1, xc->fh) != 1) - { - pass_status = 0; - } - } + if(fstFwrite(lz4_ucmem, uclen, 1, xc->fh) != 1) + { + pass_status = 0; + } + } - free(lz4_ucmem2); - free(lz4_ucmem); - free(lz4_cmem); - } - else - if(htyp == FST_BL_HIER_LZ4) - { - unsigned char *lz4_cmem = malloc(clen); - unsigned char *lz4_ucmem = malloc(uclen); + free(lz4_ucmem2); + free(lz4_ucmem); + free(lz4_cmem); + } + else + if(htyp == FST_BL_HIER_LZ4) + { + unsigned char *lz4_cmem = malloc(clen); + unsigned char *lz4_ucmem = 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)); + fstFread(lz4_cmem, clen, 1, xc->f); + pass_status = (uclen == LZ4_decompress_safe_partial ((char *)lz4_cmem, (char *)lz4_ucmem, clen, uclen, uclen)); - if(fstFwrite(lz4_ucmem, uclen, 1, xc->fh) != 1) - { - pass_status = 0; - } + if(fstFwrite(lz4_ucmem, uclen, 1, xc->fh) != 1) + { + pass_status = 0; + } - free(lz4_ucmem); - free(lz4_cmem); - } - else /* FST_BL_SKIP */ - { - pass_status = 0; - } + free(lz4_ucmem); + free(lz4_cmem); + } + else /* FST_BL_SKIP */ + { + pass_status = 0; + } - free(mem); - free(fnam); + free(mem); + free(fnam); - fstReaderFseeko(xc, xc->f, offs_cache, SEEK_SET); - } + fstReaderFseeko(xc, xc->f, offs_cache, SEEK_SET); + } return(pass_status); } @@ -3768,15 +3769,15 @@ struct fstReaderContext *xc = (struct fstReaderContext *)ctx; int pass_status = 0; if(xc) - { - pass_status = 1; - if(!xc->fh) - { - pass_status = fstReaderRecreateHierFile(xc); - } + { + pass_status = 1; + if(!xc->fh) + { + pass_status = fstReaderRecreateHierFile(xc); + } - xc->do_rewind = 1; - } + xc->do_rewind = 1; + } return(pass_status); } @@ -3793,149 +3794,149 @@ int ch; if(!xc) return(NULL); if(!xc->fh) - { - if(!fstReaderRecreateHierFile(xc)) - { - return(NULL); - } - } + { + if(!fstReaderRecreateHierFile(xc)) + { + return(NULL); + } + } if(xc->do_rewind) - { - xc->do_rewind = 0; - xc->current_handle = 0; - fstReaderFseeko(xc, xc->fh, 0, SEEK_SET); - clearerr(xc->fh); - } + { + xc->do_rewind = 0; + xc->current_handle = 0; + fstReaderFseeko(xc, xc->fh, 0, SEEK_SET); + clearerr(xc->fh); + } if(!(isfeof=feof(xc->fh))) - { - int tag = fgetc(xc->fh); - switch(tag) - { - case FST_ST_VCD_SCOPE: - xc->hier.htyp = FST_HT_SCOPE; - xc->hier.u.scope.typ = fgetc(xc->fh); - xc->hier.u.scope.name = pnt = xc->str_scope_nam; - while((ch = fgetc(xc->fh))) - { - *(pnt++) = ch; - }; /* scopename */ - *pnt = 0; - xc->hier.u.scope.name_length = pnt - xc->hier.u.scope.name; + { + int tag = fgetc(xc->fh); + switch(tag) + { + case FST_ST_VCD_SCOPE: + xc->hier.htyp = FST_HT_SCOPE; + xc->hier.u.scope.typ = fgetc(xc->fh); + xc->hier.u.scope.name = pnt = xc->str_scope_nam; + while((ch = fgetc(xc->fh))) + { + *(pnt++) = ch; + }; /* scopename */ + *pnt = 0; + xc->hier.u.scope.name_length = pnt - xc->hier.u.scope.name; - xc->hier.u.scope.component = pnt = xc->str_scope_comp; - while((ch = fgetc(xc->fh))) - { - *(pnt++) = ch; - }; /* scopecomp */ - *pnt = 0; - xc->hier.u.scope.component_length = pnt - xc->hier.u.scope.component; - break; + xc->hier.u.scope.component = pnt = xc->str_scope_comp; + while((ch = fgetc(xc->fh))) + { + *(pnt++) = ch; + }; /* scopecomp */ + *pnt = 0; + xc->hier.u.scope.component_length = pnt - xc->hier.u.scope.component; + break; - case FST_ST_VCD_UPSCOPE: - xc->hier.htyp = FST_HT_UPSCOPE; - break; + case FST_ST_VCD_UPSCOPE: + xc->hier.htyp = FST_HT_UPSCOPE; + break; - case FST_ST_GEN_ATTRBEGIN: - xc->hier.htyp = FST_HT_ATTRBEGIN; - xc->hier.u.attr.typ = fgetc(xc->fh); - xc->hier.u.attr.subtype = fgetc(xc->fh); - xc->hier.u.attr.name = pnt = xc->str_scope_nam; - while((ch = fgetc(xc->fh))) - { - *(pnt++) = ch; - }; /* scopename */ - *pnt = 0; - xc->hier.u.attr.name_length = pnt - xc->hier.u.scope.name; + case FST_ST_GEN_ATTRBEGIN: + xc->hier.htyp = FST_HT_ATTRBEGIN; + xc->hier.u.attr.typ = fgetc(xc->fh); + xc->hier.u.attr.subtype = fgetc(xc->fh); + xc->hier.u.attr.name = pnt = xc->str_scope_nam; + while((ch = fgetc(xc->fh))) + { + *(pnt++) = ch; + }; /* scopename */ + *pnt = 0; + xc->hier.u.attr.name_length = pnt - xc->hier.u.scope.name; - xc->hier.u.attr.arg = fstReaderVarint64(xc->fh); + xc->hier.u.attr.arg = fstReaderVarint64(xc->fh); - if(xc->hier.u.attr.typ == FST_AT_MISC) - { - if((xc->hier.u.attr.subtype == FST_MT_SOURCESTEM)||(xc->hier.u.attr.subtype == FST_MT_SOURCEISTEM)) - { - int sidx_skiplen_dummy = 0; - xc->hier.u.attr.arg_from_name = fstGetVarint64((unsigned char *)xc->str_scope_nam, &sidx_skiplen_dummy); - } - } - break; + if(xc->hier.u.attr.typ == FST_AT_MISC) + { + if((xc->hier.u.attr.subtype == FST_MT_SOURCESTEM)||(xc->hier.u.attr.subtype == FST_MT_SOURCEISTEM)) + { + int sidx_skiplen_dummy = 0; + xc->hier.u.attr.arg_from_name = fstGetVarint64((unsigned char *)xc->str_scope_nam, &sidx_skiplen_dummy); + } + } + break; - case FST_ST_GEN_ATTREND: - xc->hier.htyp = FST_HT_ATTREND; - break; + case FST_ST_GEN_ATTREND: + xc->hier.htyp = FST_HT_ATTREND; + break; - case FST_VT_VCD_EVENT: - case FST_VT_VCD_INTEGER: - case FST_VT_VCD_PARAMETER: - case FST_VT_VCD_REAL: - case FST_VT_VCD_REAL_PARAMETER: - case FST_VT_VCD_REG: - case FST_VT_VCD_SUPPLY0: - case FST_VT_VCD_SUPPLY1: - case FST_VT_VCD_TIME: - case FST_VT_VCD_TRI: - case FST_VT_VCD_TRIAND: - case FST_VT_VCD_TRIOR: - case FST_VT_VCD_TRIREG: - case FST_VT_VCD_TRI0: - case FST_VT_VCD_TRI1: - case FST_VT_VCD_WAND: - case FST_VT_VCD_WIRE: - case FST_VT_VCD_WOR: - case FST_VT_VCD_PORT: - case FST_VT_VCD_SPARRAY: - case FST_VT_VCD_REALTIME: - case FST_VT_GEN_STRING: - case FST_VT_SV_BIT: - case FST_VT_SV_LOGIC: - case FST_VT_SV_INT: - case FST_VT_SV_SHORTINT: - case FST_VT_SV_LONGINT: - case FST_VT_SV_BYTE: - case FST_VT_SV_ENUM: - case FST_VT_SV_SHORTREAL: - xc->hier.htyp = FST_HT_VAR; - xc->hier.u.var.svt_workspace = FST_SVT_NONE; - xc->hier.u.var.sdt_workspace = FST_SDT_NONE; - xc->hier.u.var.sxt_workspace = 0; - xc->hier.u.var.typ = tag; - xc->hier.u.var.direction = fgetc(xc->fh); - xc->hier.u.var.name = pnt = xc->str_scope_nam; - while((ch = fgetc(xc->fh))) - { - *(pnt++) = ch; - }; /* varname */ - *pnt = 0; - xc->hier.u.var.name_length = pnt - xc->hier.u.var.name; - xc->hier.u.var.length = fstReaderVarint32(xc->fh); - if(tag == FST_VT_VCD_PORT) - { - xc->hier.u.var.length -= 2; /* removal of delimiting spaces */ - xc->hier.u.var.length /= 3; /* port -> signal size adjust */ - } + case FST_VT_VCD_EVENT: + case FST_VT_VCD_INTEGER: + case FST_VT_VCD_PARAMETER: + case FST_VT_VCD_REAL: + case FST_VT_VCD_REAL_PARAMETER: + case FST_VT_VCD_REG: + case FST_VT_VCD_SUPPLY0: + case FST_VT_VCD_SUPPLY1: + case FST_VT_VCD_TIME: + case FST_VT_VCD_TRI: + case FST_VT_VCD_TRIAND: + case FST_VT_VCD_TRIOR: + case FST_VT_VCD_TRIREG: + case FST_VT_VCD_TRI0: + case FST_VT_VCD_TRI1: + case FST_VT_VCD_WAND: + case FST_VT_VCD_WIRE: + case FST_VT_VCD_WOR: + case FST_VT_VCD_PORT: + case FST_VT_VCD_SPARRAY: + case FST_VT_VCD_REALTIME: + case FST_VT_GEN_STRING: + case FST_VT_SV_BIT: + case FST_VT_SV_LOGIC: + case FST_VT_SV_INT: + case FST_VT_SV_SHORTINT: + case FST_VT_SV_LONGINT: + case FST_VT_SV_BYTE: + case FST_VT_SV_ENUM: + case FST_VT_SV_SHORTREAL: + xc->hier.htyp = FST_HT_VAR; + xc->hier.u.var.svt_workspace = FST_SVT_NONE; + xc->hier.u.var.sdt_workspace = FST_SDT_NONE; + xc->hier.u.var.sxt_workspace = 0; + xc->hier.u.var.typ = tag; + xc->hier.u.var.direction = fgetc(xc->fh); + xc->hier.u.var.name = pnt = xc->str_scope_nam; + while((ch = fgetc(xc->fh))) + { + *(pnt++) = ch; + }; /* varname */ + *pnt = 0; + xc->hier.u.var.name_length = pnt - xc->hier.u.var.name; + xc->hier.u.var.length = fstReaderVarint32(xc->fh); + if(tag == FST_VT_VCD_PORT) + { + xc->hier.u.var.length -= 2; /* removal of delimiting spaces */ + xc->hier.u.var.length /= 3; /* port -> signal size adjust */ + } - alias = fstReaderVarint32(xc->fh); + alias = fstReaderVarint32(xc->fh); - if(!alias) - { - xc->current_handle++; - xc->hier.u.var.handle = xc->current_handle; - xc->hier.u.var.is_alias = 0; - } - else - { - xc->hier.u.var.handle = alias; - xc->hier.u.var.is_alias = 1; - } + if(!alias) + { + xc->current_handle++; + xc->hier.u.var.handle = xc->current_handle; + xc->hier.u.var.is_alias = 0; + } + else + { + xc->hier.u.var.handle = alias; + xc->hier.u.var.is_alias = 1; + } - break; + break; - default: - isfeof = 1; - break; - } - } + default: + isfeof = 1; + break; + } + } return(!isfeof ? &xc->hier : NULL); } @@ -3950,7 +3951,7 @@ int ch, scopetype; int vartype; uint32_t len, alias; /* uint32_t maxvalpos=0; */ -int num_signal_dyn = 65536; +unsigned int num_signal_dyn = 65536; int attrtype, subtype; uint64_t attrarg; fstHandle maxhandle_scanbuild; @@ -3960,23 +3961,23 @@ if(!xc) return(0); xc->longest_signal_value_len = 32; /* arbitrarily set at 32...this is much longer than an expanded double */ if(!xc->fh) - { - if(!fstReaderRecreateHierFile(xc)) - { - return(0); - } - } + { + if(!fstReaderRecreateHierFile(xc)) + { + return(0); + } + } str = malloc(FST_ID_NAM_ATTR_SIZ+1); if(fv) - { - char time_dimension[2] = {0, 0}; - int time_scale = 1; + { + char time_dimension[2] = {0, 0}; + int time_scale = 1; - 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); + 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); switch(xc->timescale) { @@ -4014,8 +4015,8 @@ if(fv) default: time_dimension[0] = 'n'; break; } - if(fv) fprintf(fv, "$timescale\n\t%d%ss\n$end\n", time_scale, time_dimension); - } + if(fv) fprintf(fv, "$timescale\n\t%d%ss\n$end\n", time_scale, time_dimension); + } xc->maxhandle = 0; xc->num_alias = 0; @@ -4028,179 +4029,179 @@ xc->signal_typs = malloc(num_signal_dyn*sizeof(unsigned char)); fstReaderFseeko(xc, xc->fh, 0, SEEK_SET); while(!feof(xc->fh)) - { - int tag = fgetc(xc->fh); - switch(tag) - { - case FST_ST_VCD_SCOPE: - scopetype = fgetc(xc->fh); - if((scopetype < FST_ST_MIN) || (scopetype > FST_ST_MAX)) scopetype = FST_ST_VCD_MODULE; - pnt = str; - while((ch = fgetc(xc->fh))) - { - *(pnt++) = ch; - }; /* scopename */ - *pnt = 0; - while(fgetc(xc->fh)) { }; /* scopecomp */ + { + int tag = fgetc(xc->fh); + switch(tag) + { + case FST_ST_VCD_SCOPE: + scopetype = fgetc(xc->fh); + if((scopetype < FST_ST_MIN) || (scopetype > FST_ST_MAX)) scopetype = FST_ST_VCD_MODULE; + pnt = str; + while((ch = fgetc(xc->fh))) + { + *(pnt++) = ch; + }; /* scopename */ + *pnt = 0; + while(fgetc(xc->fh)) { }; /* scopecomp */ - if(fv) fprintf(fv, "$scope %s %s $end\n", modtypes[scopetype], str); - break; + if(fv) fprintf(fv, "$scope %s %s $end\n", modtypes[scopetype], str); + break; - case FST_ST_VCD_UPSCOPE: - if(fv) fprintf(fv, "$upscope $end\n"); - break; + case FST_ST_VCD_UPSCOPE: + if(fv) fprintf(fv, "$upscope $end\n"); + break; - case FST_ST_GEN_ATTRBEGIN: - attrtype = fgetc(xc->fh); - subtype = fgetc(xc->fh); - pnt = str; - while((ch = fgetc(xc->fh))) - { - *(pnt++) = ch; - }; /* attrname */ - *pnt = 0; + case FST_ST_GEN_ATTRBEGIN: + attrtype = fgetc(xc->fh); + subtype = fgetc(xc->fh); + pnt = str; + while((ch = fgetc(xc->fh))) + { + *(pnt++) = ch; + }; /* attrname */ + *pnt = 0; - if(!str[0]) { strcpy(str, "\"\""); } + if(!str[0]) { strcpy(str, "\"\""); } - attrarg = fstReaderVarint64(xc->fh); + attrarg = fstReaderVarint64(xc->fh); - if(fv && xc->use_vcd_extensions) - { - 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); - 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); - 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); - break; - case FST_AT_MISC: - default: attrtype = FST_AT_MISC; - if(subtype == FST_MT_COMMENT) - { - fprintf(fv, "$comment\n\t%s\n$end\n", str); - } - else - { - if((subtype == FST_MT_SOURCESTEM)||(subtype == FST_MT_SOURCEISTEM)) - { - int sidx_skiplen_dummy = 0; - uint64_t sidx = fstGetVarint64((unsigned char *)str, &sidx_skiplen_dummy); + if(fv && xc->use_vcd_extensions) + { + 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); + 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); + 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); + break; + case FST_AT_MISC: + default: attrtype = FST_AT_MISC; + if(subtype == FST_MT_COMMENT) + { + fprintf(fv, "$comment\n\t%s\n$end\n", str); + } + else + { + if((subtype == FST_MT_SOURCESTEM)||(subtype == FST_MT_SOURCEISTEM)) + { + 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); - } - else - { - fprintf(fv, "$attrbegin %s %02x %s %"PRId64" $end\n", attrtypes[attrtype], subtype, str, attrarg); - } - } - break; - } - } - break; + 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); + } + } + break; + } + } + break; - case FST_ST_GEN_ATTREND: - if(fv && xc->use_vcd_extensions) fprintf(fv, "$attrend $end\n"); - break; + case FST_ST_GEN_ATTREND: + if(fv && xc->use_vcd_extensions) fprintf(fv, "$attrend $end\n"); + break; - case FST_VT_VCD_EVENT: - case FST_VT_VCD_INTEGER: - case FST_VT_VCD_PARAMETER: - case FST_VT_VCD_REAL: - case FST_VT_VCD_REAL_PARAMETER: - case FST_VT_VCD_REG: - case FST_VT_VCD_SUPPLY0: - case FST_VT_VCD_SUPPLY1: - case FST_VT_VCD_TIME: - case FST_VT_VCD_TRI: - case FST_VT_VCD_TRIAND: - case FST_VT_VCD_TRIOR: - case FST_VT_VCD_TRIREG: - case FST_VT_VCD_TRI0: - case FST_VT_VCD_TRI1: - case FST_VT_VCD_WAND: - case FST_VT_VCD_WIRE: - case FST_VT_VCD_WOR: - case FST_VT_VCD_PORT: - case FST_VT_VCD_SPARRAY: - case FST_VT_VCD_REALTIME: - case FST_VT_GEN_STRING: - case FST_VT_SV_BIT: - case FST_VT_SV_LOGIC: - case FST_VT_SV_INT: - case FST_VT_SV_SHORTINT: - case FST_VT_SV_LONGINT: - case FST_VT_SV_BYTE: - case FST_VT_SV_ENUM: - case FST_VT_SV_SHORTREAL: - vartype = tag; - /* vardir = */ fgetc(xc->fh); /* unused in VCD reader, but need to advance read pointer */ - pnt = str; - while((ch = fgetc(xc->fh))) - { - *(pnt++) = ch; - }; /* varname */ - *pnt = 0; - len = fstReaderVarint32(xc->fh); - alias = fstReaderVarint32(xc->fh); + case FST_VT_VCD_EVENT: + case FST_VT_VCD_INTEGER: + case FST_VT_VCD_PARAMETER: + case FST_VT_VCD_REAL: + case FST_VT_VCD_REAL_PARAMETER: + case FST_VT_VCD_REG: + case FST_VT_VCD_SUPPLY0: + case FST_VT_VCD_SUPPLY1: + case FST_VT_VCD_TIME: + case FST_VT_VCD_TRI: + case FST_VT_VCD_TRIAND: + case FST_VT_VCD_TRIOR: + case FST_VT_VCD_TRIREG: + case FST_VT_VCD_TRI0: + case FST_VT_VCD_TRI1: + case FST_VT_VCD_WAND: + case FST_VT_VCD_WIRE: + case FST_VT_VCD_WOR: + case FST_VT_VCD_PORT: + case FST_VT_VCD_SPARRAY: + case FST_VT_VCD_REALTIME: + case FST_VT_GEN_STRING: + case FST_VT_SV_BIT: + case FST_VT_SV_LOGIC: + case FST_VT_SV_INT: + case FST_VT_SV_SHORTINT: + case FST_VT_SV_LONGINT: + case FST_VT_SV_BYTE: + case FST_VT_SV_ENUM: + case FST_VT_SV_SHORTREAL: + vartype = tag; + /* vardir = */ fgetc(xc->fh); /* unused in VCD reader, but need to advance read pointer */ + pnt = str; + while((ch = fgetc(xc->fh))) + { + *(pnt++) = ch; + }; /* varname */ + *pnt = 0; + len = fstReaderVarint32(xc->fh); + alias = fstReaderVarint32(xc->fh); - if(!alias) - { - 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[xc->maxhandle] = len; - xc->signal_typs[xc->maxhandle] = vartype; + if(!alias) + { + 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[xc->maxhandle] = len; + xc->signal_typs[xc->maxhandle] = vartype; - /* maxvalpos+=len; */ - if(len > xc->longest_signal_value_len) - { - xc->longest_signal_value_len = len; - } + /* maxvalpos+=len; */ + if(len > xc->longest_signal_value_len) + { + xc->longest_signal_value_len = len; + } - if((vartype == FST_VT_VCD_REAL) || (vartype == FST_VT_VCD_REAL_PARAMETER) || (vartype == FST_VT_VCD_REALTIME) || (vartype == FST_VT_SV_SHORTREAL)) - { - len = (vartype != FST_VT_SV_SHORTREAL) ? 64 : 32; - xc->signal_typs[xc->maxhandle] = FST_VT_VCD_REAL; - } - if(fv) - { - 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); - } - xc->maxhandle++; - } - else - { - if((vartype == FST_VT_VCD_REAL) || (vartype == FST_VT_VCD_REAL_PARAMETER) || (vartype == FST_VT_VCD_REALTIME) || (vartype == FST_VT_SV_SHORTREAL)) - { - len = (vartype != FST_VT_SV_SHORTREAL) ? 64 : 32; - xc->signal_typs[xc->maxhandle] = FST_VT_VCD_REAL; - } - if(fv) - { - 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); - } - xc->num_alias++; - } + if((vartype == FST_VT_VCD_REAL) || (vartype == FST_VT_VCD_REAL_PARAMETER) || (vartype == FST_VT_VCD_REALTIME) || (vartype == FST_VT_SV_SHORTREAL)) + { + len = (vartype != FST_VT_SV_SHORTREAL) ? 64 : 32; + xc->signal_typs[xc->maxhandle] = FST_VT_VCD_REAL; + } + if(fv) + { + 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); + } + xc->maxhandle++; + } + else + { + if((vartype == FST_VT_VCD_REAL) || (vartype == FST_VT_VCD_REAL_PARAMETER) || (vartype == FST_VT_VCD_REALTIME) || (vartype == FST_VT_SV_SHORTREAL)) + { + len = (vartype != FST_VT_SV_SHORTREAL) ? 64 : 32; + xc->signal_typs[xc->maxhandle] = FST_VT_VCD_REAL; + } + if(fv) + { + 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); + } + xc->num_alias++; + } - break; + break; - default: - break; - } - } + default: + break; + } + } 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 */ @@ -4237,306 +4238,306 @@ int gzread_pass_status = 1; sectype = fgetc(xc->f); if(sectype == FST_BL_ZWRAPPER) - { - FILE *fcomp; - off_t offpnt, uclen; - char gz_membuf[FST_GZIO_LEN]; - void *zhandle; - int zfd; + { + FILE *fcomp; + off_t offpnt, uclen; + char gz_membuf[FST_GZIO_LEN]; + void *zhandle; + int zfd; int flen = strlen(xc->filename); char *hf; - seclen = fstReaderUint64(xc->f); - uclen = fstReaderUint64(xc->f); + seclen = fstReaderUint64(xc->f); + uclen = fstReaderUint64(xc->f); - if(!seclen) return(0); /* not finished compressing, this is a failed read */ + if(!seclen) return(0); /* not finished compressing, this is a failed read */ hf = calloc(1, flen + 16 + 32 + 1); - sprintf(hf, "%s.upk_%d_%p", xc->filename, getpid(), (void *)xc); - fcomp = fopen(hf, "w+b"); - if(!fcomp) - { - fcomp = tmpfile_open(&xc->f_nam); - free(hf); hf = NULL; - if(!fcomp) { tmpfile_close(&fcomp, &xc->f_nam); return(0); } - } + sprintf(hf, "%s.upk_%d_%p", xc->filename, getpid(), (void *)xc); + fcomp = fopen(hf, "w+b"); + if(!fcomp) + { + fcomp = tmpfile_open(&xc->f_nam); + free(hf); hf = NULL; + if(!fcomp) { tmpfile_close(&fcomp, &xc->f_nam); return(0); } + } #if defined(FST_MACOSX) - setvbuf(fcomp, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */ + setvbuf(fcomp, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */ #endif #ifdef __MINGW32__ - setvbuf(fcomp, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */ - xc->filename_unpacked = hf; + setvbuf(fcomp, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */ + xc->filename_unpacked = hf; #else - if(hf) - { - unlink(hf); - free(hf); - } + if(hf) + { + unlink(hf); + free(hf); + } #endif - fstReaderFseeko(xc, xc->f, 1+8+8, SEEK_SET); + fstReaderFseeko(xc, xc->f, 1+8+8, SEEK_SET); #ifndef __MINGW32__ - fflush(xc->f); + fflush(xc->f); #endif - zfd = dup(fileno(xc->f)); - zhandle = gzdopen(zfd, "rb"); - if(zhandle) - { - for(offpnt = 0; offpnt < uclen; offpnt += FST_GZIO_LEN) - { - size_t this_len = ((uclen - offpnt) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - offpnt); - size_t gzreadlen = gzread(zhandle, gz_membuf, this_len); - size_t fwlen; + zfd = dup(fileno(xc->f)); + zhandle = gzdopen(zfd, "rb"); + if(zhandle) + { + for(offpnt = 0; offpnt < uclen; offpnt += FST_GZIO_LEN) + { + size_t this_len = ((uclen - offpnt) > FST_GZIO_LEN) ? FST_GZIO_LEN : (uclen - offpnt); + size_t gzreadlen = gzread(zhandle, gz_membuf, this_len); + size_t fwlen; - if(gzreadlen != this_len) - { - gzread_pass_status = 0; - break; - } - fwlen = fstFwrite(gz_membuf, this_len, 1, fcomp); - if(fwlen != 1) - { - gzread_pass_status = 0; - break; - } - } - gzclose(zhandle); - } - else - { - close(zfd); - } - fflush(fcomp); - fclose(xc->f); - xc->f = fcomp; - } + if(gzreadlen != this_len) + { + gzread_pass_status = 0; + break; + } + fwlen = fstFwrite(gz_membuf, this_len, 1, fcomp); + if(fwlen != 1) + { + gzread_pass_status = 0; + break; + } + } + gzclose(zhandle); + } + else + { + close(zfd); + } + fflush(fcomp); + fclose(xc->f); + xc->f = fcomp; + } if(gzread_pass_status) - { - fstReaderFseeko(xc, xc->f, 0, SEEK_END); - endfile = ftello(xc->f); + { + fstReaderFseeko(xc, xc->f, 0, SEEK_END); + endfile = ftello(xc->f); - while(blkpos < endfile) - { - fstReaderFseeko(xc, xc->f, blkpos, SEEK_SET); + while(blkpos < endfile) + { + fstReaderFseeko(xc, xc->f, blkpos, SEEK_SET); - sectype = fgetc(xc->f); - seclen = fstReaderUint64(xc->f); + sectype = fgetc(xc->f); + seclen = fstReaderUint64(xc->f); - if(sectype == EOF) - { - break; - } + if(sectype == EOF) + { + break; + } if((hdr_incomplete) && (!seclen)) { break; } - if(!hdr_seen && (sectype != FST_BL_HDR)) - { - break; - } + if(!hdr_seen && (sectype != FST_BL_HDR)) + { + break; + } - blkpos++; - if(sectype == FST_BL_HDR) - { - if(!hdr_seen) - { - int ch; - double dcheck; + blkpos++; + if(sectype == FST_BL_HDR) + { + if(!hdr_seen) + { + int ch; + double dcheck; - xc->start_time = fstReaderUint64(xc->f); - xc->end_time = fstReaderUint64(xc->f); + xc->start_time = fstReaderUint64(xc->f); + xc->end_time = fstReaderUint64(xc->f); - hdr_incomplete = (xc->start_time == 0) && (xc->end_time == 0); + hdr_incomplete = (xc->start_time == 0) && (xc->end_time == 0); - fstFread(&dcheck, 8, 1, xc->f); - xc->double_endian_match = (dcheck == FST_DOUBLE_ENDTEST); - if(!xc->double_endian_match) - { - union { - unsigned char rvs_buf[8]; - double d; - } vu; + fstFread(&dcheck, 8, 1, xc->f); + xc->double_endian_match = (dcheck == FST_DOUBLE_ENDTEST); + if(!xc->double_endian_match) + { + union { + unsigned char rvs_buf[8]; + double d; + } vu; - unsigned char *dcheck_alias = (unsigned char *)&dcheck; - int rvs_idx; + unsigned char *dcheck_alias = (unsigned char *)&dcheck; + int rvs_idx; - for(rvs_idx=0;rvs_idx<8;rvs_idx++) - { - vu.rvs_buf[rvs_idx] = dcheck_alias[7-rvs_idx]; - } - if(vu.d != FST_DOUBLE_ENDTEST) - { - break; /* either corrupt file or wrong architecture (offset +33 also functions as matchword) */ - } - } + for(rvs_idx=0;rvs_idx<8;rvs_idx++) + { + vu.rvs_buf[rvs_idx] = dcheck_alias[7-rvs_idx]; + } + if(vu.d != FST_DOUBLE_ENDTEST) + { + break; /* either corrupt file or wrong architecture (offset +33 also functions as matchword) */ + } + } - hdr_seen = 1; + hdr_seen = 1; - xc->mem_used_by_writer = fstReaderUint64(xc->f); - xc->scope_count = fstReaderUint64(xc->f); - xc->var_count = fstReaderUint64(xc->f); - xc->maxhandle = fstReaderUint64(xc->f); - xc->num_alias = xc->var_count - xc->maxhandle; - xc->vc_section_count = fstReaderUint64(xc->f); - ch = fgetc(xc->f); - xc->timescale = (signed char)ch; - fstFread(xc->version, FST_HDR_SIM_VERSION_SIZE, 1, xc->f); - xc->version[FST_HDR_SIM_VERSION_SIZE] = 0; - fstFread(xc->date, FST_HDR_DATE_SIZE, 1, xc->f); - xc->date[FST_HDR_DATE_SIZE] = 0; - ch = fgetc(xc->f); - xc->filetype = (unsigned char)ch; - xc->timezero = fstReaderUint64(xc->f); - } - } - else if((sectype == FST_BL_VCDATA) || (sectype == FST_BL_VCDATA_DYN_ALIAS) || (sectype == FST_BL_VCDATA_DYN_ALIAS2)) - { - if(hdr_incomplete) - { - uint64_t bt = fstReaderUint64(xc->f); - xc->end_time = fstReaderUint64(xc->f); + xc->mem_used_by_writer = fstReaderUint64(xc->f); + xc->scope_count = fstReaderUint64(xc->f); + xc->var_count = fstReaderUint64(xc->f); + xc->maxhandle = fstReaderUint64(xc->f); + xc->num_alias = xc->var_count - xc->maxhandle; + xc->vc_section_count = fstReaderUint64(xc->f); + ch = fgetc(xc->f); + xc->timescale = (signed char)ch; + fstFread(xc->version, FST_HDR_SIM_VERSION_SIZE, 1, xc->f); + xc->version[FST_HDR_SIM_VERSION_SIZE] = 0; + fstFread(xc->date, FST_HDR_DATE_SIZE, 1, xc->f); + xc->date[FST_HDR_DATE_SIZE] = 0; + ch = fgetc(xc->f); + xc->filetype = (unsigned char)ch; + xc->timezero = fstReaderUint64(xc->f); + } + } + else if((sectype == FST_BL_VCDATA) || (sectype == FST_BL_VCDATA_DYN_ALIAS) || (sectype == FST_BL_VCDATA_DYN_ALIAS2)) + { + if(hdr_incomplete) + { + uint64_t bt = fstReaderUint64(xc->f); + xc->end_time = fstReaderUint64(xc->f); - if(!vc_section_count_actual) { xc->start_time = bt; } - } + if(!vc_section_count_actual) { xc->start_time = bt; } + } - vc_section_count_actual++; - } - else if(sectype == FST_BL_GEOM) - { - if(!hdr_incomplete) - { - uint64_t clen = seclen - 24; - uint64_t uclen = fstReaderUint64(xc->f); - unsigned char *ucdata = malloc(uclen); - unsigned char *pnt = ucdata; - int i; + vc_section_count_actual++; + } + else if(sectype == FST_BL_GEOM) + { + if(!hdr_incomplete) + { + uint64_t clen = seclen - 24; + uint64_t uclen = fstReaderUint64(xc->f); + unsigned char *ucdata = malloc(uclen); + unsigned char *pnt = ucdata; + unsigned int i; - xc->contains_geom_section = 1; - xc->maxhandle = fstReaderUint64(xc->f); - xc->longest_signal_value_len = 32; /* arbitrarily set at 32...this is much longer than an expanded double */ + xc->contains_geom_section = 1; + xc->maxhandle = fstReaderUint64(xc->f); + 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); + free(xc->process_mask); + xc->process_mask = calloc(1, (xc->maxhandle+7)/8); - if(clen != uclen) - { - unsigned char *cdata = malloc(clen); - unsigned long destlen = uclen; - unsigned long sourcelen = clen; - int rc; + if(clen != uclen) + { + unsigned char *cdata = malloc(clen); + unsigned long destlen = uclen; + unsigned long sourcelen = clen; + int rc; - fstFread(cdata, clen, 1, xc->f); - rc = uncompress(ucdata, &destlen, cdata, sourcelen); + fstFread(cdata, clen, 1, xc->f); + rc = uncompress(ucdata, &destlen, cdata, sourcelen); - if(rc != Z_OK) - { - printf("geom uncompress rc = %d\n", rc); - exit(255); - } + if(rc != Z_OK) + { + printf("geom uncompress rc = %d\n", rc); + exit(255); + } - free(cdata); - } - else - { - fstFread(ucdata, uclen, 1, xc->f); - } + free(cdata); + } + else + { + fstFread(ucdata, uclen, 1, xc->f); + } - free(xc->signal_lens); - xc->signal_lens = malloc(sizeof(uint32_t) * xc->maxhandle); - free(xc->signal_typs); - xc->signal_typs = malloc(sizeof(unsigned char) * xc->maxhandle); + free(xc->signal_lens); + xc->signal_lens = malloc(sizeof(uint32_t) * xc->maxhandle); + free(xc->signal_typs); + xc->signal_typs = malloc(sizeof(unsigned char) * xc->maxhandle); - for(i=0;imaxhandle;i++) - { - int skiplen; - uint64_t val = fstGetVarint32(pnt, &skiplen); + for(i=0;imaxhandle;i++) + { + int skiplen; + uint64_t val = fstGetVarint32(pnt, &skiplen); - pnt += skiplen; + pnt += skiplen; - if(val) - { - xc->signal_lens[i] = (val != 0xFFFFFFFF) ? val : 0; - xc->signal_typs[i] = FST_VT_VCD_WIRE; - if(xc->signal_lens[i] > xc->longest_signal_value_len) - { - xc->longest_signal_value_len = xc->signal_lens[i]; - } - } - else - { - xc->signal_lens[i] = 8; /* backpatch in real */ - xc->signal_typs[i] = FST_VT_VCD_REAL; - /* xc->longest_signal_value_len handled above by overly large init size */ - } - } + if(val) + { + xc->signal_lens[i] = (val != 0xFFFFFFFF) ? val : 0; + xc->signal_typs[i] = FST_VT_VCD_WIRE; + if(xc->signal_lens[i] > xc->longest_signal_value_len) + { + xc->longest_signal_value_len = xc->signal_lens[i]; + } + } + else + { + xc->signal_lens[i] = 8; /* backpatch in real */ + xc->signal_typs[i] = FST_VT_VCD_REAL; + /* xc->longest_signal_value_len handled above by overly large init size */ + } + } - free(xc->temp_signal_value_buf); - xc->temp_signal_value_buf = malloc(xc->longest_signal_value_len + 1); + free(xc->temp_signal_value_buf); + xc->temp_signal_value_buf = malloc(xc->longest_signal_value_len + 1); - free(ucdata); - } - } - else if(sectype == FST_BL_HIER) - { - xc->contains_hier_section = 1; - xc->hier_pos = ftello(xc->f); - } - else if(sectype == FST_BL_HIER_LZ4DUO) - { - xc->contains_hier_section_lz4 = 1; - xc->contains_hier_section_lz4duo = 1; - xc->hier_pos = ftello(xc->f); - } - else if(sectype == FST_BL_HIER_LZ4) - { - xc->contains_hier_section_lz4 = 1; - xc->hier_pos = ftello(xc->f); - } - else if(sectype == FST_BL_BLACKOUT) - { - uint32_t i; - uint64_t cur_bl = 0; - uint64_t delta; + free(ucdata); + } + } + else if(sectype == FST_BL_HIER) + { + xc->contains_hier_section = 1; + xc->hier_pos = ftello(xc->f); + } + else if(sectype == FST_BL_HIER_LZ4DUO) + { + xc->contains_hier_section_lz4 = 1; + xc->contains_hier_section_lz4duo = 1; + xc->hier_pos = ftello(xc->f); + } + else if(sectype == FST_BL_HIER_LZ4) + { + xc->contains_hier_section_lz4 = 1; + xc->hier_pos = ftello(xc->f); + } + else if(sectype == FST_BL_BLACKOUT) + { + uint32_t i; + uint64_t cur_bl = 0; + uint64_t delta; - xc->num_blackouts = fstReaderVarint32(xc->f); - free(xc->blackout_times); - xc->blackout_times = calloc(xc->num_blackouts, sizeof(uint64_t)); - free(xc->blackout_activity); - xc->blackout_activity = calloc(xc->num_blackouts, sizeof(unsigned char)); + xc->num_blackouts = fstReaderVarint32(xc->f); + free(xc->blackout_times); + xc->blackout_times = calloc(xc->num_blackouts, sizeof(uint64_t)); + free(xc->blackout_activity); + xc->blackout_activity = calloc(xc->num_blackouts, sizeof(unsigned char)); - for(i=0;inum_blackouts;i++) - { - xc->blackout_activity[i] = fgetc(xc->f) != 0; - delta = fstReaderVarint64(xc->f); - cur_bl += delta; - xc->blackout_times[i] = cur_bl; - } - } + for(i=0;inum_blackouts;i++) + { + xc->blackout_activity[i] = fgetc(xc->f) != 0; + delta = fstReaderVarint64(xc->f); + cur_bl += delta; + xc->blackout_times[i] = cur_bl; + } + } - blkpos += seclen; - if(!hdr_seen) break; - } + blkpos += seclen; + if(!hdr_seen) break; + } - if(hdr_seen) - { - if(xc->vc_section_count != vc_section_count_actual) - { - xc->vc_section_count = vc_section_count_actual; - } + if(hdr_seen) + { + if(xc->vc_section_count != vc_section_count_actual) + { + xc->vc_section_count = vc_section_count_actual; + } - if(!xc->contains_geom_section) - { - fstReaderProcessHier(xc, NULL); /* recreate signal_lens/signal_typs info */ - } - } - } + if(!xc->contains_geom_section) + { + fstReaderProcessHier(xc, NULL); /* recreate signal_lens/signal_typs info */ + } + } + } return(hdr_seen); } @@ -4563,31 +4564,31 @@ if((!nam)||(!(xc->f=fopen(nam, "rb")))) { int flen = strlen(nam); char *hf = calloc(1, flen + 6); - int rc; + int rc; #if defined(__MINGW32__) || defined(FST_MACOSX) - setvbuf(xc->f, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */ + setvbuf(xc->f, (char *)NULL, _IONBF, 0); /* keeps gzip from acting weird in tandem with fopen */ #endif memcpy(hf, nam, flen); strcpy(hf + flen, ".hier"); xc->fh = fopen(hf, "rb"); - free(hf); - xc->filename = strdup(nam); - rc = fstReaderInit(xc); + free(hf); + xc->filename = strdup(nam); + rc = fstReaderInit(xc); - if((rc) && (xc->vc_section_count) && (xc->maxhandle) && ((xc->fh)||(xc->contains_hier_section||(xc->contains_hier_section_lz4)))) - { - /* more init */ - xc->do_rewind = 1; - } - else - { - fstReaderClose(xc); - xc = NULL; - } - } + if((rc) && (xc->vc_section_count) && (xc->maxhandle) && ((xc->fh)||(xc->contains_hier_section||(xc->contains_hier_section_lz4)))) + { + /* more init */ + xc->do_rewind = 1; + } + else + { + fstReaderClose(xc); + xc = NULL; + } + } return(xc); } @@ -4597,15 +4598,15 @@ static void fstReaderDeallocateRvatData(void *ctx) { struct fstReaderContext *xc = (struct fstReaderContext *)ctx; if(xc) - { - free(xc->rvat_chain_mem); xc->rvat_chain_mem = NULL; - free(xc->rvat_frame_data); xc->rvat_frame_data = NULL; - free(xc->rvat_time_table); xc->rvat_time_table = NULL; - free(xc->rvat_chain_table); xc->rvat_chain_table = NULL; - free(xc->rvat_chain_table_lengths); xc->rvat_chain_table_lengths = NULL; + { + free(xc->rvat_chain_mem); xc->rvat_chain_mem = NULL; + free(xc->rvat_frame_data); xc->rvat_frame_data = NULL; + free(xc->rvat_time_table); xc->rvat_time_table = NULL; + free(xc->rvat_chain_table); xc->rvat_chain_table = NULL; + free(xc->rvat_chain_table_lengths); xc->rvat_chain_table_lengths = NULL; - xc->rvat_data_valid = 0; - } + xc->rvat_data_valid = 0; + } } @@ -4614,36 +4615,36 @@ void fstReaderClose(void *ctx) struct fstReaderContext *xc = (struct fstReaderContext *)ctx; if(xc) - { - fstReaderDeallocateScopeData(xc); - fstReaderDeallocateRvatData(xc); - free(xc->rvat_sig_offs); xc->rvat_sig_offs = NULL; + { + fstReaderDeallocateScopeData(xc); + fstReaderDeallocateRvatData(xc); + free(xc->rvat_sig_offs); xc->rvat_sig_offs = NULL; - free(xc->process_mask); xc->process_mask = NULL; - free(xc->blackout_times); xc->blackout_times = NULL; - free(xc->blackout_activity); xc->blackout_activity = NULL; - free(xc->temp_signal_value_buf); xc->temp_signal_value_buf = NULL; - free(xc->signal_typs); xc->signal_typs = NULL; - free(xc->signal_lens); xc->signal_lens = NULL; - free(xc->filename); xc->filename = NULL; + free(xc->process_mask); xc->process_mask = NULL; + free(xc->blackout_times); xc->blackout_times = NULL; + free(xc->blackout_activity); xc->blackout_activity = NULL; + free(xc->temp_signal_value_buf); xc->temp_signal_value_buf = NULL; + free(xc->signal_typs); xc->signal_typs = NULL; + free(xc->signal_lens); xc->signal_lens = NULL; + free(xc->filename); xc->filename = NULL; - if(xc->fh) - { - tmpfile_close(&xc->fh, &xc->fh_nam); - } + if(xc->fh) + { + tmpfile_close(&xc->fh, &xc->fh_nam); + } - if(xc->f) - { - tmpfile_close(&xc->f, &xc->f_nam); - if(xc->filename_unpacked) - { - unlink(xc->filename_unpacked); - free(xc->filename_unpacked); - } - } + if(xc->f) + { + tmpfile_close(&xc->f, &xc->f_nam); + if(xc->filename_unpacked) + { + unlink(xc->filename_unpacked); + free(xc->filename_unpacked); + } + } - free(xc); - } + free(xc); + } } @@ -4662,7 +4663,7 @@ return(fstReaderIterBlocks2(ctx, value_change_callback, NULL, user_callback_data int fstReaderIterBlocks2(void *ctx, void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx, const unsigned char *value), - void (*value_change_callback_varlen)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx, const unsigned char *value, uint32_t len), + void (*value_change_callback_varlen)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx, const unsigned char *value, uint32_t len), void *user_callback_data_pointer, FILE *fv) { struct fstReaderContext *xc = (struct fstReaderContext *)ctx; @@ -4670,7 +4671,7 @@ struct fstReaderContext *xc = (struct fstReaderContext *)ctx; uint64_t previous_time = UINT64_MAX; uint64_t *time_table = NULL; uint64_t tsec_nitems; -int secnum = 0; +unsigned int secnum = 0; int blocks_skipped = 0; off_t blkpos = 0; uint64_t seclen, beg_tim; @@ -4706,914 +4707,914 @@ headptr = calloc(xc->maxhandle, sizeof(uint32_t)); length_remaining = calloc(xc->maxhandle, sizeof(uint32_t)); if(fv) - { - fprintf(fv, "$dumpvars\n"); + { + fprintf(fv, "$dumpvars\n"); #ifndef FST_WRITEX_DISABLE - fflush(fv); - setvbuf(fv, (char *) NULL, _IONBF, 0); /* even buffered IO is slow so disable it and use our own routines that don't need seeking */ - xc->writex_fd = fileno(fv); + fflush(fv); + setvbuf(fv, (char *) NULL, _IONBF, 0); /* even buffered IO is slow so disable it and use our own routines that don't need seeking */ + xc->writex_fd = fileno(fv); #endif - } + } for(;;) - { - uint32_t *tc_head = NULL; - traversal_mem_offs = 0; + { + uint32_t *tc_head = NULL; + traversal_mem_offs = 0; - fstReaderFseeko(xc, xc->f, blkpos, SEEK_SET); + fstReaderFseeko(xc, xc->f, blkpos, SEEK_SET); - sectype = fgetc(xc->f); - seclen = fstReaderUint64(xc->f); + sectype = fgetc(xc->f); + seclen = fstReaderUint64(xc->f); - if((sectype == EOF) || (sectype == FST_BL_SKIP)) - { + if((sectype == EOF) || (sectype == FST_BL_SKIP)) + { #ifdef FST_DEBUG - fprintf(stderr, "<< EOF >>\n"); + fprintf(stderr, "<< EOF >>\n"); #endif - break; - } + break; + } - blkpos++; - if((sectype != FST_BL_VCDATA) && (sectype != FST_BL_VCDATA_DYN_ALIAS) && (sectype != FST_BL_VCDATA_DYN_ALIAS2)) - { - blkpos += seclen; - continue; - } + blkpos++; + if((sectype != FST_BL_VCDATA) && (sectype != FST_BL_VCDATA_DYN_ALIAS) && (sectype != FST_BL_VCDATA_DYN_ALIAS2)) + { + blkpos += seclen; + continue; + } - if(!seclen) break; + if(!seclen) break; - beg_tim = fstReaderUint64(xc->f); + beg_tim = fstReaderUint64(xc->f); #ifdef FST_DEBUG - end_tim = + end_tim = #endif - fstReaderUint64(xc->f); + fstReaderUint64(xc->f); - if(xc->limit_range_valid) - { - if(beg_tim < xc->limit_range_start) - { - blocks_skipped++; - blkpos += seclen; - continue; - } + if(xc->limit_range_valid) + { + if(beg_tim < xc->limit_range_start) + { + blocks_skipped++; + blkpos += seclen; + continue; + } - if(beg_tim > xc->limit_range_end) /* likely the compare in for(i=0;i xc->limit_range_end) /* likely the compare in for(i=0;if); - mem_for_traversal = malloc(mem_required_for_traversal + 66); /* add in potential fastlz overhead */ + 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: %d 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, "sec: %d 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); #endif - /* process time block */ - { - unsigned char *ucdata; - unsigned char *cdata; - unsigned long destlen /* = tsec_uclen */; /* scan-build */ - unsigned long sourcelen /*= tsec_clen */; /* scan-build */ - int rc; - unsigned char *tpnt; - uint64_t tpval; - int ti; + /* process time block */ + { + unsigned char *ucdata; + unsigned char *cdata; + unsigned long destlen /* = tsec_uclen */; /* scan-build */ + unsigned long sourcelen /*= tsec_clen */; /* scan-build */ + int rc; + unsigned char *tpnt; + uint64_t tpval; + unsigned int ti; - if(fstReaderFseeko(xc, xc->f, blkpos + seclen - 24, SEEK_SET) != 0) break; - tsec_uclen = fstReaderUint64(xc->f); - tsec_clen = fstReaderUint64(xc->f); - tsec_nitems = fstReaderUint64(xc->f); + if(fstReaderFseeko(xc, xc->f, blkpos + seclen - 24, SEEK_SET) != 0) break; + 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", - (int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems); + fprintf(stderr, "\ttime 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 */ - ucdata = malloc(tsec_uclen); - if(!ucdata) break; /* malloc fail as tsec_uclen out of range from corrupted file */ - destlen = tsec_uclen; - sourcelen = tsec_clen; + if(tsec_clen > seclen) break; /* corrupted tsec_clen: by definition it can't be larger than size of section */ + ucdata = malloc(tsec_uclen); + if(!ucdata) break; /* malloc fail as tsec_uclen out of range from corrupted file */ + destlen = tsec_uclen; + sourcelen = tsec_clen; - fstReaderFseeko(xc, xc->f, -24 - ((off_t)tsec_clen), SEEK_CUR); + fstReaderFseeko(xc, xc->f, -24 - ((off_t)tsec_clen), SEEK_CUR); - if(tsec_uclen != tsec_clen) - { - cdata = malloc(tsec_clen); - fstFread(cdata, tsec_clen, 1, xc->f); + if(tsec_uclen != tsec_clen) + { + cdata = malloc(tsec_clen); + fstFread(cdata, tsec_clen, 1, xc->f); - rc = uncompress(ucdata, &destlen, cdata, sourcelen); + rc = uncompress(ucdata, &destlen, cdata, sourcelen); - if(rc != Z_OK) - { - printf("tsec uncompress rc = %d\n", rc); - exit(255); - } + if(rc != Z_OK) + { + printf("tsec uncompress rc = %d\n", rc); + exit(255); + } - free(cdata); - } - else - { - fstFread(ucdata, tsec_uclen, 1, xc->f); - } + free(cdata); + } + else + { + fstFread(ucdata, tsec_uclen, 1, xc->f); + } - free(time_table); - time_table = calloc(tsec_nitems, sizeof(uint64_t)); - tpnt = ucdata; - tpval = 0; - for(ti=0;tif, blkpos+32, SEEK_SET); + fstReaderFseeko(xc, xc->f, blkpos+32, SEEK_SET); - frame_uclen = fstReaderVarint64(xc->f); - frame_clen = fstReaderVarint64(xc->f); - frame_maxhandle = fstReaderVarint64(xc->f); + frame_uclen = fstReaderVarint64(xc->f); + frame_clen = fstReaderVarint64(xc->f); + frame_maxhandle = fstReaderVarint64(xc->f); - if(secnum == 0) - { - if((beg_tim != time_table[0]) || (blocks_skipped)) - { - unsigned char *mu = malloc(frame_uclen); - uint32_t sig_offs = 0; + if(secnum == 0) + { + if((beg_tim != time_table[0]) || (blocks_skipped)) + { + unsigned char *mu = malloc(frame_uclen); + uint32_t sig_offs = 0; - if(fv) - { - char wx_buf[32]; - int wx_len; + if(fv) + { + char wx_buf[32]; + int wx_len; - if(beg_tim) - { - wx_len = sprintf(wx_buf, "#%"PRIu64"\n", beg_tim); - fstWritex(xc, wx_buf, wx_len); - } - if((xc->num_blackouts)&&(cur_blackout != xc->num_blackouts)) - { - if(beg_tim == xc->blackout_times[cur_blackout]) - { - wx_len = sprintf(wx_buf, "$dump%s $end\n", (xc->blackout_activity[cur_blackout++]) ? "on" : "off"); - fstWritex(xc, wx_buf, wx_len); - } - } - } + if(beg_tim) + { + wx_len = sprintf(wx_buf, "#%"PRIu64"\n", beg_tim); + fstWritex(xc, wx_buf, wx_len); + } + if((xc->num_blackouts)&&(cur_blackout != xc->num_blackouts)) + { + if(beg_tim == xc->blackout_times[cur_blackout]) + { + wx_len = sprintf(wx_buf, "$dump%s $end\n", (xc->blackout_activity[cur_blackout++]) ? "on" : "off"); + fstWritex(xc, wx_buf, wx_len); + } + } + } - if(frame_uclen == frame_clen) - { - fstFread(mu, frame_uclen, 1, xc->f); - } - else - { - unsigned char *mc = malloc(frame_clen); - int rc; + if(frame_uclen == frame_clen) + { + fstFread(mu, frame_uclen, 1, xc->f); + } + else + { + unsigned char *mc = malloc(frame_clen); + int rc; - unsigned long destlen = frame_uclen; - unsigned long sourcelen = frame_clen; + unsigned long destlen = frame_uclen; + unsigned long sourcelen = frame_clen; - fstFread(mc, sourcelen, 1, xc->f); - rc = uncompress(mu, &destlen, mc, sourcelen); - if(rc != Z_OK) - { - printf("rc: %d\n", rc); - exit(255); - } - free(mc); - } + fstFread(mc, sourcelen, 1, xc->f); + rc = uncompress(mu, &destlen, mc, sourcelen); + if(rc != Z_OK) + { + printf("rc: %d\n", rc); + exit(255); + } + free(mc); + } - for(idx=0;idxprocess_mask[process_idx]&(1<signal_lens[idx] <= 1) - { - if(xc->signal_lens[idx] == 1) - { - unsigned char val = mu[sig_offs]; - if(value_change_callback) - { - xc->temp_signal_value_buf[0] = val; - xc->temp_signal_value_buf[1] = 0; - value_change_callback(user_callback_data_pointer, beg_tim, idx+1, xc->temp_signal_value_buf); - } - else - { - if(fv) - { - char vcd_id[16]; + if(xc->process_mask[process_idx]&(1<signal_lens[idx] <= 1) + { + if(xc->signal_lens[idx] == 1) + { + unsigned char val = mu[sig_offs]; + if(value_change_callback) + { + xc->temp_signal_value_buf[0] = val; + xc->temp_signal_value_buf[1] = 0; + value_change_callback(user_callback_data_pointer, beg_tim, idx+1, xc->temp_signal_value_buf); + } + else + { + if(fv) + { + char vcd_id[16]; - int vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); - vcd_id[0] = val; /* collapse 3 writes into one I/O call */ - vcd_id[vcdid_len + 1] = '\n'; - fstWritex(xc, vcd_id, vcdid_len + 2); - } - } - } - else - { - /* variable-length ("0" length) records have no initial state */ - } - } - else - { - if(xc->signal_typs[idx] != FST_VT_VCD_REAL) - { - if(value_change_callback) - { - memcpy(xc->temp_signal_value_buf, mu+sig_offs, xc->signal_lens[idx]); - xc->temp_signal_value_buf[xc->signal_lens[idx]] = 0; - value_change_callback(user_callback_data_pointer, beg_tim, idx+1, xc->temp_signal_value_buf); - } - else - { - if(fv) - { - char vcd_id[16]; - int vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); + int vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); + vcd_id[0] = val; /* collapse 3 writes into one I/O call */ + vcd_id[vcdid_len + 1] = '\n'; + fstWritex(xc, vcd_id, vcdid_len + 2); + } + } + } + else + { + /* variable-length ("0" length) records have no initial state */ + } + } + else + { + if(xc->signal_typs[idx] != FST_VT_VCD_REAL) + { + if(value_change_callback) + { + memcpy(xc->temp_signal_value_buf, mu+sig_offs, xc->signal_lens[idx]); + xc->temp_signal_value_buf[xc->signal_lens[idx]] = 0; + value_change_callback(user_callback_data_pointer, beg_tim, idx+1, xc->temp_signal_value_buf); + } + else + { + if(fv) + { + char vcd_id[16]; + int vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); - vcd_id[0] = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p'; - fstWritex(xc, vcd_id, 1); - fstWritex(xc,mu+sig_offs, xc->signal_lens[idx]); + vcd_id[0] = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p'; + fstWritex(xc, vcd_id, 1); + fstWritex(xc,mu+sig_offs, xc->signal_lens[idx]); - vcd_id[0] = ' '; /* collapse 3 writes into one I/O call */ - vcd_id[vcdid_len + 1] = '\n'; - fstWritex(xc, vcd_id, vcdid_len + 2); - } - } - } - else - { - double d; - unsigned char *clone_d; - unsigned char *srcdata = mu+sig_offs; + vcd_id[0] = ' '; /* collapse 3 writes into one I/O call */ + vcd_id[vcdid_len + 1] = '\n'; + fstWritex(xc, vcd_id, vcdid_len + 2); + } + } + } + else + { + double d; + unsigned char *clone_d; + unsigned char *srcdata = mu+sig_offs; - if(value_change_callback) - { - if(xc->native_doubles_for_cb) - { - if(xc->double_endian_match) - { - clone_d = srcdata; - } - else - { - int j; + if(value_change_callback) + { + if(xc->native_doubles_for_cb) + { + if(xc->double_endian_match) + { + clone_d = srcdata; + } + else + { + int j; - clone_d = (unsigned char *)&d; - for(j=0;j<8;j++) - { - clone_d[j] = srcdata[7-j]; - } - } - value_change_callback(user_callback_data_pointer, beg_tim, idx+1, clone_d); - } - else - { - clone_d = (unsigned char *)&d; - if(xc->double_endian_match) - { - memcpy(clone_d, srcdata, 8); - } - else - { - int j; + clone_d = (unsigned char *)&d; + for(j=0;j<8;j++) + { + clone_d[j] = srcdata[7-j]; + } + } + value_change_callback(user_callback_data_pointer, beg_tim, idx+1, clone_d); + } + else + { + clone_d = (unsigned char *)&d; + if(xc->double_endian_match) + { + memcpy(clone_d, srcdata, 8); + } + else + { + int j; - for(j=0;j<8;j++) - { - clone_d[j] = srcdata[7-j]; - } - } - sprintf((char *)xc->temp_signal_value_buf, "%.16g", d); - value_change_callback(user_callback_data_pointer, beg_tim, idx+1, xc->temp_signal_value_buf); - } - } - else - { - if(fv) - { - char vcdid_buf[16]; - char wx_buf[64]; - int wx_len; + for(j=0;j<8;j++) + { + clone_d[j] = srcdata[7-j]; + } + } + sprintf((char *)xc->temp_signal_value_buf, "%.16g", d); + value_change_callback(user_callback_data_pointer, beg_tim, idx+1, xc->temp_signal_value_buf); + } + } + else + { + if(fv) + { + char vcdid_buf[16]; + char wx_buf[64]; + int wx_len; - clone_d = (unsigned char *)&d; - if(xc->double_endian_match) - { - memcpy(clone_d, srcdata, 8); - } - else - { - int j; + clone_d = (unsigned char *)&d; + if(xc->double_endian_match) + { + memcpy(clone_d, srcdata, 8); + } + else + { + int j; - for(j=0;j<8;j++) - { - clone_d[j] = srcdata[7-j]; - } - } + for(j=0;j<8;j++) + { + clone_d[j] = srcdata[7-j]; + } + } - fstVcdID(vcdid_buf, idx+1); - wx_len = sprintf(wx_buf, "r%.16g %s\n", d, vcdid_buf); - fstWritex(xc, wx_buf, wx_len); - } - } - } - } - } + fstVcdID(vcdid_buf, idx+1); + wx_len = sprintf(wx_buf, "r%.16g %s\n", d, vcdid_buf); + fstWritex(xc, wx_buf, wx_len); + } + } + } + } + } - sig_offs += xc->signal_lens[idx]; - } + sig_offs += xc->signal_lens[idx]; + } - free(mu); - fstReaderFseeko(xc, xc->f, -((off_t)frame_clen), SEEK_CUR); - } - } + free(mu); + fstReaderFseeko(xc, xc->f, -((off_t)frame_clen), SEEK_CUR); + } + } - fstReaderFseeko(xc, xc->f, (off_t)frame_clen, SEEK_CUR); /* skip past compressed data */ + fstReaderFseeko(xc, xc->f, (off_t)frame_clen, SEEK_CUR); /* skip past compressed data */ - vc_maxhandle = fstReaderVarint64(xc->f); - vc_start = ftello(xc->f); /* points to '!' character */ - packtype = fgetc(xc->f); + vc_maxhandle = fstReaderVarint64(xc->f); + vc_start = ftello(xc->f); /* points to '!' character */ + packtype = fgetc(xc->f); #ifdef FST_DEBUG - fprintf(stderr, "\tframe_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, "\tframe_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); #endif - indx_pntr = blkpos + seclen - 24 -tsec_clen -8; - fstReaderFseeko(xc, xc->f, indx_pntr, SEEK_SET); - chain_clen = fstReaderUint64(xc->f); - indx_pos = indx_pntr - chain_clen; + indx_pntr = blkpos + seclen - 24 -tsec_clen -8; + 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, "\tindx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen); #endif - chain_cmem = 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); + chain_cmem = 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); - if(vc_maxhandle > vc_maxhandle_largest) - { - free(chain_table); - free(chain_table_lengths); + if(vc_maxhandle > vc_maxhandle_largest) + { + free(chain_table); + 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)); - } + vc_maxhandle_largest = vc_maxhandle; + chain_table = calloc((vc_maxhandle+1), sizeof(off_t)); + chain_table_lengths = calloc((vc_maxhandle+1), sizeof(uint32_t)); + } - if(!chain_table || !chain_table_lengths) goto block_err; + if(!chain_table || !chain_table_lengths) goto block_err; - pnt = chain_cmem; - idx = 0; - pval = 0; + pnt = chain_cmem; + idx = 0; + pval = 0; - if(sectype == FST_BL_VCDATA_DYN_ALIAS2) - { - uint32_t prev_alias = 0; + if(sectype == FST_BL_VCDATA_DYN_ALIAS2) + { + uint32_t prev_alias = 0; - do { - int skiplen; + do { + int skiplen; - if(*pnt & 0x01) - { - int64_t shval = fstGetSVarint64(pnt, &skiplen) >> 1; - if(shval > 0) - { - pval = chain_table[idx] = pval + shval; - if(idx) { chain_table_lengths[pidx] = pval - chain_table[pidx]; } - pidx = idx++; - } - else if(shval < 0) - { - chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */ - chain_table_lengths[idx] = prev_alias = shval; /* because during this loop iter would give stale data! */ - idx++; - } - else - { - chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */ - chain_table_lengths[idx] = prev_alias; /* because during this loop iter would give stale data! */ - idx++; - } - } - else - { - uint64_t val = fstGetVarint32(pnt, &skiplen); + if(*pnt & 0x01) + { + int64_t shval = fstGetSVarint64(pnt, &skiplen) >> 1; + if(shval > 0) + { + pval = chain_table[idx] = pval + shval; + if(idx) { chain_table_lengths[pidx] = pval - chain_table[pidx]; } + pidx = idx++; + } + else if(shval < 0) + { + chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */ + chain_table_lengths[idx] = prev_alias = shval; /* because during this loop iter would give stale data! */ + idx++; + } + else + { + chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */ + chain_table_lengths[idx] = prev_alias; /* because during this loop iter would give stale data! */ + idx++; + } + } + else + { + uint64_t val = fstGetVarint32(pnt, &skiplen); - int loopcnt = val >> 1; - for(i=0;i> 1; + for(i=0;i> 1); - if(idx) { chain_table_lengths[pidx] = pval - chain_table[pidx]; } - pidx = idx++; - } - else - { - int loopcnt = val >> 1; - for(i=0;i> 1); + if(idx) { chain_table_lengths[pidx] = pval - chain_table[pidx]; } + pidx = idx++; + } + else + { + fstHandle loopcnt = val >> 1; + for(i=0;i xc->maxhandle) idx = xc->maxhandle; - for(i=0;i xc->maxhandle) idx = xc->maxhandle; + for(i=0;iprocess_mask[process_idx]&(1<process_mask[process_idx]&(1<f, vc_start + chain_table[i], SEEK_SET); - val = fstReaderVarint32WithSkip(xc->f, &skiplen); - if(val) - { - unsigned char *mu = mem_for_traversal + traversal_mem_offs; /* uncomp: dst */ - unsigned char *mc; /* comp: src */ - unsigned long destlen = val; - unsigned long sourcelen = chain_table_lengths[i]; + fstReaderFseeko(xc, xc->f, vc_start + chain_table[i], SEEK_SET); + val = fstReaderVarint32WithSkip(xc->f, &skiplen); + if(val) + { + unsigned char *mu = mem_for_traversal + traversal_mem_offs; /* uncomp: dst */ + unsigned char *mc; /* comp: src */ + unsigned long destlen = val; + unsigned long sourcelen = chain_table_lengths[i]; - if(mc_mem_len < chain_table_lengths[i]) - { - free(mc_mem); - mc_mem = malloc(mc_mem_len = chain_table_lengths[i]); - } - mc = mc_mem; + if(mc_mem_len < chain_table_lengths[i]) + { + free(mc_mem); + mc_mem = malloc(mc_mem_len = chain_table_lengths[i]); + } + mc = mc_mem; - fstFread(mc, chain_table_lengths[i], 1, xc->f); + fstFread(mc, chain_table_lengths[i], 1, xc->f); - switch(packtype) - { - case '4': rc = (destlen == LZ4_decompress_safe_partial((char *)mc, (char *)mu, sourcelen, destlen, destlen)) ? Z_OK : Z_DATA_ERROR; - break; - case 'F': fastlz_decompress(mc, sourcelen, mu, destlen); /* rc appears unreliable */ - break; - default: rc = uncompress(mu, &destlen, mc, sourcelen); - break; - } + switch(packtype) + { + case '4': rc = (destlen == (unsigned long)LZ4_decompress_safe_partial((char *)mc, (char *)mu, sourcelen, destlen, destlen)) ? Z_OK : Z_DATA_ERROR; + break; + case 'F': fastlz_decompress(mc, sourcelen, mu, destlen); /* rc appears unreliable */ + break; + default: rc = uncompress(mu, &destlen, mc, sourcelen); + break; + } - /* data to process is for(j=0;jf); - /* data to process is for(j=0;jf); + /* data to process is for(j=0;jsignal_lens[i] == 1) - { - uint32_t vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[i]); - uint32_t shcnt = 2 << (vli & 1); - tdelta = vli >> shcnt; - } - else - { - uint32_t vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[i]); - tdelta = vli >> 1; - } + if(xc->signal_lens[i] == 1) + { + uint32_t vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[i]); + uint32_t shcnt = 2 << (vli & 1); + tdelta = vli >> shcnt; + } + else + { + uint32_t vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[i]); + tdelta = vli >> 1; + } - scatterptr[i] = tc_head[tdelta]; - tc_head[tdelta] = i+1; - } - } - } + scatterptr[i] = tc_head[tdelta]; + tc_head[tdelta] = i+1; + } + } + } - free(mc_mem); /* there is no usage below for this, no real need to clear out mc_mem or mc_mem_len */ + free(mc_mem); /* there is no usage below for this, no real need to clear out mc_mem or mc_mem_len */ - for(i=0;ilimit_range_valid) - { - if(time_table[i] > xc->limit_range_end) - { - break; - } - } + if(time_table[i] != previous_time) + { + if(xc->limit_range_valid) + { + if(time_table[i] > xc->limit_range_end) + { + break; + } + } - wx_len = sprintf(wx_buf, "#%"PRIu64"\n", time_table[i]); - fstWritex(xc, wx_buf, wx_len); + 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)) - { - if(time_table[i] == xc->blackout_times[cur_blackout]) - { - wx_len = sprintf(wx_buf, "$dump%s $end\n", (xc->blackout_activity[cur_blackout++]) ? "on" : "off"); - fstWritex(xc, wx_buf, wx_len); - } - } - previous_time = time_table[i]; - } - } + if((xc->num_blackouts)&&(cur_blackout != xc->num_blackouts)) + { + if(time_table[i] == xc->blackout_times[cur_blackout]) + { + wx_len = sprintf(wx_buf, "$dump%s $end\n", (xc->blackout_activity[cur_blackout++]) ? "on" : "off"); + fstWritex(xc, wx_buf, wx_len); + } + } + previous_time = time_table[i]; + } + } - while(tc_head[i]) - { - idx = tc_head[i] - 1; - vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen); + while(tc_head[i]) + { + idx = tc_head[i] - 1; + vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen); - if(xc->signal_lens[idx] <= 1) - { - if(xc->signal_lens[idx] == 1) - { - unsigned char val; - if(!(vli & 1)) - { - /* tdelta = vli >> 2; */ /* scan-build */ - val = ((vli >> 1) & 1) | '0'; - } - else - { - /* tdelta = vli >> 4; */ /* scan-build */ - val = FST_RCV_STR[((vli >> 1) & 7)]; - } + if(xc->signal_lens[idx] <= 1) + { + if(xc->signal_lens[idx] == 1) + { + unsigned char val; + if(!(vli & 1)) + { + /* tdelta = vli >> 2; */ /* scan-build */ + val = ((vli >> 1) & 1) | '0'; + } + else + { + /* tdelta = vli >> 4; */ /* scan-build */ + val = FST_RCV_STR[((vli >> 1) & 7)]; + } - if(value_change_callback) - { - xc->temp_signal_value_buf[0] = val; - xc->temp_signal_value_buf[1] = 0; - value_change_callback(user_callback_data_pointer, time_table[i], idx+1, xc->temp_signal_value_buf); - } - else - { - if(fv) - { - char vcd_id[16]; - int vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); + if(value_change_callback) + { + xc->temp_signal_value_buf[0] = val; + xc->temp_signal_value_buf[1] = 0; + value_change_callback(user_callback_data_pointer, time_table[i], idx+1, xc->temp_signal_value_buf); + } + else + { + if(fv) + { + char vcd_id[16]; + int vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); - vcd_id[0] = val; - vcd_id[vcdid_len+1] = '\n'; - fstWritex(xc, vcd_id, vcdid_len+2); - } - } - headptr[idx] += skiplen; - length_remaining[idx] -= skiplen; + vcd_id[0] = val; + vcd_id[vcdid_len+1] = '\n'; + fstWritex(xc, vcd_id, vcdid_len+2); + } + } + headptr[idx] += skiplen; + length_remaining[idx] -= skiplen; - tc_head[i] = scatterptr[idx]; - scatterptr[idx] = 0; + tc_head[i] = scatterptr[idx]; + scatterptr[idx] = 0; - if(length_remaining[idx]) - { - int shamt; - vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]); - shamt = 2 << (vli & 1); - tdelta = vli >> shamt; + if(length_remaining[idx]) + { + int shamt; + vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]); + shamt = 2 << (vli & 1); + tdelta = vli >> shamt; - scatterptr[idx] = tc_head[i+tdelta]; - tc_head[i+tdelta] = idx+1; - } - } - else - { - unsigned char *vdata; - uint32_t len; + scatterptr[idx] = tc_head[i+tdelta]; + tc_head[i+tdelta] = idx+1; + } + } + else + { + unsigned char *vdata; + uint32_t len; - vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen); - len = fstGetVarint32(mem_for_traversal + headptr[idx] + skiplen, &skiplen2); - /* tdelta = vli >> 1; */ /* scan-build */ - skiplen += skiplen2; - vdata = mem_for_traversal + headptr[idx] + skiplen; + vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen); + len = fstGetVarint32(mem_for_traversal + headptr[idx] + skiplen, &skiplen2); + /* tdelta = vli >> 1; */ /* scan-build */ + skiplen += skiplen2; + vdata = mem_for_traversal + headptr[idx] + skiplen; - if(!(vli & 1)) - { - if(value_change_callback_varlen) - { - value_change_callback_varlen(user_callback_data_pointer, time_table[i], idx+1, vdata, len); - } - else - { - if(fv) - { - char vcd_id[16]; - int vcdid_len; + if(!(vli & 1)) + { + if(value_change_callback_varlen) + { + value_change_callback_varlen(user_callback_data_pointer, time_table[i], idx+1, vdata, len); + } + else + { + if(fv) + { + char vcd_id[16]; + int vcdid_len; - vcd_id[0] = 's'; - fstWritex(xc, vcd_id, 1); + vcd_id[0] = 's'; + fstWritex(xc, vcd_id, 1); - vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); - { - unsigned char *vesc = malloc(len*4 + 1); - int vlen = fstUtilityBinToEsc(vesc, vdata, len); - fstWritex(xc, vesc, vlen); - free(vesc); - } + vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); + { + unsigned char *vesc = malloc(len*4 + 1); + int vlen = fstUtilityBinToEsc(vesc, vdata, len); + fstWritex(xc, vesc, vlen); + free(vesc); + } - vcd_id[0] = ' '; - vcd_id[vcdid_len + 1] = '\n'; - fstWritex(xc, vcd_id, vcdid_len+2); - } - } - } + vcd_id[0] = ' '; + vcd_id[vcdid_len + 1] = '\n'; + fstWritex(xc, vcd_id, vcdid_len+2); + } + } + } - skiplen += len; - headptr[idx] += skiplen; - length_remaining[idx] -= skiplen; + skiplen += len; + headptr[idx] += skiplen; + length_remaining[idx] -= skiplen; - tc_head[i] = scatterptr[idx]; - scatterptr[idx] = 0; + tc_head[i] = scatterptr[idx]; + scatterptr[idx] = 0; - if(length_remaining[idx]) - { - vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]); - tdelta = vli >> 1; + if(length_remaining[idx]) + { + vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]); + tdelta = vli >> 1; - scatterptr[idx] = tc_head[i+tdelta]; - tc_head[i+tdelta] = idx+1; - } - } - } - else - { - uint32_t len = xc->signal_lens[idx]; - unsigned char *vdata; + scatterptr[idx] = tc_head[i+tdelta]; + tc_head[i+tdelta] = idx+1; + } + } + } + else + { + uint32_t len = xc->signal_lens[idx]; + unsigned char *vdata; - vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen); - /* tdelta = vli >> 1; */ /* scan-build */ - vdata = mem_for_traversal + headptr[idx] + skiplen; + vli = fstGetVarint32(mem_for_traversal + headptr[idx], &skiplen); + /* tdelta = vli >> 1; */ /* scan-build */ + vdata = mem_for_traversal + headptr[idx] + skiplen; - if(xc->signal_typs[idx] != FST_VT_VCD_REAL) - { - if(!(vli & 1)) - { - int byte = 0; - int bit; - int j; + if(xc->signal_typs[idx] != FST_VT_VCD_REAL) + { + if(!(vli & 1)) + { + int byte = 0; + int bit; + unsigned int j; - for(j=0;j> bit) & 1) | '0'; - xc->temp_signal_value_buf[j] = ch; - } - xc->temp_signal_value_buf[j] = 0; + for(j=0;j> bit) & 1) | '0'; + xc->temp_signal_value_buf[j] = ch; + } + xc->temp_signal_value_buf[j] = 0; - if(value_change_callback) - { - value_change_callback(user_callback_data_pointer, time_table[i], idx+1, xc->temp_signal_value_buf); - } - else - { - if(fv) { - unsigned char ch_bp = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p'; + if(value_change_callback) + { + value_change_callback(user_callback_data_pointer, time_table[i], idx+1, xc->temp_signal_value_buf); + } + else + { + if(fv) { + unsigned char ch_bp = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p'; - fstWritex(xc, &ch_bp, 1); - fstWritex(xc, xc->temp_signal_value_buf, len); - } - } + fstWritex(xc, &ch_bp, 1); + fstWritex(xc, xc->temp_signal_value_buf, len); + } + } - len = byte+1; - } - else - { - if(value_change_callback) - { - memcpy(xc->temp_signal_value_buf, vdata, len); - xc->temp_signal_value_buf[len] = 0; - value_change_callback(user_callback_data_pointer, time_table[i], idx+1, xc->temp_signal_value_buf); - } - else - { - if(fv) - { - unsigned char ch_bp = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p'; + len = byte+1; + } + else + { + if(value_change_callback) + { + memcpy(xc->temp_signal_value_buf, vdata, len); + xc->temp_signal_value_buf[len] = 0; + value_change_callback(user_callback_data_pointer, time_table[i], idx+1, xc->temp_signal_value_buf); + } + else + { + if(fv) + { + unsigned char ch_bp = (xc->signal_typs[idx] != FST_VT_VCD_PORT) ? 'b' : 'p'; - fstWritex(xc, &ch_bp, 1); - fstWritex(xc, vdata, len); - } - } - } - } - else - { - double d; - unsigned char *clone_d /*= (unsigned char *)&d */; /* scan-build */ - unsigned char buf[8]; - unsigned char *srcdata; + fstWritex(xc, &ch_bp, 1); + fstWritex(xc, vdata, len); + } + } + } + } + else + { + double d; + unsigned char *clone_d /*= (unsigned char *)&d */; /* scan-build */ + unsigned char buf[8]; + unsigned char *srcdata; - if(!(vli & 1)) /* very rare case, but possible */ - { - int bit; - int j; + if(!(vli & 1)) /* very rare case, but possible */ + { + int bit; + int j; - for(j=0;j<8;j++) - { - unsigned char ch; - bit = 7 - (j & 7); - ch = ((vdata[0] >> bit) & 1) | '0'; - buf[j] = ch; - } + for(j=0;j<8;j++) + { + unsigned char ch; + bit = 7 - (j & 7); + ch = ((vdata[0] >> bit) & 1) | '0'; + buf[j] = ch; + } - len = 1; - srcdata = buf; - } - else - { - srcdata = vdata; - } + len = 1; + srcdata = buf; + } + else + { + srcdata = vdata; + } - if(value_change_callback) - { - if(xc->native_doubles_for_cb) - { - if(xc->double_endian_match) - { - clone_d = srcdata; - } - else - { - int j; + if(value_change_callback) + { + if(xc->native_doubles_for_cb) + { + if(xc->double_endian_match) + { + clone_d = srcdata; + } + else + { + int j; - clone_d = (unsigned char *)&d; - for(j=0;j<8;j++) - { - clone_d[j] = srcdata[7-j]; - } - } - value_change_callback(user_callback_data_pointer, time_table[i], idx+1, clone_d); - } - else - { - clone_d = (unsigned char *)&d; - if(xc->double_endian_match) - { - memcpy(clone_d, srcdata, 8); - } - else - { - int j; + clone_d = (unsigned char *)&d; + for(j=0;j<8;j++) + { + clone_d[j] = srcdata[7-j]; + } + } + value_change_callback(user_callback_data_pointer, time_table[i], idx+1, clone_d); + } + else + { + clone_d = (unsigned char *)&d; + if(xc->double_endian_match) + { + memcpy(clone_d, srcdata, 8); + } + else + { + int j; - for(j=0;j<8;j++) - { - clone_d[j] = srcdata[7-j]; - } - } - sprintf((char *)xc->temp_signal_value_buf, "%.16g", d); - value_change_callback(user_callback_data_pointer, time_table[i], idx+1, xc->temp_signal_value_buf); - } - } - else - { - if(fv) - { - char wx_buf[32]; - int wx_len; + for(j=0;j<8;j++) + { + clone_d[j] = srcdata[7-j]; + } + } + sprintf((char *)xc->temp_signal_value_buf, "%.16g", d); + value_change_callback(user_callback_data_pointer, time_table[i], idx+1, xc->temp_signal_value_buf); + } + } + else + { + if(fv) + { + char wx_buf[32]; + int wx_len; - clone_d = (unsigned char *)&d; - if(xc->double_endian_match) - { - memcpy(clone_d, srcdata, 8); - } - else - { - int j; + clone_d = (unsigned char *)&d; + if(xc->double_endian_match) + { + memcpy(clone_d, srcdata, 8); + } + else + { + int j; - for(j=0;j<8;j++) - { - clone_d[j] = srcdata[7-j]; - } - } + for(j=0;j<8;j++) + { + clone_d[j] = srcdata[7-j]; + } + } - wx_len = sprintf(wx_buf, "r%.16g", d); - fstWritex(xc, wx_buf, wx_len); - } - } - } + wx_len = sprintf(wx_buf, "r%.16g", d); + fstWritex(xc, wx_buf, wx_len); + } + } + } - if(fv) - { - char vcd_id[16]; - int vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); - vcd_id[0] = ' '; - vcd_id[vcdid_len+1] = '\n'; - fstWritex(xc, vcd_id, vcdid_len+2); - } + if(fv) + { + char vcd_id[16]; + int vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); + vcd_id[0] = ' '; + vcd_id[vcdid_len+1] = '\n'; + fstWritex(xc, vcd_id, vcdid_len+2); + } - skiplen += len; - headptr[idx] += skiplen; - length_remaining[idx] -= skiplen; + skiplen += len; + headptr[idx] += skiplen; + length_remaining[idx] -= skiplen; - tc_head[i] = scatterptr[idx]; - scatterptr[idx] = 0; + tc_head[i] = scatterptr[idx]; + scatterptr[idx] = 0; - if(length_remaining[idx]) - { - vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]); - tdelta = vli >> 1; + if(length_remaining[idx]) + { + vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]); + tdelta = vli >> 1; - scatterptr[idx] = tc_head[i+tdelta]; - tc_head[i+tdelta] = idx+1; - } - } - } - } + scatterptr[idx] = tc_head[i+tdelta]; + tc_head[i+tdelta] = idx+1; + } + } + } + } block_err: - free(tc_head); - free(chain_cmem); - free(mem_for_traversal); mem_for_traversal = NULL; + free(tc_head); + free(chain_cmem); + free(mem_for_traversal); mem_for_traversal = NULL; - secnum++; - if(secnum == xc->vc_section_count) break; /* in case file is growing, keep with original block count */ - blkpos += seclen; - } + secnum++; + if(secnum == xc->vc_section_count) break; /* in case file is growing, keep with original block count */ + blkpos += seclen; + } if(mem_for_traversal) free(mem_for_traversal); /* scan-build */ free(length_remaining); @@ -5621,15 +5622,15 @@ free(headptr); free(scatterptr); if(chain_table) free(chain_table); -if(chain_table_lengths) free(chain_table_lengths); +if(chain_table_lengths) free(chain_table_lengths); free(time_table); #ifndef FST_WRITEX_DISABLE if(fv) - { - fstWritex(xc, NULL, 0); - } + { + fstWritex(xc, NULL, 0); + } #endif return(1); @@ -5641,45 +5642,45 @@ return(1); static char *fstExtractRvatDataFromFrame(struct fstReaderContext *xc, fstHandle facidx, char *buf) { if(facidx >= xc->rvat_frame_maxhandle) - { - return(NULL); - } + { + return(NULL); + } if(xc->signal_lens[facidx] == 1) - { - buf[0] = (char)xc->rvat_frame_data[xc->rvat_sig_offs[facidx]]; - buf[1] = 0; - } - else - { - if(xc->signal_typs[facidx] != FST_VT_VCD_REAL) - { - memcpy(buf, xc->rvat_frame_data + xc->rvat_sig_offs[facidx], xc->signal_lens[facidx]); - buf[xc->signal_lens[facidx]] = 0; - } - else - { - double d; - unsigned char *clone_d = (unsigned char *)&d; - unsigned char *srcdata = xc->rvat_frame_data + xc->rvat_sig_offs[facidx]; + { + buf[0] = (char)xc->rvat_frame_data[xc->rvat_sig_offs[facidx]]; + buf[1] = 0; + } + else + { + if(xc->signal_typs[facidx] != FST_VT_VCD_REAL) + { + memcpy(buf, xc->rvat_frame_data + xc->rvat_sig_offs[facidx], xc->signal_lens[facidx]); + buf[xc->signal_lens[facidx]] = 0; + } + else + { + double d; + unsigned char *clone_d = (unsigned char *)&d; + unsigned char *srcdata = xc->rvat_frame_data + xc->rvat_sig_offs[facidx]; - if(xc->double_endian_match) - { - memcpy(clone_d, srcdata, 8); - } - else - { - int j; + if(xc->double_endian_match) + { + memcpy(clone_d, srcdata, 8); + } + else + { + int j; - for(j=0;j<8;j++) - { - clone_d[j] = srcdata[7-j]; - } - } + for(j=0;j<8;j++) + { + clone_d[j] = srcdata[7-j]; + } + } - sprintf((char *)buf, "%.16g", d); - } - } + sprintf((char *)buf, "%.16g", d); + } + } return(buf); } @@ -5691,7 +5692,7 @@ struct fstReaderContext *xc = (struct fstReaderContext *)ctx; off_t blkpos = 0, prev_blkpos; uint64_t beg_tim, end_tim, beg_tim2, end_tim2; int sectype; -int secnum = 0; +unsigned int secnum = 0; uint64_t seclen; uint64_t tsec_uclen = 0, tsec_clen = 0; uint64_t tsec_nitems; @@ -5707,84 +5708,84 @@ fstHandle idx, pidx=0, i; uint64_t pval; if((!xc) || (!facidx) || (facidx > xc->maxhandle) || (!buf) || (!xc->signal_lens[facidx-1])) - { - return(NULL); - } + { + return(NULL); + } if(!xc->rvat_sig_offs) - { - uint32_t cur_offs = 0; + { + uint32_t cur_offs = 0; - xc->rvat_sig_offs = calloc(xc->maxhandle, sizeof(uint32_t)); - for(i=0;imaxhandle;i++) - { - xc->rvat_sig_offs[i] = cur_offs; - cur_offs += xc->signal_lens[i]; - } - } + xc->rvat_sig_offs = calloc(xc->maxhandle, sizeof(uint32_t)); + for(i=0;imaxhandle;i++) + { + xc->rvat_sig_offs[i] = cur_offs; + cur_offs += xc->signal_lens[i]; + } + } if(xc->rvat_data_valid) - { - if((xc->rvat_beg_tim <= tim) && (tim <= xc->rvat_end_tim)) - { - goto process_value; - } + { + if((xc->rvat_beg_tim <= tim) && (tim <= xc->rvat_end_tim)) + { + goto process_value; + } - fstReaderDeallocateRvatData(xc); - } + fstReaderDeallocateRvatData(xc); + } xc->rvat_chain_pos_valid = 0; for(;;) - { - fstReaderFseeko(xc, xc->f, (prev_blkpos = blkpos), SEEK_SET); + { + fstReaderFseeko(xc, xc->f, (prev_blkpos = blkpos), SEEK_SET); - sectype = fgetc(xc->f); - seclen = fstReaderUint64(xc->f); + sectype = fgetc(xc->f); + seclen = fstReaderUint64(xc->f); - if((sectype == EOF) || (sectype == FST_BL_SKIP) || (!seclen)) - { - return(NULL); /* if this loop exits on break, it's successful */ - } + if((sectype == EOF) || (sectype == FST_BL_SKIP) || (!seclen)) + { + return(NULL); /* if this loop exits on break, it's successful */ + } - blkpos++; - if((sectype != FST_BL_VCDATA) && (sectype != FST_BL_VCDATA_DYN_ALIAS) && (sectype != FST_BL_VCDATA_DYN_ALIAS2)) - { - blkpos += seclen; - continue; - } + blkpos++; + if((sectype != FST_BL_VCDATA) && (sectype != FST_BL_VCDATA_DYN_ALIAS) && (sectype != FST_BL_VCDATA_DYN_ALIAS2)) + { + blkpos += seclen; + continue; + } - beg_tim = fstReaderUint64(xc->f); - end_tim = fstReaderUint64(xc->f); + beg_tim = fstReaderUint64(xc->f); + end_tim = fstReaderUint64(xc->f); - if((beg_tim <= tim) && (tim <= end_tim)) - { - if((tim == end_tim) && (tim != xc->end_time)) - { - off_t cached_pos = ftello(xc->f); - fstReaderFseeko(xc, xc->f, blkpos, SEEK_SET); + if((beg_tim <= tim) && (tim <= end_tim)) + { + if((tim == end_tim) && (tim != xc->end_time)) + { + off_t cached_pos = ftello(xc->f); + fstReaderFseeko(xc, xc->f, blkpos, SEEK_SET); - sectype = fgetc(xc->f); - seclen = fstReaderUint64(xc->f); + sectype = fgetc(xc->f); + seclen = fstReaderUint64(xc->f); - beg_tim2 = fstReaderUint64(xc->f); - end_tim2 = fstReaderUint64(xc->f); + beg_tim2 = fstReaderUint64(xc->f); + end_tim2 = fstReaderUint64(xc->f); - if(((sectype != FST_BL_VCDATA)&&(sectype != FST_BL_VCDATA_DYN_ALIAS)&&(sectype != FST_BL_VCDATA_DYN_ALIAS2)) || (!seclen) || (beg_tim2 != tim)) - { - blkpos = prev_blkpos; - break; - } - beg_tim = beg_tim2; - end_tim = end_tim2; - fstReaderFseeko(xc, xc->f, cached_pos, SEEK_SET); - } - break; - } + if(((sectype != FST_BL_VCDATA)&&(sectype != FST_BL_VCDATA_DYN_ALIAS)&&(sectype != FST_BL_VCDATA_DYN_ALIAS2)) || (!seclen) || (beg_tim2 != tim)) + { + blkpos = prev_blkpos; + break; + } + beg_tim = beg_tim2; + end_tim = end_tim2; + fstReaderFseeko(xc, xc->f, cached_pos, SEEK_SET); + } + break; + } - blkpos += seclen; - secnum++; - } + blkpos += seclen; + secnum++; + } xc->rvat_beg_tim = beg_tim; xc->rvat_end_tim = end_tim; @@ -5792,11 +5793,11 @@ xc->rvat_end_tim = end_tim; #ifdef FST_DEBUG mem_required_for_traversal = #endif - fstReaderUint64(xc->f); + fstReaderUint64(xc->f); #ifdef FST_DEBUG fprintf(stderr, "rvat sec: %d seclen: %d begtim: %d endtim: %d\n", - secnum, (int)seclen, (int)beg_tim, (int)end_tim); + secnum, (int)seclen, (int)beg_tim, (int)end_tim); fprintf(stderr, "\tmem_required_for_traversal: %d\n", (int)mem_required_for_traversal); #endif @@ -5809,7 +5810,7 @@ unsigned long sourcelen /* = tsec_clen */; /* scan-build */ int rc; unsigned char *tpnt; uint64_t tpval; -int ti; +unsigned int ti; fstReaderFseeko(xc, xc->f, blkpos + seclen - 24, SEEK_SET); tsec_uclen = fstReaderUint64(xc->f); @@ -5817,7 +5818,7 @@ tsec_clen = fstReaderUint64(xc->f); tsec_nitems = fstReaderUint64(xc->f); #ifdef FST_DEBUG fprintf(stderr, "\ttime section unc: %d, com: %d (%d items)\n", - (int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems); + (int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems); #endif ucdata = malloc(tsec_uclen); destlen = tsec_uclen; @@ -5825,35 +5826,35 @@ sourcelen = tsec_clen; fstReaderFseeko(xc, xc->f, -24 - ((off_t)tsec_clen), SEEK_CUR); if(tsec_uclen != tsec_clen) - { - cdata = malloc(tsec_clen); - fstFread(cdata, tsec_clen, 1, xc->f); + { + cdata = malloc(tsec_clen); + fstFread(cdata, tsec_clen, 1, xc->f); - rc = uncompress(ucdata, &destlen, cdata, sourcelen); + rc = uncompress(ucdata, &destlen, cdata, sourcelen); - if(rc != Z_OK) - { - printf("tsec uncompress rc = %d\n", rc); - exit(255); - } + if(rc != Z_OK) + { + printf("tsec uncompress rc = %d\n", rc); + exit(255); + } - free(cdata); - } - else - { - fstFread(ucdata, tsec_uclen, 1, xc->f); - } + free(cdata); + } + else + { + fstFread(ucdata, tsec_uclen, 1, xc->f); + } xc->rvat_time_table = calloc(tsec_nitems, sizeof(uint64_t)); tpnt = ucdata; tpval = 0; for(ti=0;tirvat_time_table[ti] = tpval + val; - tpnt += skiplen; - } + { + int skiplen; + uint64_t val = fstGetVarint64(tpnt, &skiplen); + tpval = xc->rvat_time_table[ti] = tpval + val; + tpnt += skiplen; + } free(ucdata); } @@ -5866,33 +5867,33 @@ xc->rvat_frame_maxhandle = fstReaderVarint64(xc->f); xc->rvat_frame_data = malloc(frame_uclen); if(frame_uclen == frame_clen) - { - fstFread(xc->rvat_frame_data, frame_uclen, 1, xc->f); - } - else - { - unsigned char *mc = malloc(frame_clen); - int rc; + { + fstFread(xc->rvat_frame_data, frame_uclen, 1, xc->f); + } + else + { + unsigned char *mc = malloc(frame_clen); + int rc; - unsigned long destlen = frame_uclen; - unsigned long sourcelen = frame_clen; + unsigned long destlen = frame_uclen; + unsigned long sourcelen = frame_clen; - fstFread(mc, sourcelen, 1, xc->f); - rc = uncompress(xc->rvat_frame_data, &destlen, mc, sourcelen); - if(rc != Z_OK) - { - printf("decompress rc: %d\n", rc); - exit(255); - } - free(mc); - } + fstFread(mc, sourcelen, 1, xc->f); + rc = uncompress(xc->rvat_frame_data, &destlen, mc, sourcelen); + if(rc != Z_OK) + { + printf("decompress rc: %d\n", rc); + exit(255); + } + free(mc); + } xc->rvat_vc_maxhandle = fstReaderVarint64(xc->f); -xc->rvat_vc_start = ftello(xc->f); /* points to '!' character */ +xc->rvat_vc_start = ftello(xc->f); /* points to '!' character */ #ifdef FST_DEBUG fprintf(stderr, "\tframe_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", - (int)frame_uclen, (int)frame_clen, (int)xc->rvat_frame_maxhandle); + (int)frame_uclen, (int)frame_clen, (int)xc->rvat_frame_maxhandle); fprintf(stderr, "\tvc_maxhandle: %d\n", (int)xc->rvat_vc_maxhandle); #endif @@ -5914,55 +5915,55 @@ pnt = chain_cmem; idx = 0; pval = 0; do - { - int skiplen; - uint64_t val = fstGetVarint32(pnt, &skiplen); + { + int skiplen; + uint64_t val = fstGetVarint32(pnt, &skiplen); if(!val) - { - pnt += skiplen; - val = fstGetVarint32(pnt, &skiplen); - xc->rvat_chain_table[idx] = 0; + { + pnt += skiplen; + val = fstGetVarint32(pnt, &skiplen); + xc->rvat_chain_table[idx] = 0; xc->rvat_chain_table_lengths[idx] = -val; idx++; } - else - if(val&1) - { - pval = xc->rvat_chain_table[idx] = pval + (val >> 1); - if(idx) { xc->rvat_chain_table_lengths[pidx] = pval - xc->rvat_chain_table[pidx]; } - pidx = idx++; - } - else - { - int loopcnt = val >> 1; - for(i=0;irvat_chain_table[idx++] = 0; - } - } + else + if(val&1) + { + pval = xc->rvat_chain_table[idx] = pval + (val >> 1); + if(idx) { xc->rvat_chain_table_lengths[pidx] = pval - xc->rvat_chain_table[pidx]; } + pidx = idx++; + } + else + { + fstHandle loopcnt = val >> 1; + for(i=0;irvat_chain_table[idx++] = 0; + } + } - pnt += skiplen; - } while (pnt != (chain_cmem + chain_clen)); + pnt += skiplen; + } while (pnt != (chain_cmem + chain_clen)); free(chain_cmem); xc->rvat_chain_table[idx] = indx_pos - xc->rvat_vc_start; xc->rvat_chain_table_lengths[pidx] = xc->rvat_chain_table[idx] - xc->rvat_chain_table[pidx]; for(i=0;irvat_chain_table_lengths[i]; - if((v32 < 0) && (!xc->rvat_chain_table[i])) - { + if((v32 < 0) && (!xc->rvat_chain_table[i])) + { v32 = -v32; - v32--; - if(((uint32_t)v32) < i) /* sanity check */ - { - xc->rvat_chain_table[i] = xc->rvat_chain_table[v32]; - xc->rvat_chain_table_lengths[i] = xc->rvat_chain_table_lengths[v32]; - } + v32--; + if(((uint32_t)v32) < i) /* sanity check */ + { + xc->rvat_chain_table[i] = xc->rvat_chain_table[v32]; + xc->rvat_chain_table_lengths[i] = xc->rvat_chain_table_lengths[v32]; + } } - } + } #ifdef FST_DEBUG fprintf(stderr, "\tdecompressed chain idx len: %"PRIu32"\n", idx); @@ -5973,66 +5974,66 @@ xc->rvat_data_valid = 1; /* all data at this point is loaded or resident in fst cache, process and return appropriate value */ process_value: if(facidx > xc->rvat_vc_maxhandle) - { - return(NULL); - } + { + return(NULL); + } facidx--; /* scale down for array which starts at zero */ if(((tim == xc->rvat_beg_tim)&&(!xc->rvat_chain_table[facidx])) || (!xc->rvat_chain_table[facidx])) - { - return(fstExtractRvatDataFromFrame(xc, facidx, buf)); - } + { + return(fstExtractRvatDataFromFrame(xc, facidx, buf)); + } if(facidx != xc->rvat_chain_facidx) - { - if(xc->rvat_chain_mem) - { - free(xc->rvat_chain_mem); - xc->rvat_chain_mem = NULL; + { + if(xc->rvat_chain_mem) + { + free(xc->rvat_chain_mem); + xc->rvat_chain_mem = NULL; - xc->rvat_chain_pos_valid = 0; - } - } + xc->rvat_chain_pos_valid = 0; + } + } if(!xc->rvat_chain_mem) - { - uint32_t skiplen; - fstReaderFseeko(xc, xc->f, xc->rvat_vc_start + xc->rvat_chain_table[facidx], SEEK_SET); - 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 long destlen = xc->rvat_chain_len; - unsigned long sourcelen = xc->rvat_chain_table_lengths[facidx]; - int rc; + { + uint32_t skiplen; + fstReaderFseeko(xc, xc->f, xc->rvat_vc_start + xc->rvat_chain_table[facidx], SEEK_SET); + 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 long destlen = xc->rvat_chain_len; + unsigned long sourcelen = xc->rvat_chain_table_lengths[facidx]; + int rc; - fstFread(mc, xc->rvat_chain_table_lengths[facidx], 1, xc->f); - rc = uncompress(mu, &destlen, mc, sourcelen); - free(mc); + fstFread(mc, xc->rvat_chain_table_lengths[facidx], 1, xc->f); + rc = uncompress(mu, &destlen, mc, sourcelen); + free(mc); - if(rc != Z_OK) - { - printf("\tclen: %d (rc=%d)\n", (int)xc->rvat_chain_len, rc); - exit(255); - } + if(rc != Z_OK) + { + printf("\tclen: %d (rc=%d)\n", (int)xc->rvat_chain_len, rc); + exit(255); + } - /* data to process is for(j=0;jrvat_chain_mem = mu; - } - else - { - int destlen = xc->rvat_chain_table_lengths[facidx] - skiplen; - unsigned char *mu = malloc(xc->rvat_chain_len = destlen); - fstFread(mu, destlen, 1, xc->f); - /* data to process is for(j=0;jrvat_chain_mem = mu; - } + /* data to process is for(j=0;jrvat_chain_mem = mu; + } + else + { + int destlen = xc->rvat_chain_table_lengths[facidx] - skiplen; + unsigned char *mu = malloc(xc->rvat_chain_len = destlen); + fstFread(mu, destlen, 1, xc->f); + /* data to process is for(j=0;jrvat_chain_mem = mu; + } - xc->rvat_chain_facidx = facidx; - } + xc->rvat_chain_facidx = facidx; + } /* process value chain here */ @@ -6040,185 +6041,185 @@ if(!xc->rvat_chain_mem) uint32_t tidx = 0, ptidx = 0; uint32_t tdelta; int skiplen; -int iprev = xc->rvat_chain_len; +unsigned int iprev = xc->rvat_chain_len; uint32_t pvli = 0; int pskip = 0; if((xc->rvat_chain_pos_valid)&&(tim >= xc->rvat_chain_pos_time)) - { - i = xc->rvat_chain_pos_idx; - tidx = xc->rvat_chain_pos_tidx; - } - else - { - i = 0; - tidx = 0; - xc->rvat_chain_pos_time = xc->rvat_beg_tim; - } - -if(xc->signal_lens[facidx] == 1) - { - while(irvat_chain_len) - { - uint32_t vli = fstGetVarint32(xc->rvat_chain_mem + i, &skiplen); - uint32_t shcnt = 2 << (vli & 1); - tdelta = vli >> shcnt; - - if(xc->rvat_time_table[tidx + tdelta] <= tim) - { - iprev = i; - pvli = vli; - ptidx = tidx; - /* pskip = skiplen; */ /* scan-build */ - - tidx += tdelta; - i+=skiplen; - } - else - { - break; - } - } - if(iprev != xc->rvat_chain_len) - { - xc->rvat_chain_pos_tidx = ptidx; - xc->rvat_chain_pos_idx = iprev; - xc->rvat_chain_pos_time = tim; - xc->rvat_chain_pos_valid = 1; - - if(!(pvli & 1)) - { - buf[0] = ((pvli >> 1) & 1) | '0'; - } - else - { - buf[0] = FST_RCV_STR[((pvli >> 1) & 7)]; - } - buf[1] = 0; - return(buf); - } - else - { - return(fstExtractRvatDataFromFrame(xc, facidx, buf)); - } + { + i = xc->rvat_chain_pos_idx; + tidx = xc->rvat_chain_pos_tidx; } else { - while(irvat_chain_len) - { - uint32_t vli = fstGetVarint32(xc->rvat_chain_mem + i, &skiplen); - tdelta = vli >> 1; + i = 0; + tidx = 0; + xc->rvat_chain_pos_time = xc->rvat_beg_tim; + } - if(xc->rvat_time_table[tidx + tdelta] <= tim) - { - iprev = i; - pvli = vli; - ptidx = tidx; - pskip = skiplen; +if(xc->signal_lens[facidx] == 1) + { + while(irvat_chain_len) + { + uint32_t vli = fstGetVarint32(xc->rvat_chain_mem + i, &skiplen); + uint32_t shcnt = 2 << (vli & 1); + tdelta = vli >> shcnt; - tidx += tdelta; - i+=skiplen; + if(xc->rvat_time_table[tidx + tdelta] <= tim) + { + iprev = i; + pvli = vli; + ptidx = tidx; + /* pskip = skiplen; */ /* scan-build */ - if(!(pvli & 1)) - { - i+=((xc->signal_lens[facidx]+7)/8); - } - else - { - i+=xc->signal_lens[facidx]; - } - } - else - { - break; - } - } + tidx += tdelta; + i+=skiplen; + } + else + { + break; + } + } + if(iprev != xc->rvat_chain_len) + { + xc->rvat_chain_pos_tidx = ptidx; + xc->rvat_chain_pos_idx = iprev; + xc->rvat_chain_pos_time = tim; + xc->rvat_chain_pos_valid = 1; - if(iprev != xc->rvat_chain_len) - { - unsigned char *vdata = xc->rvat_chain_mem + iprev + pskip; + if(!(pvli & 1)) + { + buf[0] = ((pvli >> 1) & 1) | '0'; + } + else + { + buf[0] = FST_RCV_STR[((pvli >> 1) & 7)]; + } + buf[1] = 0; + return(buf); + } + else + { + return(fstExtractRvatDataFromFrame(xc, facidx, buf)); + } + } + else + { + while(irvat_chain_len) + { + uint32_t vli = fstGetVarint32(xc->rvat_chain_mem + i, &skiplen); + tdelta = vli >> 1; - xc->rvat_chain_pos_tidx = ptidx; - xc->rvat_chain_pos_idx = iprev; - xc->rvat_chain_pos_time = tim; - xc->rvat_chain_pos_valid = 1; + if(xc->rvat_time_table[tidx + tdelta] <= tim) + { + iprev = i; + pvli = vli; + ptidx = tidx; + pskip = skiplen; - if(xc->signal_typs[facidx] != FST_VT_VCD_REAL) - { - if(!(pvli & 1)) - { - int byte = 0; - int bit; - int j; + tidx += tdelta; + i+=skiplen; - for(j=0;jsignal_lens[facidx];j++) - { - unsigned char ch; - byte = j/8; - bit = 7 - (j & 7); - ch = ((vdata[byte] >> bit) & 1) | '0'; - buf[j] = ch; - } - buf[j] = 0; + if(!(pvli & 1)) + { + i+=((xc->signal_lens[facidx]+7)/8); + } + else + { + i+=xc->signal_lens[facidx]; + } + } + else + { + break; + } + } - return(buf); - } - else - { - memcpy(buf, vdata, xc->signal_lens[facidx]); - buf[xc->signal_lens[facidx]] = 0; - return(buf); - } - } - else - { - double d; - unsigned char *clone_d = (unsigned char *)&d; - unsigned char bufd[8]; - unsigned char *srcdata; + if(iprev != xc->rvat_chain_len) + { + unsigned char *vdata = xc->rvat_chain_mem + iprev + pskip; - if(!(pvli & 1)) /* very rare case, but possible */ - { - int bit; - int j; + xc->rvat_chain_pos_tidx = ptidx; + xc->rvat_chain_pos_idx = iprev; + xc->rvat_chain_pos_time = tim; + xc->rvat_chain_pos_valid = 1; - for(j=0;j<8;j++) - { - unsigned char ch; - bit = 7 - (j & 7); - ch = ((vdata[0] >> bit) & 1) | '0'; - bufd[j] = ch; - } + if(xc->signal_typs[facidx] != FST_VT_VCD_REAL) + { + if(!(pvli & 1)) + { + int byte = 0; + int bit; + unsigned int j; - srcdata = bufd; - } - else - { - srcdata = vdata; - } + for(j=0;jsignal_lens[facidx];j++) + { + unsigned char ch; + byte = j/8; + bit = 7 - (j & 7); + ch = ((vdata[byte] >> bit) & 1) | '0'; + buf[j] = ch; + } + buf[j] = 0; - if(xc->double_endian_match) - { - memcpy(clone_d, srcdata, 8); - } - else - { - int j; + return(buf); + } + else + { + memcpy(buf, vdata, xc->signal_lens[facidx]); + buf[xc->signal_lens[facidx]] = 0; + return(buf); + } + } + else + { + double d; + unsigned char *clone_d = (unsigned char *)&d; + unsigned char bufd[8]; + unsigned char *srcdata; - for(j=0;j<8;j++) - { - clone_d[j] = srcdata[7-j]; - } - } + if(!(pvli & 1)) /* very rare case, but possible */ + { + int bit; + int j; - sprintf(buf, "r%.16g", d); - return(buf); - } - } - else - { - return(fstExtractRvatDataFromFrame(xc, facidx, buf)); - } + for(j=0;j<8;j++) + { + unsigned char ch; + bit = 7 - (j & 7); + ch = ((vdata[0] >> bit) & 1) | '0'; + bufd[j] = ch; + } + + srcdata = bufd; + } + else + { + srcdata = vdata; + } + + if(xc->double_endian_match) + { + memcpy(clone_d, srcdata, 8); + } + else + { + int j; + + for(j=0;j<8;j++) + { + clone_d[j] = srcdata[7-j]; + } + } + + sprintf(buf, "r%.16g", d); + return(buf); + } + } + else + { + return(fstExtractRvatDataFromFrame(xc, facidx, buf)); + } } } @@ -6370,29 +6371,29 @@ struct collchain_t **ar; struct collchain_t *chain, *pchain; if(!*base) - { - *base = calloc(1, (hashmask + 1) * sizeof(void *)); - } + { + *base = calloc(1, (hashmask + 1) * sizeof(void *)); + } ar = *base; h = (hf = j_hash(mem, length, length)) & hashmask; pchain = chain = ar[h]; while(chain) - { - if((chain->fullhash == hf) && (chain->length == length) && !memcmp(chain->mem, mem, length)) - { - if(pchain != chain) /* move hit to front */ - { - pchain->next = chain->next; - chain->next = ar[h]; - ar[h] = chain; - } - return(&(chain->payload)); - } + { + if((chain->fullhash == hf) && (chain->length == length) && !memcmp(chain->mem, mem, length)) + { + if(pchain != chain) /* move hit to front */ + { + pchain->next = chain->next; + chain->next = ar[h]; + ar[h] = chain; + } + return(&(chain->payload)); + } - pchain = chain; - chain = chain->next; - } + pchain = chain; + chain = chain->next; + } chain = calloc(1, sizeof(struct collchain_t) + length - 1); memcpy(chain->mem, mem, length); @@ -6412,22 +6413,22 @@ struct collchain_t **ar; struct collchain_t *chain, *chain_next; if(base && *base) - { - ar = *base; - for(h=0;h<=hashmask;h++) - { - chain = ar[h]; - while(chain) - { - chain_next = chain->next; - free(chain); - chain = chain_next; - } - } + { + ar = *base; + for(h=0;h<=hashmask;h++) + { + chain = ar[h]; + while(chain) + { + chain_next = chain->next; + free(chain); + chain = chain_next; + } + } - free(*base); - *base = NULL; - } + free(*base); + *base = NULL; + } } #endif @@ -6448,35 +6449,35 @@ unsigned char val; int i; for(i=0;i ' ') && (src[i] <= '~')) /* no white spaces in output */ - { - *(dst++) = src[i]; - } - else - { - val = src[i]; - *(dst++) = '\\'; - *(dst++) = (val/64) + '0'; val = val & 63; - *(dst++) = (val/8) + '0'; val = val & 7; - *(dst++) = (val) + '0'; - } - break; - } - } + { + switch(src[i]) + { + case '\a': *(dst++) = '\\'; *(dst++) = 'a'; break; + case '\b': *(dst++) = '\\'; *(dst++) = 'b'; break; + case '\f': *(dst++) = '\\'; *(dst++) = 'f'; break; + case '\n': *(dst++) = '\\'; *(dst++) = 'n'; break; + case '\r': *(dst++) = '\\'; *(dst++) = 'r'; break; + case '\t': *(dst++) = '\\'; *(dst++) = 't'; break; + case '\v': *(dst++) = '\\'; *(dst++) = 'v'; break; + case '\'': *(dst++) = '\\'; *(dst++) = '\''; break; + case '\"': *(dst++) = '\\'; *(dst++) = '\"'; break; + case '\\': *(dst++) = '\\'; *(dst++) = '\\'; break; + case '\?': *(dst++) = '\\'; *(dst++) = '\?'; break; + default: if((src[i] > ' ') && (src[i] <= '~')) /* no white spaces in output */ + { + *(dst++) = src[i]; + } + else + { + val = src[i]; + *(dst++) = '\\'; + *(dst++) = (val/64) + '0'; val = val & 63; + *(dst++) = (val/8) + '0'; val = val & 7; + *(dst++) = (val) + '0'; + } + break; + } + } return(dst - d); } @@ -6493,51 +6494,51 @@ unsigned char val[3]; int i; for(i=0;i='A')&&(val[0]<='F')) ? (val[0] - 'A' + 10) : (val[0] - '0'); - val[1] = ((val[1]>='A')&&(val[1]<='F')) ? (val[1] - 'A' + 10) : (val[1] - '0'); - *(dst++) = val[0] * 16 + val[1]; - break; + case 'x': val[0] = toupper(src[++i]); + val[1] = toupper(src[++i]); + val[0] = ((val[0]>='A')&&(val[0]<='F')) ? (val[0] - 'A' + 10) : (val[0] - '0'); + val[1] = ((val[1]>='A')&&(val[1]<='F')) ? (val[1] - 'A' + 10) : (val[1] - '0'); + *(dst++) = val[0] * 16 + val[1]; + break; - case '0': - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': val[0] = src[ i] - '0'; - val[1] = src[++i] - '0'; - val[2] = src[++i] - '0'; - *(dst++) = val[0] * 64 + val[1] * 8 + val[2]; - break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': val[0] = src[ i] - '0'; + val[1] = src[++i] - '0'; + val[2] = src[++i] - '0'; + *(dst++) = val[0] * 64 + val[1] * 8 + val[2]; + break; - default: *(dst++) = src[i]; break; - } - } - } + default: *(dst++) = src[i]; break; + } + } + } return(dst - s); } diff --git a/vpi/fstapi.h b/vpi/fstapi.h index bc02f66f4..83daac4b0 100644 --- a/vpi/fstapi.h +++ b/vpi/fstapi.h @@ -57,9 +57,9 @@ enum fstFileType { }; enum fstBlockType { - FST_BL_HDR = 0, + FST_BL_HDR = 0, FST_BL_VCDATA = 1, - FST_BL_BLACKOUT = 2, + FST_BL_BLACKOUT = 2, FST_BL_GEOM = 3, FST_BL_HIER = 4, FST_BL_VCDATA_DYN_ALIAS = 5, @@ -67,8 +67,8 @@ enum fstBlockType { FST_BL_HIER_LZ4DUO = 7, FST_BL_VCDATA_DYN_ALIAS2 = 8, - FST_BL_ZWRAPPER = 254, /* indicates that whole trace is gz wrapped */ - FST_BL_SKIP = 255 /* used while block is being written */ + FST_BL_ZWRAPPER = 254, /* indicates that whole trace is gz wrapped */ + FST_BL_SKIP = 255 /* used while block is being written */ }; enum fstScopeType { @@ -108,7 +108,7 @@ enum fstScopeType { }; enum fstVarType { - FST_VT_MIN = 0, /* start of vartypes */ + FST_VT_MIN = 0, /* start of vartypes */ FST_VT_VCD_EVENT = 0, FST_VT_VCD_INTEGER = 1, @@ -129,21 +129,21 @@ enum fstVarType { FST_VT_VCD_WIRE = 16, FST_VT_VCD_WOR = 17, FST_VT_VCD_PORT = 18, - FST_VT_VCD_SPARRAY = 19, /* used to define the rownum (index) port for a sparse array */ + FST_VT_VCD_SPARRAY = 19, /* used to define the rownum (index) port for a sparse array */ FST_VT_VCD_REALTIME = 20, - FST_VT_GEN_STRING = 21, /* generic string type (max len is defined dynamically via fstWriterEmitVariableLengthValueChange) */ + FST_VT_GEN_STRING = 21, /* generic string type (max len is defined dynamically via fstWriterEmitVariableLengthValueChange) */ FST_VT_SV_BIT = 22, FST_VT_SV_LOGIC = 23, - FST_VT_SV_INT = 24, /* declare as size = 32 */ - FST_VT_SV_SHORTINT = 25, /* declare as size = 16 */ - FST_VT_SV_LONGINT = 26, /* declare as size = 64 */ - FST_VT_SV_BYTE = 27, /* declare as size = 8 */ - FST_VT_SV_ENUM = 28, /* declare as appropriate type range */ - FST_VT_SV_SHORTREAL = 29, /* declare and emit same as FST_VT_VCD_REAL (needs to be emitted as double, not a float) */ + FST_VT_SV_INT = 24, /* declare as size = 32 */ + FST_VT_SV_SHORTINT = 25, /* declare as size = 16 */ + FST_VT_SV_LONGINT = 26, /* declare as size = 64 */ + FST_VT_SV_BYTE = 27, /* declare as size = 8 */ + FST_VT_SV_ENUM = 28, /* declare as appropriate type range */ + FST_VT_SV_SHORTREAL = 29, /* declare and emit same as FST_VT_VCD_REAL (needs to be emitted as double, not a float) */ - FST_VT_MAX = 29 /* end of vartypes */ + FST_VT_MAX = 29 /* end of vartypes */ }; enum fstVarDir { @@ -174,7 +174,7 @@ enum fstHierType { enum fstAttrType { FST_AT_MIN = 0, - FST_AT_MISC = 0, /* self-contained: does not need matching FST_HT_ATTREND */ + FST_AT_MISC = 0, /* self-contained: does not need matching FST_HT_ATTREND */ FST_AT_ARRAY = 1, FST_AT_ENUM = 2, FST_AT_PACK = 3, @@ -185,9 +185,9 @@ enum fstAttrType { enum fstMiscType { FST_MT_MIN = 0, - FST_MT_COMMENT = 0, /* use fstWriterSetComment() to emit */ - FST_MT_ENVVAR = 1, /* use fstWriterSetEnvVar() to emit */ - FST_MT_SUPVAR = 2, /* use fstWriterCreateVar2() to emit */ + FST_MT_COMMENT = 0, /* use fstWriterSetComment() to emit */ + FST_MT_ENVVAR = 1, /* use fstWriterSetEnvVar() to emit */ + FST_MT_SUPVAR = 2, /* use fstWriterCreateVar2() to emit */ FST_MT_PATHNAME = 3, /* reserved for fstWriterSetSourceStem() string -> number management */ FST_MT_SOURCESTEM = 4, /* use fstWriterSetSourceStem() to emit */ FST_MT_SOURCEISTEM = 5, /* use fstWriterSetSourceInstantiationStem() to emit */ @@ -274,7 +274,7 @@ enum fstSupplementalDataType { FST_SDT_MAX = 16, FST_SDT_SVT_SHIFT_COUNT = 10, /* FST_SVT_* is ORed in by fstWriterCreateVar2() to the left after shifting FST_SDT_SVT_SHIFT_COUNT */ - FST_SDT_ABS_MAX = ((1<<(FST_SDT_SVT_SHIFT_COUNT))-1) + FST_SDT_ABS_MAX = ((1<<(FST_SDT_SVT_SHIFT_COUNT))-1) }; @@ -283,141 +283,141 @@ struct fstHier unsigned char htyp; union { - /* if htyp == FST_HT_SCOPE */ - struct fstHierScope { - unsigned char typ; /* FST_ST_MIN ... FST_ST_MAX */ - const char *name; - const char *component; - uint32_t name_length; /* strlen(u.scope.name) */ - uint32_t component_length; /* strlen(u.scope.component) */ - } scope; + /* if htyp == FST_HT_SCOPE */ + struct fstHierScope { + unsigned char typ; /* FST_ST_MIN ... FST_ST_MAX */ + const char *name; + const char *component; + uint32_t name_length; /* strlen(u.scope.name) */ + uint32_t component_length; /* strlen(u.scope.component) */ + } scope; - /* if htyp == FST_HT_VAR */ - struct fstHierVar { - unsigned char typ; /* FST_VT_MIN ... FST_VT_MAX */ - unsigned char direction; /* FST_VD_MIN ... FST_VD_MAX */ - unsigned char svt_workspace; /* zeroed out by FST reader, for client code use */ - unsigned char sdt_workspace; /* zeroed out by FST reader, for client code use */ - unsigned int sxt_workspace; /* zeroed out by FST reader, for client code use */ - const char *name; - uint32_t length; - fstHandle handle; - uint32_t name_length; /* strlen(u.var.name) */ - unsigned is_alias : 1; - } var; + /* if htyp == FST_HT_VAR */ + struct fstHierVar { + unsigned char typ; /* FST_VT_MIN ... FST_VT_MAX */ + unsigned char direction; /* FST_VD_MIN ... FST_VD_MAX */ + unsigned char svt_workspace; /* zeroed out by FST reader, for client code use */ + unsigned char sdt_workspace; /* zeroed out by FST reader, for client code use */ + unsigned int sxt_workspace; /* zeroed out by FST reader, for client code use */ + const char *name; + uint32_t length; + fstHandle handle; + uint32_t name_length; /* strlen(u.var.name) */ + unsigned is_alias : 1; + } var; - /* if htyp == FST_HT_ATTRBEGIN */ - struct fstHierAttr { - unsigned char typ; /* FST_AT_MIN ... FST_AT_MAX */ - unsigned char subtype; /* from fstMiscType, fstArrayType, fstEnumValueType, fstPackType */ - const char *name; - uint64_t arg; /* number of array elements, struct members, or some other payload (possibly ignored) */ - uint64_t arg_from_name; /* for when name is overloaded as a variable-length integer (FST_AT_MISC + FST_MT_SOURCESTEM) */ - uint32_t name_length; /* strlen(u.attr.name) */ - } attr; - } u; + /* if htyp == FST_HT_ATTRBEGIN */ + struct fstHierAttr { + unsigned char typ; /* FST_AT_MIN ... FST_AT_MAX */ + unsigned char subtype; /* from fstMiscType, fstArrayType, fstEnumValueType, fstPackType */ + const char *name; + uint64_t arg; /* number of array elements, struct members, or some other payload (possibly ignored) */ + uint64_t arg_from_name; /* for when name is overloaded as a variable-length integer (FST_AT_MISC + FST_MT_SOURCESTEM) */ + uint32_t name_length; /* strlen(u.attr.name) */ + } attr; + } u; }; /* * writer functions */ -void fstWriterClose(void *ctx); -void * fstWriterCreate(const char *nam, int use_compressed_hier); - /* used for Verilog/SV */ -fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir vd, - uint32_t len, const char *nam, fstHandle aliasHandle); - /* future expansion for VHDL and other languages. The variable type, data type, etc map onto - the current Verilog/SV one. The "type" string is optional for a more verbose or custom description */ -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 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); -int fstWriterGetFseekFailed(void *ctx); -void fstWriterSetAttrBegin(void *ctx, enum fstAttrType attrtype, int subtype, - const char *attrname, uint64_t arg); -void fstWriterSetAttrEnd(void *ctx); -void fstWriterSetComment(void *ctx, const char *comm); -void fstWriterSetDate(void *ctx, const char *dat); -void fstWriterSetDumpSizeLimit(void *ctx, uint64_t numbytes); -void fstWriterSetEnvVar(void *ctx, const char *envvar); -void fstWriterSetFileType(void *ctx, enum fstFileType filetype); -void fstWriterSetPackType(void *ctx, enum fstWriterPackType typ); -void fstWriterSetParallelMode(void *ctx, int enable); -void fstWriterSetRepackOnClose(void *ctx, int enable); /* type = 0 (none), 1 (libz) */ -void fstWriterSetScope(void *ctx, enum fstScopeType scopetype, - const char *scopename, const char *scopecomp); -void fstWriterSetSourceInstantiationStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath); -void fstWriterSetSourceStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath); -void fstWriterSetTimescale(void *ctx, int ts); -void fstWriterSetTimescaleFromString(void *ctx, const char *s); -void fstWriterSetTimezero(void *ctx, int64_t tim); -void fstWriterSetUpscope(void *ctx); -void fstWriterSetVersion(void *ctx, const char *vers); +void fstWriterClose(void *ctx); +void * fstWriterCreate(const char *nam, int use_compressed_hier); + /* used for Verilog/SV */ +fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir vd, + uint32_t len, const char *nam, fstHandle aliasHandle); + /* future expansion for VHDL and other languages. The variable type, data type, etc map onto + the current Verilog/SV one. The "type" string is optional for a more verbose or custom description */ +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 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); +int fstWriterGetFseekFailed(void *ctx); +void fstWriterSetAttrBegin(void *ctx, enum fstAttrType attrtype, int subtype, + const char *attrname, uint64_t arg); +void fstWriterSetAttrEnd(void *ctx); +void fstWriterSetComment(void *ctx, const char *comm); +void fstWriterSetDate(void *ctx, const char *dat); +void fstWriterSetDumpSizeLimit(void *ctx, uint64_t numbytes); +void fstWriterSetEnvVar(void *ctx, const char *envvar); +void fstWriterSetFileType(void *ctx, enum fstFileType filetype); +void fstWriterSetPackType(void *ctx, enum fstWriterPackType typ); +void fstWriterSetParallelMode(void *ctx, int enable); +void fstWriterSetRepackOnClose(void *ctx, int enable); /* type = 0 (none), 1 (libz) */ +void fstWriterSetScope(void *ctx, enum fstScopeType scopetype, + const char *scopename, const char *scopecomp); +void fstWriterSetSourceInstantiationStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath); +void fstWriterSetSourceStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath); +void fstWriterSetTimescale(void *ctx, int ts); +void fstWriterSetTimescaleFromString(void *ctx, const char *s); +void fstWriterSetTimezero(void *ctx, int64_t tim); +void fstWriterSetUpscope(void *ctx); +void fstWriterSetVersion(void *ctx, const char *vers); /* * reader functions */ -void fstReaderClose(void *ctx); -void fstReaderClrFacProcessMask(void *ctx, fstHandle facidx); -void fstReaderClrFacProcessMaskAll(void *ctx); -uint64_t fstReaderGetAliasCount(void *ctx); -const char * fstReaderGetCurrentFlatScope(void *ctx); -void * fstReaderGetCurrentScopeUserInfo(void *ctx); -int fstReaderGetCurrentScopeLen(void *ctx); -const char * fstReaderGetDateString(void *ctx); -int fstReaderGetDoubleEndianMatchState(void *ctx); -uint64_t fstReaderGetDumpActivityChangeTime(void *ctx, uint32_t idx); -unsigned char fstReaderGetDumpActivityChangeValue(void *ctx, uint32_t idx); -uint64_t fstReaderGetEndTime(void *ctx); -int fstReaderGetFacProcessMask(void *ctx, fstHandle facidx); -int fstReaderGetFileType(void *ctx); -int fstReaderGetFseekFailed(void *ctx); -fstHandle fstReaderGetMaxHandle(void *ctx); -uint64_t fstReaderGetMemoryUsedByWriter(void *ctx); -uint32_t fstReaderGetNumberDumpActivityChanges(void *ctx); -uint64_t fstReaderGetScopeCount(void *ctx); -uint64_t fstReaderGetStartTime(void *ctx); -signed char fstReaderGetTimescale(void *ctx); -int64_t fstReaderGetTimezero(void *ctx); -uint64_t fstReaderGetValueChangeSectionCount(void *ctx); -char * fstReaderGetValueFromHandleAtTime(void *ctx, uint64_t tim, fstHandle facidx, char *buf); -uint64_t fstReaderGetVarCount(void *ctx); -const char * fstReaderGetVersionString(void *ctx); +void fstReaderClose(void *ctx); +void fstReaderClrFacProcessMask(void *ctx, fstHandle facidx); +void fstReaderClrFacProcessMaskAll(void *ctx); +uint64_t fstReaderGetAliasCount(void *ctx); +const char * fstReaderGetCurrentFlatScope(void *ctx); +void * fstReaderGetCurrentScopeUserInfo(void *ctx); +int fstReaderGetCurrentScopeLen(void *ctx); +const char * fstReaderGetDateString(void *ctx); +int fstReaderGetDoubleEndianMatchState(void *ctx); +uint64_t fstReaderGetDumpActivityChangeTime(void *ctx, uint32_t idx); +unsigned char fstReaderGetDumpActivityChangeValue(void *ctx, uint32_t idx); +uint64_t fstReaderGetEndTime(void *ctx); +int fstReaderGetFacProcessMask(void *ctx, fstHandle facidx); +int fstReaderGetFileType(void *ctx); +int fstReaderGetFseekFailed(void *ctx); +fstHandle fstReaderGetMaxHandle(void *ctx); +uint64_t fstReaderGetMemoryUsedByWriter(void *ctx); +uint32_t fstReaderGetNumberDumpActivityChanges(void *ctx); +uint64_t fstReaderGetScopeCount(void *ctx); +uint64_t fstReaderGetStartTime(void *ctx); +signed char fstReaderGetTimescale(void *ctx); +int64_t fstReaderGetTimezero(void *ctx); +uint64_t fstReaderGetValueChangeSectionCount(void *ctx); +char * fstReaderGetValueFromHandleAtTime(void *ctx, uint64_t tim, fstHandle facidx, char *buf); +uint64_t fstReaderGetVarCount(void *ctx); +const char * fstReaderGetVersionString(void *ctx); struct fstHier *fstReaderIterateHier(void *ctx); -int fstReaderIterateHierRewind(void *ctx); -int fstReaderIterBlocks(void *ctx, - void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx, const unsigned char *value), - void *user_callback_data_pointer, FILE *vcdhandle); -int fstReaderIterBlocks2(void *ctx, - void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx, const unsigned char *value), - void (*value_change_callback_varlen)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx, const unsigned char *value, uint32_t len), - void *user_callback_data_pointer, FILE *vcdhandle); -void fstReaderIterBlocksSetNativeDoublesOnCallback(void *ctx, int enable); -void * fstReaderOpen(const char *nam); -void * fstReaderOpenForUtilitiesOnly(void); -const char * fstReaderPopScope(void *ctx); -int fstReaderProcessHier(void *ctx, FILE *vcdhandle); -const char * fstReaderPushScope(void *ctx, const char *nam, void *user_info); -void fstReaderResetScope(void *ctx); -void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx); -void fstReaderSetFacProcessMaskAll(void *ctx); -void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_time); -void fstReaderSetUnlimitedTimeRange(void *ctx); -void fstReaderSetVcdExtensions(void *ctx, int enable); +int fstReaderIterateHierRewind(void *ctx); +int fstReaderIterBlocks(void *ctx, + void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx, const unsigned char *value), + void *user_callback_data_pointer, FILE *vcdhandle); +int fstReaderIterBlocks2(void *ctx, + void (*value_change_callback)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx, const unsigned char *value), + void (*value_change_callback_varlen)(void *user_callback_data_pointer, uint64_t time, fstHandle facidx, const unsigned char *value, uint32_t len), + void *user_callback_data_pointer, FILE *vcdhandle); +void fstReaderIterBlocksSetNativeDoublesOnCallback(void *ctx, int enable); +void * fstReaderOpen(const char *nam); +void * fstReaderOpenForUtilitiesOnly(void); +const char * fstReaderPopScope(void *ctx); +int fstReaderProcessHier(void *ctx, FILE *vcdhandle); +const char * fstReaderPushScope(void *ctx, const char *nam, void *user_info); +void fstReaderResetScope(void *ctx); +void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx); +void fstReaderSetFacProcessMaskAll(void *ctx); +void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_time); +void fstReaderSetUnlimitedTimeRange(void *ctx); +void fstReaderSetVcdExtensions(void *ctx, int enable); /* * utility functions */ -int fstUtilityBinToEsc(unsigned char *d, unsigned char *s, int len); -int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len); +int fstUtilityBinToEsc(unsigned char *d, unsigned char *s, int len); +int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len); #ifdef __cplusplus } From 684e46a6c15fcf04b758551b8c0f00d63ee43a10 Mon Sep 17 00:00:00 2001 From: Cary R Date: Wed, 11 Jun 2014 17:01:47 -0700 Subject: [PATCH 057/245] Update fstapi.c to latest from GTKWavE (remove some compile warnings) --- vpi/fstapi.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/vpi/fstapi.c b/vpi/fstapi.c index 05c2a82b2..49476ade9 100644 --- a/vpi/fstapi.c +++ b/vpi/fstapi.c @@ -1696,7 +1696,7 @@ if(tmem) unsigned char *dmem = malloc(compressBound(destlen)); int rc = compress2(dmem, &destlen, tmem, tlen, 9); - if((rc == Z_OK) && (destlen < tlen)) + if((rc == Z_OK) && (((off_t)destlen) < tlen)) { fstFwrite(dmem, destlen, 1, xc->handle); } @@ -1926,7 +1926,7 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) unsigned char *dmem = malloc(compressBound(destlen)); int rc = compress2(dmem, &destlen, tmem, tlen, 9); - if((rc != Z_OK) || (destlen > tlen)) + if((rc != Z_OK) || (((off_t)destlen) > tlen)) { destlen = tlen; } @@ -1937,7 +1937,7 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) fstWriterUint64(xc->handle, tlen); /* uncompressed */ /* compressed len is section length - 24 */ fstWriterUint64(xc->handle, xc->maxhandle); /* maxhandle */ - fstFwrite((destlen != tlen) ? dmem : tmem, destlen, 1, xc->handle); + fstFwrite((((off_t)destlen) != tlen) ? dmem : tmem, destlen, 1, xc->handle); fflush(xc->handle); fstWriterFseeko(xc, xc->handle, fixup_offs, SEEK_SET); From 81947edaa5e9f8d544ad66bcdacb339ec169cd8a Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 12 Jun 2014 09:09:49 -0700 Subject: [PATCH 058/245] A bit select is not the same as selecting part of a packed array When adding the ability to select part of a multi-dimensional packed array the sign and size information for a true bit select was broken. --- elab_expr.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/elab_expr.cc b/elab_expr.cc index 481430024..693f4f84d 100644 --- a/elab_expr.cc +++ b/elab_expr.cc @@ -2832,9 +2832,11 @@ unsigned PEIdent::test_width(Design*des, NetScope*scope, width_mode_t&mode) const index_component_t&index_tail = name_tail.index.back(); ivl_assert(*this, index_tail.msb); } - // If we have a net in hand, then we can predict what - // the slice width will be. If not, then just guess. - if (net == 0) + // If we have a net in hand, then we can predict what the + // slice width will be. If not, then assume it will be a + // simple bit select. If the net only has a single dimension + // then this is still a simple bit select. + if ((net == 0) || (net->packed_dimensions() <= 1)) use_width = 1; break; default: From 7cd3bdb0d0b62061d46eb42770607fc5756c8c36 Mon Sep 17 00:00:00 2001 From: Cary R Date: Thu, 12 Jun 2014 09:17:03 -0700 Subject: [PATCH 059/245] Add support for a single argument $urandom_range() call --- vpi/sys_random.c | 36 +++++++++++++++++++----------------- 1 file changed, 19 insertions(+), 17 deletions(-) diff --git a/vpi/sys_random.c b/vpi/sys_random.c index b8c68e1ce..31e05e244 100644 --- a/vpi/sys_random.c +++ b/vpi/sys_random.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2013 Stephen Williams (steve@icarus.com) + * Copyright (c) 2000-2014 Stephen Williams (steve@icarus.com) * * This source code is free software; you can redistribute it * and/or modify it in source code form under the terms of the GNU @@ -552,7 +552,7 @@ static PLI_INT32 sys_random_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) return 0; } -/* From System Verilog 3.1a. */ +/* From System Verilog */ static PLI_INT32 sys_urandom_range_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); @@ -561,20 +561,17 @@ static PLI_INT32 sys_urandom_range_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) /* Check that there are arguments. */ if (argv == 0) { - vpi_printf("ERROR: %s requires two arguments.\n", name); + vpi_printf("ERROR: %s requires one or two arguments.\n", name); vpi_control(vpiFinish, 1); return 0; } - /* Check that there are at least two arguments. */ + /* Check that there is at least one arguments. */ arg = vpi_scan(argv); /* This should never be zero. */ assert(arg); arg = vpi_scan(argv); - if (arg == 0) { - vpi_printf("ERROR: %s requires two arguments.\n", name); - vpi_control(vpiFinish, 1); - return 0; - } + /* Is this a signle argument function call? */ + if (arg == 0) return 0; /* These functions takes at most two argument. */ arg = vpi_scan(argv); @@ -588,7 +585,7 @@ static PLI_INT32 sys_urandom_range_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) return 0; } -/* From System Verilog 3.1a. */ +/* From System Verilog */ static unsigned long urandom(long *seed, unsigned long max, unsigned long min) { static long i_seed = 0; @@ -603,7 +600,7 @@ static unsigned long urandom(long *seed, unsigned long max, unsigned long min) return result; } -/* From System Verilog 3.1a. */ +/* From System Verilog */ static PLI_INT32 sys_urandom_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh, argv, seed = 0; @@ -639,7 +636,7 @@ static PLI_INT32 sys_urandom_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) return 0; } -/* From System Verilog 3.1a. */ +/* From System Verilog */ static PLI_INT32 sys_urandom_range_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh, argv, maxval, minval; @@ -656,8 +653,14 @@ static PLI_INT32 sys_urandom_range_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) vpi_get_value(maxval, &val); i_maxval = val.value.integer; - vpi_get_value(minval, &val); - i_minval = val.value.integer; + /* Is this a two or one argument function call? */ + if (minval) { + vpi_get_value(minval, &val); + i_minval = val.value.integer; + vpi_free_object(argv); + } else { + i_minval = 0; + } /* Swap the two arguments if they are out of order. */ if (i_minval > i_maxval) { @@ -669,7 +672,6 @@ static PLI_INT32 sys_urandom_range_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) /* Calculate and return the result. */ val.value.integer = urandom(0, i_maxval, i_minval); vpi_put_value(callh, &val, 0, vpiNoDelay); - vpi_free_object(argv); return 0; } @@ -922,7 +924,7 @@ void sys_random_register() res = vpi_register_systf(&tf_data); vpip_make_systf_system_defined(res); - /* From System Verilog 3.1a. */ + /* From System Verilog */ tf_data.type = vpiSysFunc; tf_data.sysfunctype = vpiSysFuncSized; tf_data.tfname = "$urandom"; @@ -933,7 +935,7 @@ void sys_random_register() res = vpi_register_systf(&tf_data); vpip_make_systf_system_defined(res); - /* From System Verilog 3.1a. */ + /* From System Verilog */ tf_data.type = vpiSysFunc; tf_data.sysfunctype = vpiSysFuncSized; tf_data.tfname = "$urandom_range"; From 26f71f2d94ce2df1a18c494d560662f5a371a974 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Thu, 12 Jun 2014 17:50:44 -0700 Subject: [PATCH 060/245] Handle special case of missing condit inputs. It shouldn't be possible, but sometimes is, that a NetCondit is missing input nets during async synthesis. Handle this by generating a place-holder net and printing a warning. --- synth2.cc | 50 +++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/synth2.cc b/synth2.cc index 86e7d8804..8b5370b9a 100644 --- a/synth2.cc +++ b/synth2.cc @@ -514,8 +514,26 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, bool rc_flag = true; for (unsigned idx = 0 ; idx < nex_out.pin_count() ; idx += 1) { - ivl_assert(*this, asig.pin(idx).nexus()->pick_any_net()); - ivl_assert(*this, bsig.pin(idx).nexus()->pick_any_net()); + // It should not be possible for the a (true) or b + // (false) signals to be missing. If either is, print a + // warning and clear a flag so that the rest of this + // code can find a way to cope. + bool asig_is_present = true; + if (! asig.pin(idx).nexus()->pick_any_net()) { + cerr << get_fileline() << ": warning: " + << "True clause of conditional statement might not" + << " drive all expected outputs." << endl; + asig_is_present = false; + } + + bool bsig_is_present = true; + if (! bsig.pin(idx).nexus()->pick_any_net()) { + cerr << get_fileline() << ": warning: " + << "False clause of conditional statement might not" + << " drive all expected outputs." << endl; + bsig_is_present = false; + } + // Guess the mux type from the type of the output. ivl_variable_type_t mux_data_type = IVL_VT_LOGIC; if (NetNet*tmp = nex_out.pin(idx).nexus()->pick_any_net()) { @@ -523,7 +541,14 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, } unsigned mux_off = 0; - unsigned mux_width = asig.pin(idx).nexus()->vector_width(); + unsigned mux_width; + if (asig_is_present) + mux_width = asig.pin(idx).nexus()->vector_width(); + else if (bsig_is_present) + mux_width = bsig.pin(idx).nexus()->vector_width(); + else + mux_width = 0; + const unsigned mux_lwidth = mux_width; ivl_assert(*this, mux_width != 0); @@ -561,7 +586,7 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, bpv = 0; } - if (mux_width != bsig.pin(idx).nexus()->vector_width()) { + if (bsig_is_present && mux_width != bsig.pin(idx).nexus()->vector_width()) { cerr << get_fileline() << ": internal error: " << "NetCondit::synth_async: " << "Mux input sizes do not match." @@ -587,9 +612,10 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, NetMux*mux = new NetMux(scope, scope->local_symbol(), mux_width, 2, 1); + mux->set_line(*this); listnot_an_array; - netvector_t*tmp_type; + netvector_t*tmp_type = 0; if (mux_width==1) tmp_type = new netvector_t(mux_data_type); else @@ -605,6 +631,20 @@ bool NetCondit::synth_async(Design*des, NetScope*scope, connect(mux->pin_Data(1), asig.pin(idx)); connect(mux->pin_Data(0), bsig.pin(idx)); + if (! asig_is_present) { + tmp_type = new netvector_t(mux_data_type, mux_width-1,0); + NetNet*tmp = new NetNet(scope, scope->local_symbol(), + NetNet::WIRE, not_an_array, tmp_type); + connect(mux->pin_Data(1), tmp->pin(0)); + } + + if (! bsig_is_present) { + tmp_type = new netvector_t(mux_data_type, mux_width-1,0); + NetNet*tmp = new NetNet(scope, scope->local_symbol(), + NetNet::WIRE, not_an_array, tmp_type); + connect(mux->pin_Data(0), tmp->pin(0)); + } + // We are only muxing a part of the output vector, so // make a NetPartSelect::PV to widen the vector to the // output at hand. From f8dc430fe59585ef7fdc6cfac91cb09b0a83db30 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Fri, 13 Jun 2014 18:01:41 -0700 Subject: [PATCH 061/245] Add synthesis support for casez statements. This generates an EQZ LPM device that carries the case-z-ness to the code generator. Also add to the vvp code generator support for the EQZ device so that the synthesis results can be simulated. Account for the wildcard devices in the sizer. --- design_dump.cc | 26 ++++-- expr_synth.cc | 2 +- ivl_target.h | 15 +++- net_func_eval.cc | 8 +- net_nex_input.cc | 2 +- net_nex_output.cc | 2 +- net_proc.cc | 11 +-- netlist.cc | 9 +-- netlist.h | 37 ++++++--- synth2.cc | 169 ++++++++++++++++++++++++++++++++++++++- t-dll-api.cc | 8 ++ t-dll.cc | 15 +++- tgt-sizer/scan_lpms.cc | 14 ++++ tgt-sizer/sizer.cc | 9 +++ tgt-sizer/sizer_priv.h | 2 + tgt-stub/stub.c | 24 +++++- tgt-vvp/draw_net_input.c | 2 + tgt-vvp/vvp_scope.c | 14 ++++ vvp/arith.cc | 77 ++++++++++++++++++ vvp/arith.h | 18 +++++ vvp/compile.cc | 28 +++++++ vvp/compile.h | 4 + vvp/lexor.lex | 2 + vvp/parse.y | 13 ++- 24 files changed, 465 insertions(+), 46 deletions(-) diff --git a/design_dump.cc b/design_dump.cc index 0004cc3b4..65f602f3c 100644 --- a/design_dump.cc +++ b/design_dump.cc @@ -174,6 +174,25 @@ ostream& operator << (ostream&fd, PortType::Enum val) return fd; } +ostream& operator << (ostream&fd, NetCaseCmp::kind_t that) +{ + switch (that) { + case NetCaseCmp::EEQ: + fd << "==="; + break; + case NetCaseCmp::NEQ: + fd << "!=="; + break; + case NetCaseCmp::XEQ: + fd << "==?"; + break; + case NetCaseCmp::ZEQ: + fd << "==z?"; + break; + } + return fd; +} + ostream& ivl_type_s::debug_dump(ostream&o) const { o << typeid(*this).name(); @@ -550,10 +569,7 @@ void NetBUFZ::dump_node(ostream&o, unsigned ind) const void NetCaseCmp::dump_node(ostream&o, unsigned ind) const { - if (eeq_) - o << setw(ind) << "" << "case compare === : " << name() << endl; - else - o << setw(ind) << "" << "case compare !== : " << name() << endl; + o << setw(ind) << "" << "case compare " << kind_ << ": " << name() << endl; dump_node_pins(o, ind+4); } @@ -1004,7 +1020,7 @@ void NetCase::dump(ostream&o, unsigned ind) const break; } - for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { + for (unsigned idx = 0 ; idx < items_.size() ; idx += 1) { o << setw(ind+2) << ""; if (items_[idx].guard) o << *items_[idx].guard << ":"; diff --git a/expr_synth.cc b/expr_synth.cc index f709668b9..28f3c783e 100644 --- a/expr_synth.cc +++ b/expr_synth.cc @@ -274,7 +274,7 @@ NetNet* NetEBComp::synthesize(Design*des, NetScope*scope, NetExpr*root) if (op_ == 'E' || op_ == 'N') { NetCaseCmp*gate = new NetCaseCmp(scope, scope->local_symbol(), - width, op_=='E'?true:false); + width, op_=='E'?NetCaseCmp::EEQ:NetCaseCmp::NEQ); gate->set_line(*this); connect(gate->pin(0), osig->pin(0)); connect(gate->pin(1), lsig->pin(0)); diff --git a/ivl_target.h b/ivl_target.h index 70b5b9db2..56f5fc476 100644 --- a/ivl_target.h +++ b/ivl_target.h @@ -300,6 +300,8 @@ 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_EQZ= 38, /* casez EQ */ IVL_LPM_CMP_EQ = 10, IVL_LPM_CMP_GE = 1, IVL_LPM_CMP_GT = 2, @@ -1265,7 +1267,7 @@ extern unsigned ivl_lpm_lineno(ivl_lpm_t net); * width of the part. The ivl_lpm_q is the part end, and the * ivl_lpm_data(0) is the non-part end. * - * - Comparisons (IVL_LPM_CMP_GT/GE/EQ/NE/EEQ/NEE) + * - Comparisons (IVL_LPM_CMP_GT/GE/EQ/NE/EEQ/NEE/EQX/EQZ) * These devices have two inputs, available by the ivl_lpm_data() * function, and one output available by the ivl_lpm_q function. The * output width is always 1, but the ivl_lpm_width() returns the width @@ -1277,6 +1279,11 @@ 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 + * bits in the data(0) operand are wild. This matches the + * SystemVerilog convention for the ==? operator. + * * - Mux Device (IVL_LPM_MUX) * The MUX device has a q output, a select input, and a number of data * inputs. The ivl_lpm_q output and the ivl_lpm_data inputs all have @@ -1414,10 +1421,12 @@ extern ivl_nexus_t ivl_lpm_enable(ivl_lpm_t net); IVL_LPM_MUX IVL_LPM_POW IVL_LPM_SHIFTL IVL_LPM_SHIFTR IVL_LPM_SUB IVL_LPM_UFUNC */ extern ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx); - /* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_POW IVL_LPM_SUB */ + /* IVL_LPM_ADD IVL_LPM_MULT IVL_LPM_POW IVL_LPM_SUB IVL_LPM_CMP_EQ + IVL_LPM_CMP_EEQ IVL_LPM_CMP_EQX IVL_LPM_CMP_EQZ IVL_LPM_CMP_NEE */ extern ivl_nexus_t ivl_lpm_datab(ivl_lpm_t net, unsigned idx); /* IVL_LPM_ADD IVL_LPM_FF IVL_LPM_MULT IVL_LPM_PART IVL_LPM_POW - IVL_LPM_SUB IVL_LPM_UFUNC */ + IVL_LPM_SUB IVL_LPM_UFUNC IVL_LPM_CMP_EEQ IVL_LPM_CMP_EQX + IVL_LPM_CMP_EQZ IVL_LPM_CMP_NEE */ extern ivl_nexus_t ivl_lpm_q(ivl_lpm_t net); extern ivl_drive_t ivl_lpm_drive0(ivl_lpm_t net); extern ivl_drive_t ivl_lpm_drive1(ivl_lpm_t net); diff --git a/net_func_eval.cc b/net_func_eval.cc index a5b336b11..ecbe55780 100644 --- a/net_func_eval.cc +++ b/net_func_eval.cc @@ -416,8 +416,8 @@ bool NetCase::evaluate_function_vect_(const LineInfo&loc, NetProc*default_statement = 0; - for (unsigned cnt = 0 ; cnt < nitems_ ; cnt += 1) { - Item*item = &items_[cnt]; + for (unsigned cnt = 0 ; cnt < items_.size() ; cnt += 1) { + const Item*item = &items_[cnt]; if (item->guard == 0) { default_statement = item->statement; @@ -478,8 +478,8 @@ bool NetCase::evaluate_function_real_(const LineInfo&loc, NetProc*default_statement = 0; - for (unsigned cnt = 0 ; cnt < nitems_ ; cnt += 1) { - Item*item = &items_[cnt]; + for (unsigned cnt = 0 ; cnt < items_.size() ; cnt += 1) { + const Item*item = &items_[cnt]; if (item->guard == 0) { default_statement = item->statement; diff --git a/net_nex_input.cc b/net_nex_input.cc index 50053bf04..c30f52368 100644 --- a/net_nex_input.cc +++ b/net_nex_input.cc @@ -340,7 +340,7 @@ NexusSet* NetCase::nex_input(bool rem_out) if (result == 0) return 0; - for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { + for (size_t idx = 0 ; idx < items_.size() ; idx += 1) { /* Skip cases that have empty statements. */ if (items_[idx].statement == 0) diff --git a/net_nex_output.cc b/net_nex_output.cc index 232f0a122..a6cc52986 100644 --- a/net_nex_output.cc +++ b/net_nex_output.cc @@ -102,7 +102,7 @@ void NetBlock::nex_output(NexusSet&out) void NetCase::nex_output(NexusSet&out) { - for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { + for (size_t idx = 0 ; idx < items_.size() ; idx += 1) { // Empty statements clearly have no output. if (items_[idx].statement == 0) diff --git a/net_proc.cc b/net_proc.cc index 081a4ea40..c10bff7ab 100644 --- a/net_proc.cc +++ b/net_proc.cc @@ -71,23 +71,18 @@ const NetProc* NetBlock::proc_next(const NetProc*cur) const } NetCase::NetCase(NetCase::TYPE c, NetExpr*ex, unsigned cnt) -: type_(c), expr_(ex), nitems_(cnt) +: type_(c), expr_(ex), items_(cnt) { assert(expr_); - items_ = new Item[nitems_]; - for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { - items_[idx].statement = 0; - } } NetCase::~NetCase() { delete expr_; - for (unsigned idx = 0 ; idx < nitems_ ; idx += 1) { + for (size_t idx = 0 ; idx < items_.size() ; idx += 1) { delete items_[idx].guard; if (items_[idx].statement) delete items_[idx].statement; } - delete[]items_; } NetCase::TYPE NetCase::type() const @@ -97,7 +92,7 @@ NetCase::TYPE NetCase::type() const void NetCase::set_case(unsigned idx, NetExpr*e, NetProc*p) { - assert(idx < nitems_); + assert(idx < items_.size()); items_[idx].guard = e; items_[idx].statement = p; } diff --git a/netlist.cc b/netlist.cc index ebbf29d0f..2d266c943 100644 --- a/netlist.cc +++ b/netlist.cc @@ -1903,8 +1903,8 @@ unsigned NetBUFZ::width() const return width_; } -NetCaseCmp::NetCaseCmp(NetScope*s, perm_string n, unsigned wid, bool eeq__) -: NetNode(s, n, 3), width_(wid), eeq_(eeq__) +NetCaseCmp::NetCaseCmp(NetScope*s, perm_string n, unsigned wid, kind_t k) +: NetNode(s, n, 3), width_(wid), kind_(k) { pin(0).set_dir(Link::OUTPUT); pin(1).set_dir(Link::INPUT); @@ -1920,11 +1920,6 @@ unsigned NetCaseCmp::width() const return width_; } -bool NetCaseCmp::eeq() const -{ - return eeq_; -} - NetCondit::NetCondit(NetExpr*ex, NetProc*i, NetProc*e) : expr_(ex), if_(i), else_(e) { diff --git a/netlist.h b/netlist.h index 1f5d4e9be..87ea09ab7 100644 --- a/netlist.h +++ b/netlist.h @@ -2218,30 +2218,43 @@ class NetBUFZ : public NetNode { * input. The elaboration, btw, needs to make sure the input widths * match. * + * The case compare can be generated to handle ===/!==, or also + * to test guards in the case/casez/casex statements. + * * This pins are assigned as: * * 0 -- Output (always returns 0 or 1) * 1 -- Input - * 2 -- Input + * 2 -- Input (windcard input for EQX and EQZ variants) */ class NetCaseCmp : public NetNode { public: - explicit NetCaseCmp(NetScope*s, perm_string n, unsigned wid, bool eeq); + enum kind_t { + EEQ, // === + NEQ, // !== + XEQ, // casex guard tests + ZEQ // casez guard tests + }; + + public: + explicit NetCaseCmp(NetScope*s, perm_string n, unsigned wid, kind_t eeq); ~NetCaseCmp(); unsigned width() const; - // true if this is ===, false if this is !== - bool eeq() const; + // What kind of case compare? + inline kind_t kind() const { return kind_; } virtual void dump_node(ostream&, unsigned ind) const; virtual bool emit_node(struct target_t*) const; private: unsigned width_; - bool eeq_; + const kind_t kind_; }; +extern ostream& operator << (ostream&fd, NetCaseCmp::kind_t that); + /* NOTE: This class should be replaced with the NetLiteral class * below, that is more general in that it supports different types of * values. @@ -2868,10 +2881,10 @@ class NetCase : public NetProc { TYPE type() const; const NetExpr*expr() const { return expr_; } - unsigned nitems() const { return nitems_; } + inline unsigned nitems() const { return items_.size(); } - const NetExpr*expr(unsigned idx) const { return items_[idx].guard;} - const NetProc*stat(unsigned idx) const { return items_[idx].statement; } + 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 void nex_output(NexusSet&out); @@ -2892,16 +2905,20 @@ class NetCase : public NetProc { bool evaluate_function_real_(const LineInfo&loc, map&ctx) const; + bool synth_async_casez_(Design*des, NetScope*scope, + NexusSet&nex_map, NetBus&nex_out, + NetBus&accumulated_nex_out); + TYPE type_; struct Item { + inline Item() : guard(0), statement(0) { } NetExpr*guard; NetProc*statement; }; NetExpr* expr_; - unsigned nitems_; - Item*items_; + std::vectoritems_; }; /* diff --git a/synth2.cc b/synth2.cc index 8b5370b9a..104533b08 100644 --- a/synth2.cc +++ b/synth2.cc @@ -252,11 +252,14 @@ bool NetCase::synth_async(Design*des, NetScope*scope, NexusSet&nex_map, NetBus&nex_out, NetBus&accumulated_nex_out) { + if (type()==NetCase::EQZ) + return synth_async_casez_(des, scope, nex_map, nex_out, accumulated_nex_out); + /* Synthesize the select expression. */ NetNet*esig = expr_->synthesize(des, scope, expr_); unsigned sel_width = esig->vector_width(); - assert(sel_width > 0); + ivl_assert(*this, sel_width > 0); ivl_assert(*this, nex_map.size() == nex_out.pin_count()); @@ -288,7 +291,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope, mapstatement_map; NetProc*statement_default = 0; - for (unsigned item = 0 ; item < nitems_ ; item += 1) { + for (size_t item = 0 ; item < items_.size() ; item += 1) { if (items_[item].guard == 0) { statement_default = items_[item].statement; continue; @@ -417,6 +420,168 @@ bool NetCase::synth_async(Design*des, NetScope*scope, return true; } +/* + * casez statements are hard to implement as a single wide mux because + * the test doesn't really map to a select input. Instead, implement + * it as a chain of binary muxes. This gives the synthesizer my + * flexibility, and is more typically what is desired from a casez anyhow. + */ +bool NetCase::synth_async_casez_(Design*des, NetScope*scope, + NexusSet&nex_map, NetBus&nex_out, + NetBus&accumulated_nex_out) +{ + /* Synthesize the select expression. */ + NetNet*esig = expr_->synthesize(des, scope, expr_); + + unsigned sel_width = esig->vector_width(); + ivl_assert(*this, sel_width > 0); + + ivl_assert(*this, nex_map.size() == nex_out.pin_count()); + + vectormux_width (nex_out.pin_count()); + for (unsigned idx = 0 ; idx < nex_out.pin_count() ; idx += 1) { + mux_width[idx] = nex_map[idx].wid; + if (debug_synth2) { + cerr << get_fileline() << ": NetCase::synth_async_casez_: " + << "idx=" << idx + << ", mux_width[idx]=" << mux_width[idx] << endl; + } + } + + // The accumulated_nex_out is taken as the input for this + // statement. Since there are collection of statements that + // start at this same point, we save all these inputs and + // reuse them for each statement. + NetBus statement_input (scope, nex_out.pin_count()); + for (unsigned idx = 0 ; idx < nex_out.pin_count() ; idx += 1) { + connect(statement_input.pin(idx), accumulated_nex_out.pin(idx)); + } + + // Look for a default statement. + NetProc*statement_default = 0; + for (size_t item = 0 ; item < items_.size() ; item += 1) { + if (items_[item].guard != 0) + continue; + + ivl_assert(*this, statement_default==0); + statement_default = items_[item].statement; + } + + NetBus default_bus (scope, nex_out.pin_count()); + if (statement_default) { + bool flag = synth_async_block_substatement_(des, scope, nex_map, + accumulated_nex_out, + statement_default); + if (!flag) { + return false; + } + + for (unsigned idx = 0 ; idx < default_bus.pin_count() ; idx += 1) { + connect(default_bus.pin(idx), accumulated_nex_out.pin(idx)); + accumulated_nex_out.pin(idx).unlink(); + } + + if (debug_synth2) { + cerr << get_fileline() << ": NetCase::synth_async_casez_: " + << "synthesize default clause at " << statement_default->get_fileline() + << " is done." << endl; + } + } + + netvector_t*condit_type = new netvector_t(IVL_VT_LOGIC, 0, 0); + + NetCaseCmp::kind_t case_kind; + switch (type()) { + case NetCase::EQ: + case_kind = NetCaseCmp::EEQ; + break; + case NetCase::EQX: + case_kind = NetCaseCmp::XEQ; + break; + case NetCase::EQZ: + case_kind = NetCaseCmp::ZEQ; + break; + } + + // Process the items from last to first. We generate a + // true/false must, with the select being the comparison of + // the case select with the guard expression. The true input + // (data1) is the current statement, and the false input is + // the result of a later statement. + vectormux_prev (mux_width.size()); + for (size_t idx = 0 ; idx < items_.size() ; idx += 1) { + size_t item = items_.size()-idx-1; + if (items_[item].guard == 0) + continue; + + NetProc*stmt = items_[item].statement; + ivl_assert(*this, stmt); + + NetExpr*guard_expr = items_[item].guard; + NetNet*guard = guard_expr->synthesize(des, scope, guard_expr); + + NetCaseCmp*condit_dev = new NetCaseCmp(scope, scope->local_symbol(), + 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 + // NetCaseCmp statement. + connect(condit_dev->pin(2), esig->pin(0)); + connect(condit_dev->pin(1), guard->pin(0)); + + NetNet*condit = new NetNet(scope, scope->local_symbol(), + NetNet::TRI, condit_type); + condit->set_line(*this); + condit->local_flag(true); + connect(condit_dev->pin(0), condit->pin(0)); + + // Synthesize the guarded statement. + NetBus true_bus (scope, nex_out.pin_count()); + for (unsigned pin = 0 ; pin < nex_map.size() ; pin += 1) + connect(true_bus.pin(pin), statement_input.pin(pin)); + + synth_async_block_substatement_(des, scope, nex_map, true_bus, stmt); + + for (unsigned mdx = 0 ; mdx < mux_width.size() ; mdx += 1) { + NetMux*mux_cur = new NetMux(scope, scope->local_symbol(), + mux_width[mdx], 2, 1); + des->add_node(mux_cur); + mux_cur->set_line(*this); + connect(mux_cur->pin_Sel(), condit->pin(0)); + + connect(mux_cur->pin_Data(1), true_bus.pin(mdx)); + + // If there is a previous mux, then use that as the + // false clause input. Otherwise, use the default. + if (mux_prev[mdx]) { + connect(mux_cur->pin_Data(0), mux_prev[mdx]->pin_Result()); + } else { + connect(mux_cur->pin_Data(0), default_bus.pin(mdx)); + } + + // Make a NetNet for the result. + ivl_variable_type_t mux_data_type = IVL_VT_LOGIC; + netvector_t*tmp_vec = new netvector_t(mux_data_type, mux_width[mdx]-1, 0); + NetNet*tmp = new NetNet(scope, scope->local_symbol(), + NetNet::TRI, tmp_vec); + tmp->local_flag(true); + ivl_assert(*this, tmp->vector_width() != 0); + connect(mux_cur->pin_Result(), tmp->pin(0)); + + // This mux becomes the "false" input to the next mux. + mux_prev[mdx] = mux_cur; + } + } + + // Connect the last mux to the output. + for (size_t mdx = 0 ; mdx < mux_prev.size() ; mdx += 1) { + connect(mux_prev[mdx]->pin_Result(), nex_out.pin(mdx)); + } + + return true; +} + /* * A condit statement (if (cond) ... else ... ;) infers an A-B mux, * with the cond expression acting as a select input. If the cond diff --git a/t-dll-api.cc b/t-dll-api.cc index 4fcd623f8..cd12d2dfd 100644 --- a/t-dll-api.cc +++ b/t-dll-api.cc @@ -1164,6 +1164,8 @@ extern "C" ivl_nexus_t ivl_lpm_data(ivl_lpm_t net, unsigned idx) case IVL_LPM_ADD: case IVL_LPM_CMP_EEQ: case IVL_LPM_CMP_EQ: + case IVL_LPM_CMP_EQX: + case IVL_LPM_CMP_EQZ: case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GT: case IVL_LPM_CMP_NE: @@ -1309,6 +1311,8 @@ extern "C" ivl_nexus_t ivl_lpm_q(ivl_lpm_t net) case IVL_LPM_CMP_EQ: case IVL_LPM_CMP_NE: case IVL_LPM_CMP_EEQ: + case IVL_LPM_CMP_EQX: + case IVL_LPM_CMP_EQZ: case IVL_LPM_CMP_NEE: case IVL_LPM_DIVIDE: case IVL_LPM_MOD: @@ -1447,6 +1451,8 @@ extern "C" int ivl_lpm_signed(ivl_lpm_t net) case IVL_LPM_CAST_REAL: case IVL_LPM_CMP_EEQ: case IVL_LPM_CMP_EQ: + case IVL_LPM_CMP_EQX: + case IVL_LPM_CMP_EQZ: case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GT: case IVL_LPM_CMP_NE: @@ -1521,6 +1527,8 @@ extern "C" unsigned ivl_lpm_size(ivl_lpm_t net) case IVL_LPM_ADD: case IVL_LPM_CMP_EEQ: case IVL_LPM_CMP_EQ: + case IVL_LPM_CMP_EQX: + case IVL_LPM_CMP_EQZ: case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GT: case IVL_LPM_CMP_NE: diff --git a/t-dll.cc b/t-dll.cc index a068bb59b..6eff6ce08 100644 --- a/t-dll.cc +++ b/t-dll.cc @@ -1190,7 +1190,20 @@ bool dll_target::ureduce(const NetUReduce*net) void dll_target::net_case_cmp(const NetCaseCmp*net) { struct ivl_lpm_s*obj = new struct ivl_lpm_s; - obj->type = net->eeq()? IVL_LPM_CMP_EEQ : IVL_LPM_CMP_NEE; + switch (net->kind()) { + case NetCaseCmp::EEQ: + obj->type = IVL_LPM_CMP_EEQ; + break; + case NetCaseCmp::NEQ: + obj->type = IVL_LPM_CMP_NEE; + break; + case NetCaseCmp::XEQ: + obj->type = IVL_LPM_CMP_EQX; + break; + case NetCaseCmp::ZEQ: + obj->type = IVL_LPM_CMP_EQZ; + break; + } obj->name = net->name(); obj->scope = find_scope(des_, net->scope()); assert(obj->scope); diff --git a/tgt-sizer/scan_lpms.cc b/tgt-sizer/scan_lpms.cc index a5c6b5aae..18dcbb7d8 100644 --- a/tgt-sizer/scan_lpms.cc +++ b/tgt-sizer/scan_lpms.cc @@ -59,6 +59,15 @@ static void scan_lpms_equality(ivl_scope_t, ivl_lpm_t lpm, struct sizer_statisti stats.gate_count += 2*wid; } +static void scan_lpms_equality_wild(ivl_scope_t, ivl_lpm_t lpm, struct sizer_statistics&stats) +{ + unsigned wid = ivl_lpm_width(lpm); + + stats.equality_wc_count[wid] += 1; + + stats.gate_count += 2*wid; +} + /* * Count magnitude comparators as 2m gates. * Also keep a count of comparators by width, just out of curiosity. @@ -129,6 +138,11 @@ void scan_lpms(ivl_scope_t scope, struct sizer_statistics&stats) scan_lpms_equality(scope, lpm, stats); break; + case IVL_LPM_CMP_EQX: + case IVL_LPM_CMP_EQZ: + scan_lpms_equality_wild(scope, lpm, stats); + break; + case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GT: scan_lpms_magnitude(scope, lpm, stats); diff --git a/tgt-sizer/sizer.cc b/tgt-sizer/sizer.cc index a729e6f2b..8eabea097 100644 --- a/tgt-sizer/sizer.cc +++ b/tgt-sizer/sizer.cc @@ -164,6 +164,11 @@ static void show_stats(struct sizer_statistics&stats) fprintf(sizer_out, " EQUALITY[%u]: %u units\n", cur->first, cur->second); } + for (map::const_iterator cur = stats.equality_wc_count.begin() + ; cur != stats.equality_wc_count.end() ; ++ cur) { + fprintf(sizer_out, " EQUALITY_WC[%u]: %u units\n", cur->first, cur->second); + } + for (map::const_iterator cur = stats.magnitude_count.begin() ; cur != stats.magnitude_count.end() ; ++ cur) { fprintf(sizer_out, " MAGNITUDE[%u]: %u units\n", cur->first, cur->second); @@ -214,6 +219,10 @@ struct sizer_statistics& sizer_statistics::operator += (const sizer_statistics&t ; cur != that.equality_count.end() ; ++ cur) equality_count[cur->first] += cur->second; + for (map::const_iterator cur = that.equality_wc_count.begin() + ; cur != that.equality_wc_count.end() ; ++ cur) + equality_wc_count[cur->first] += cur->second; + for (map::const_iterator cur = that.magnitude_count.begin() ; cur != that.magnitude_count.end() ; ++ cur) magnitude_count[cur->first] += cur->second; diff --git a/tgt-sizer/sizer_priv.h b/tgt-sizer/sizer_priv.h index 85ca43cb9..721c34602 100644 --- a/tgt-sizer/sizer_priv.h +++ b/tgt-sizer/sizer_priv.h @@ -33,6 +33,8 @@ struct sizer_statistics { std::map adder_count; // count equality comparators std::map equality_count; + // count equality (with wildcard) comparators + std::map equality_wc_count; // Count magnitude comparators std::map magnitude_count; // Count mux's of various dimension diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index de786f3e2..b8a279c13 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -371,13 +371,31 @@ static void show_lpm_divide(ivl_lpm_t net) show_lpm_arithmetic_pins(net); } -/* IVL_LPM_CMP_EEQ/NEE +/* IVL_LPM_CMP_EEQ/EQX/EQZ/NEE * This LPM node supports two-input compare. The output width is * actually always 1, the lpm_width is the expected width of the inputs. */ static void show_lpm_cmp_eeq(ivl_lpm_t net) { - const char*str = (ivl_lpm_type(net) == IVL_LPM_CMP_EEQ)? "EEQ" : "NEE"; + const char*str; + switch (ivl_lpm_type(net)) { + case IVL_LPM_CMP_EEQ: + str = "EEQ"; + break; + case IVL_LPM_CMP_EQX: + str = "EQX"; + break; + case IVL_LPM_CMP_EQZ: + str = "EQZ"; + break; + case IVL_LPM_CMP_NEE: + str = "NEE"; + break; + default: + assert(0); + break; + } + unsigned width = ivl_lpm_width(net); fprintf(out, " LPM_CMP_%s %s: \n", str, @@ -934,6 +952,8 @@ static void show_lpm(ivl_lpm_t net) break; case IVL_LPM_CMP_EEQ: + case IVL_LPM_CMP_EQX: + case IVL_LPM_CMP_EQZ: case IVL_LPM_CMP_NEE: show_lpm_cmp_eeq(net); break; diff --git a/tgt-vvp/draw_net_input.c b/tgt-vvp/draw_net_input.c index 3ee73d36b..4a142f0e0 100644 --- a/tgt-vvp/draw_net_input.c +++ b/tgt-vvp/draw_net_input.c @@ -450,6 +450,8 @@ static char* draw_net_input_drive(ivl_nexus_t nex, ivl_nexus_ptr_t nptr) case IVL_LPM_CONCATZ: case IVL_LPM_CMP_EEQ: case IVL_LPM_CMP_EQ: + case IVL_LPM_CMP_EQX: + case IVL_LPM_CMP_EQZ: case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GT: case IVL_LPM_CMP_NE: diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 7a8632367..643316d23 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -1280,6 +1280,8 @@ static const char* draw_lpm_output_delay(ivl_lpm_t net, ivl_variable_type_t dt) switch (ivl_lpm_type(net)) { case IVL_LPM_CMP_EEQ: case IVL_LPM_CMP_EQ: + case IVL_LPM_CMP_EQX: + case IVL_LPM_CMP_EQZ: case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GT: case IVL_LPM_CMP_NE: @@ -1489,6 +1491,16 @@ static void draw_lpm_cmp(ivl_lpm_t net) type = "eq"; signed_string = ""; break; + case IVL_LPM_CMP_EQX: + assert(dtc != IVL_VT_REAL); + type = "eqx"; + signed_string = ""; + break; + case IVL_LPM_CMP_EQZ: + assert(dtc != IVL_VT_REAL); + type = "eqz"; + signed_string = ""; + break; case IVL_LPM_CMP_GE: if (dtc == IVL_VT_REAL) { type = "ge.r"; @@ -2060,6 +2072,8 @@ static void draw_lpm_in_scope(ivl_lpm_t net) case IVL_LPM_CMP_EEQ: case IVL_LPM_CMP_EQ: + case IVL_LPM_CMP_EQX: + case IVL_LPM_CMP_EQZ: case IVL_LPM_CMP_GE: case IVL_LPM_CMP_GT: case IVL_LPM_CMP_NE: diff --git a/vvp/arith.cc b/vvp/arith.cc index 7b23e3bd6..7fe9ebcef 100644 --- a/vvp/arith.cc +++ b/vvp/arith.cc @@ -670,6 +670,83 @@ void vvp_cmp_eq::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, net->send_vec4(res, 0); } +vvp_cmp_eqx::vvp_cmp_eqx(unsigned wid) +: vvp_arith_(wid) +{ +} + +/* + * Compare Vector a and Vector b. If in any bit position the a and b + * bits are known and different, then the result is 0. Otherwise, if + * there are X/Z bits anywhere in A or B, the result is X. Finally, + * the result is 1. + */ +void vvp_cmp_eqx::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, + vvp_context_t) +{ + dispatch_operand_(ptr, bit); + + if (op_a_.size() != op_b_.size()) { + cerr << "COMPARISON size mismatch. " + << "a=" << op_a_ << ", b=" << op_b_ << endl; + assert(0); + } + + vvp_vector4_t res (1); + res.set_bit(0, BIT4_1); + + 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; + if (b == BIT4_Z) + continue; + if (a != b) { + res.set_bit(0, BIT4_0); + break; + } + } + + vvp_net_t*net = ptr.ptr(); + net->send_vec4(res, 0); +} + +vvp_cmp_eqz::vvp_cmp_eqz(unsigned wid) +: vvp_arith_(wid) +{ +} + +void vvp_cmp_eqz::recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, + vvp_context_t) +{ + dispatch_operand_(ptr, bit); + + if (op_a_.size() != op_b_.size()) { + cerr << "COMPARISON size mismatch. " + << "a=" << op_a_ << ", b=" << op_b_ << endl; + assert(0); + } + + vvp_vector4_t res (1); + res.set_bit(0, BIT4_1); + + 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_Z) + continue; + if (a != b) { + res.set_bit(0, BIT4_0); + break; + } + } + + vvp_net_t*net = ptr.ptr(); + net->send_vec4(res, 0); +} vvp_cmp_ne::vvp_cmp_ne(unsigned wid) : vvp_arith_(wid) diff --git a/vvp/arith.h b/vvp/arith.h index bd1b99c5c..5f714e231 100644 --- a/vvp/arith.h +++ b/vvp/arith.h @@ -157,6 +157,24 @@ class vvp_cmp_eq : public vvp_arith_ { }; +class vvp_cmp_eqx : public vvp_arith_ { + + public: + explicit vvp_cmp_eqx(unsigned wid); + void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, + vvp_context_t); + +}; + +class vvp_cmp_eqz : public vvp_arith_ { + + public: + explicit vvp_cmp_eqz(unsigned wid); + void recv_vec4(vvp_net_ptr_t ptr, const vvp_vector4_t&bit, + vvp_context_t); + +}; + class vvp_cmp_ne : public vvp_arith_ { public: diff --git a/vvp/compile.cc b/vvp/compile.cc index f79b5b883..a8d33357e 100644 --- a/vvp/compile.cc +++ b/vvp/compile.cc @@ -1245,6 +1245,34 @@ void compile_cmp_eq(char*label, long wid, unsigned argc, struct symb_s*argv) make_arith(arith, label, argc, argv); } +void compile_cmp_eqx(char*label, long wid, unsigned argc, struct symb_s*argv) +{ + assert( wid > 0 ); + + if (argc != 2) { + fprintf(stderr, "%s .cmp/eqx has wrong number of symbols\n",label); + compile_errors += 1; + return; + } + + vvp_arith_ *arith = new vvp_cmp_eqx(wid); + make_arith(arith, label, argc, argv); +} + +void compile_cmp_eqz(char*label, long wid, unsigned argc, struct symb_s*argv) +{ + assert( wid > 0 ); + + if (argc != 2) { + fprintf(stderr, "%s .cmp/eqz has wrong number of symbols\n",label); + compile_errors += 1; + return; + } + + vvp_arith_ *arith = new vvp_cmp_eqz(wid); + make_arith(arith, label, argc, argv); +} + void compile_cmp_eq_r(char*label, unsigned argc, struct symb_s*argv) { if (argc != 2) { diff --git a/vvp/compile.h b/vvp/compile.h index 6685cc2d1..43ba3cb27 100644 --- a/vvp/compile.h +++ b/vvp/compile.h @@ -181,6 +181,10 @@ extern void compile_cmp_nee(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_cmp_eq(char*label, long width, unsigned argc, struct symb_s*argv); +extern void compile_cmp_eqx(char*label, long width, + unsigned argc, struct symb_s*argv); +extern void compile_cmp_eqz(char*label, long width, + unsigned argc, struct symb_s*argv); extern void compile_cmp_ne(char*label, long width, unsigned argc, struct symb_s*argv); extern void compile_cmp_ge(char*label, long width, bool signed_flag, diff --git a/vvp/lexor.lex b/vvp/lexor.lex index a2d8cbf8f..6e59154ab 100644 --- a/vvp/lexor.lex +++ b/vvp/lexor.lex @@ -134,6 +134,8 @@ static char* strdupnew(char const *str) ".cast/real.s" { return K_CAST_REAL_S; } ".class" { return K_CLASS; } ".cmp/eeq" { return K_CMP_EEQ; } +".cmp/eqx" { return K_CMP_EQX; } +".cmp/eqz" { return K_CMP_EQZ; } ".cmp/eq" { return K_CMP_EQ; } ".cmp/eq.r" { return K_CMP_EQ_R; } ".cmp/nee" { return K_CMP_NEE; } diff --git a/vvp/parse.y b/vvp/parse.y index 8fff1c223..04f241fe5 100644 --- a/vvp/parse.y +++ b/vvp/parse.y @@ -80,7 +80,8 @@ static struct __vpiModPath*modpath_dst = 0; %token K_ARRAY K_ARRAY_2U K_ARRAY_2S K_ARRAY_I 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_EQ_R K_CMP_NEE K_CMP_NE K_CMP_NE_R +%token K_CMP_EEQ K_CMP_EQ K_CMP_EQX K_CMP_EQZ +%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 %token K_ENUM2 K_ENUM2_S K_ENUM4 K_ENUM4_S K_EVENT K_EVENT_OR @@ -414,6 +415,16 @@ statement compile_cmp_eq($1, $3, obj.cnt, obj.vect); } + | T_LABEL K_CMP_EQX T_NUMBER ',' symbols ';' + { struct symbv_s obj = $5; + compile_cmp_eqx($1, $3, obj.cnt, obj.vect); + } + + | T_LABEL K_CMP_EQZ T_NUMBER ',' symbols ';' + { struct symbv_s obj = $5; + compile_cmp_eqz($1, $3, obj.cnt, obj.vect); + } + | T_LABEL K_CMP_EQ_R T_NUMBER ',' symbols ';' { struct symbv_s obj = $5; compile_cmp_eq_r($1, obj.cnt, obj.vect); From 6d2fa6e5792fbfa0142f60d4bba8d8d3a0a278ed Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Fri, 13 Jun 2014 18:22:24 -0700 Subject: [PATCH 062/245] case/x/z synthesis with constant case expression. If the case expression is constant, then the guards probably are not, and the synthesis should be handled differently. --- synth2.cc | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/synth2.cc b/synth2.cc index 104533b08..4d9e744b1 100644 --- a/synth2.cc +++ b/synth2.cc @@ -252,7 +252,14 @@ bool NetCase::synth_async(Design*des, NetScope*scope, NexusSet&nex_map, NetBus&nex_out, NetBus&accumulated_nex_out) { - if (type()==NetCase::EQZ) + if (type()==NetCase::EQZ || type()==NetCase::EQX) + return synth_async_casez_(des, scope, nex_map, nex_out, accumulated_nex_out); + + // Special case: If the case expression is constant, then this + // is a pattern where the guards are non-constant and tested + // against a constant case. Handle this as chained conditions + // instead. + if (dynamic_cast (expr_)) return synth_async_casez_(des, scope, nex_map, nex_out, accumulated_nex_out); /* Synthesize the select expression. */ @@ -298,7 +305,7 @@ bool NetCase::synth_async(Design*des, NetScope*scope, } NetEConst*ge = dynamic_cast(items_[item].guard); - assert(ge); + ivl_assert(*this, ge); verinum gval = ge->value(); unsigned sel_idx = gval.as_ulong(); From 9c79e321ae8fb160541bbe2e7dd62cd26a5775a1 Mon Sep 17 00:00:00 2001 From: Cary R Date: Sat, 14 Jun 2014 14:18:59 -0700 Subject: [PATCH 063/245] Spell, etc. fixes --- vpi/sys_random.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/vpi/sys_random.c b/vpi/sys_random.c index 31e05e244..78546b64f 100644 --- a/vpi/sys_random.c +++ b/vpi/sys_random.c @@ -552,7 +552,7 @@ static PLI_INT32 sys_random_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) return 0; } -/* From System Verilog */ +/* From SystemVerilog. */ static PLI_INT32 sys_urandom_range_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh = vpi_handle(vpiSysTfCall, 0); @@ -566,11 +566,11 @@ static PLI_INT32 sys_urandom_range_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) return 0; } - /* Check that there is at least one arguments. */ + /* Check that there is at least one argument. */ arg = vpi_scan(argv); /* This should never be zero. */ assert(arg); arg = vpi_scan(argv); - /* Is this a signle argument function call? */ + /* Is this a single argument function call? */ if (arg == 0) return 0; /* These functions takes at most two argument. */ @@ -585,7 +585,7 @@ static PLI_INT32 sys_urandom_range_compiletf(ICARUS_VPI_CONST PLI_BYTE8 *name) return 0; } -/* From System Verilog */ +/* From SystemVerilog. */ static unsigned long urandom(long *seed, unsigned long max, unsigned long min) { static long i_seed = 0; @@ -600,7 +600,7 @@ static unsigned long urandom(long *seed, unsigned long max, unsigned long min) return result; } -/* From System Verilog */ +/* From SystemVerilog. */ static PLI_INT32 sys_urandom_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh, argv, seed = 0; @@ -636,7 +636,7 @@ static PLI_INT32 sys_urandom_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) return 0; } -/* From System Verilog */ +/* From SystemVerilog. */ static PLI_INT32 sys_urandom_range_calltf(ICARUS_VPI_CONST PLI_BYTE8 *name) { vpiHandle callh, argv, maxval, minval; @@ -924,7 +924,7 @@ void sys_random_register() res = vpi_register_systf(&tf_data); vpip_make_systf_system_defined(res); - /* From System Verilog */ + /* From SystemVerilog. */ tf_data.type = vpiSysFunc; tf_data.sysfunctype = vpiSysFuncSized; tf_data.tfname = "$urandom"; @@ -935,7 +935,7 @@ void sys_random_register() res = vpi_register_systf(&tf_data); vpip_make_systf_system_defined(res); - /* From System Verilog */ + /* From SystemVerilog. */ tf_data.type = vpiSysFunc; tf_data.sysfunctype = vpiSysFuncSized; tf_data.tfname = "$urandom_range"; From 0f85bf0b9a18055314a760e32dd3528c350639f5 Mon Sep 17 00:00:00 2001 From: Stephen Williams Date: Sun, 15 Jun 2014 18:22:02 -0700 Subject: [PATCH 064/245] Basic DFF asynchronous set/reset synthesis support. --- netlist.h | 4 ++ synth2.cc | 120 ++++++++++++++++++++++++++------------------ tgt-stub/stub.c | 24 ++++++++- tgt-vvp/vvp_scope.c | 21 ++++++-- vvp/README.txt | 10 ++-- vvp/compile.h | 14 +++++- vvp/dff.cc | 119 ++++++++++++++++++++++++++++++++++++++----- vvp/dff.h | 26 ++++++++++ vvp/lexor.lex | 2 + vvp/parse.y | 14 ++++-- 10 files changed, 274 insertions(+), 80 deletions(-) diff --git a/netlist.h b/netlist.h index 87ea09ab7..7bc72221e 100644 --- a/netlist.h +++ b/netlist.h @@ -2557,6 +2557,7 @@ class NetProc : public virtual LineInfo { // the flipflop being generated. virtual bool synth_sync(Design*des, NetScope*scope, NetNet*ff_clock, NetNet*ff_ce, + NetNet*ff_aclr, NetNet*ff_aset, NexusSet&nex_map, NetBus&nex_out, const std::vector&events); @@ -2837,6 +2838,7 @@ class NetBlock : public NetProc { bool synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetNet*ff_ce, + NetNet*ff_aclr,NetNet*ff_aset, NexusSet&nex_map, NetBus&nex_out, const std::vector&events); @@ -2975,6 +2977,7 @@ class NetCondit : public NetProc { bool synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetNet*ff_ce, + NetNet*ff_aclr,NetNet*ff_aset, NexusSet&nex_map, NetBus&nex_out, const std::vector&events); @@ -3251,6 +3254,7 @@ class NetEvWait : public NetProc { virtual bool synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetNet*ff_ce, + NetNet*ff_aclr,NetNet*ff_aset, NexusSet&nex_map, NetBus&nex_out, const std::vector&events); diff --git a/synth2.cc b/synth2.cc index 685ed4e30..8277bf7f8 100644 --- a/synth2.cc +++ b/synth2.cc @@ -35,6 +35,7 @@ bool NetProc::synth_async(Design*, NetScope*, NexusSet&, NetBus&, NetBus&) bool NetProc::synth_sync(Design*des, NetScope*scope, NetNet* /* ff_clk */, NetNet* /* ff_ce */, + NetNet* /* ff_aclr*/, NetNet* /* ff_aset*/, NexusSet&nex_map, NetBus&nex_out, const vector&events) { @@ -1035,6 +1036,7 @@ bool NetProcTop::synth_async(Design*des) */ bool NetBlock::synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetNet*ff_ce, + NetNet*ff_aclr,NetNet*ff_aset, NexusSet&nex_map, NetBus&nex_out, const vector&events_in) { @@ -1064,6 +1066,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, ff_ce, + ff_aclr, ff_aset, tmp_set, tmp_out, events_in); flag = flag && ok_flag; @@ -1099,6 +1102,7 @@ bool NetBlock::synth_sync(Design*des, NetScope*scope, */ bool NetCondit::synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetNet*ff_ce, + NetNet*ff_aclr,NetNet*ff_aset, NexusSet&nex_map, NetBus&nex_out, const vector&events_in) { @@ -1118,65 +1122,71 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, if (! expr_input->contains(pin_set)) continue; - cerr << get_fileline() << ": sorry: " - << "Forgot how to implement asynchronous set/reset." << endl; - return false; -#if 0 - /* Ah, this edge is in the sensitivity list for the - expression, so we have an asynchronous - input. Synthesize the set/reset input expression. */ - - NetNet*rst = expr_->synthesize(des); - assert(rst->pin_count() == 1); + // Synthesize the set/reset input expression. + NetNet*rst = expr_->synthesize(des, scope, expr_); + ivl_assert(*this, rst->pin_count() == 1); /* XXXX I really should find a way to check that the edge used on the reset input is correct. This would involve interpreting the expression that is fed by the reset expression. */ - //assert(ev->edge() == NetEvProbe::POSEDGE); + ivl_assert(*this, ev->edge() == NetEvProbe::POSEDGE); - /* Synthesize the true clause to figure out what - kind of set/reset we have. */ - NetNet*asig = new NetNet(scope, scope->local_symbol(), - NetNet::WIRE, nex_map->pin_count()); - asig->local_flag(true); + // Synthesize the true clause to figure out what kind of + // set/reset we have. This should synthesize down to a + // constant. If not, we have an asynchronous LOAD, a + // very different beast. + ivl_assert(*this, if_); + bool flag; + NetBus tmp_out(scope, nex_out.pin_count()); + NetBus accumulated_tmp_out(scope, nex_out.pin_count()); + flag = if_->synth_async(des, scope, nex_map, tmp_out, accumulated_tmp_out); + ivl_assert(*this, flag); - assert(if_ != 0); - bool flag = if_->synth_async(des, scope, nex_map, asig); + ivl_assert(*this, tmp_out.pin_count()==1); + Nexus*rst_nex = tmp_out.pin(0).nexus(); - assert(asig->pin_count() == ff->width()); + vector rst_mask = rst_nex->driven_mask(); + cerr << get_fileline() << ": NetCondit::synth_sync: " + << "rst_mask.size()==" << rst_mask.size() + << ", rst_nex->vector_width()=" << rst_nex->vector_width() + << endl; - /* Collect the set/reset value into a verinum. If - this turns out to be entirely 0 values, then - use the Aclr input. Otherwise, use the Aset - input and save the set value. */ - verinum tmp (verinum::V0, ff->width()); - for (unsigned bit = 0 ; bit < ff->width() ; bit += 1) { - - assert(asig->pin(bit).nexus()->drivers_constant()); - tmp.set(bit, asig->pin(bit).nexus()->driven_value()); + ivl_assert(*this, rst_mask.size()==1); + if (rst_mask[0]==false) { + cerr << get_fileline() << ": sorry: " + << "Asynchronous LOAD not implemented." << endl; + return false; } - assert(tmp.is_defined()); - if (tmp.is_zero()) { - connect(ff->pin_Aclr(), rst->pin(0)); + verinum rst_drv = rst_nex->driven_vector(); + ivl_assert(*this, rst_drv.len()==1); + + if (rst_drv[0]==verinum::V0) { + ivl_assert(*this, ff_aclr && ff_aclr->pin_count()==1); + // Don't yet support multiple asynchronous reset inputs. + ivl_assert(*this, ! ff_aclr->pin(0).is_linked()); + + ivl_assert(*this, rst->pin_count()==1); + connect(ff_aclr->pin(0), rst->pin(0)); + + } else if (rst_drv[0]==verinum::V1) { + ivl_assert(*this, ff_aset && ff_aset->pin_count()==1); + // Don't yet support multiple asynchronous set inputs. + ivl_assert(*this, ! ff_aset->pin(0).is_linked()); + + ivl_assert(*this, rst->pin_count()==1); + connect(ff_aset->pin(0), rst->pin(0)); } else { - connect(ff->pin_Aset(), rst->pin(0)); - ff->aset_value(tmp); + cerr << get_fileline() << ": sorry: " + << "Forgot how to implement asynchronous scramble (set to x/z)." << endl; + return false; } - delete asig; - delete expr_input; - - assert(events_in.count() == 1); - assert(else_ != 0); - flag = else_->synth_sync(des, scope, ff, nex_map, - nex_out, svector(0)) - && flag; - DEBUG_SYNTH2_EXIT("NetCondit",flag) - return flag; -#endif + return else_->synth_sync(des, scope, ff_clk, ff_ce, + ff_aclr, ff_aset, + nex_map, nex_out, vector(0)); } delete expr_input; @@ -1302,13 +1312,14 @@ bool NetCondit::synth_sync(Design*des, NetScope*scope, connect(ff_ce->pin(0), ce->pin(0)); } - bool flag = if_->synth_sync(des, scope, ff_clk, ff_ce, nex_map, nex_out, events_in); + bool flag = if_->synth_sync(des, scope, ff_clk, ff_ce, ff_aclr, ff_aset, nex_map, nex_out, events_in); return flag; } bool NetEvWait::synth_sync(Design*des, NetScope*scope, NetNet*ff_clk, NetNet*ff_ce, + NetNet*ff_aclr,NetNet*ff_aset, NexusSet&nex_map, NetBus&nex_out, const vector&events_in) { @@ -1390,6 +1401,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, nex_map, nex_out, events); return flag; @@ -1424,6 +1436,14 @@ bool NetProcTop::synth_sync(Design*des) NetNet::TRI, &netvector_t::scalar_logic); ce->local_flag(true); + NetNet*aclr = new NetNet(scope(), scope()->local_symbol(), + NetNet::TRI, &netvector_t::scalar_logic); + aclr->local_flag(true); + + NetNet*aset = new NetNet(scope(), scope()->local_symbol(), + NetNet::TRI, &netvector_t::scalar_logic); + aset->local_flag(true); + NetBus nex_d (scope(), nex_set.size()); NetBus nex_q (scope(), nex_set.size()); @@ -1438,7 +1458,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, + bool flag = statement_->synth_sync(des, scope(), clock, ce, aclr, aset, nex_set, nex_d, vector()); if (! flag) { @@ -1473,11 +1493,11 @@ bool NetProcTop::synth_sync(Design*des) connect(clock->pin(0), ff2->pin_Clock()); if (ce->is_linked()) connect(ce->pin(0), ff2->pin_Enable()); + if (aclr->is_linked()) + connect(aclr->pin(0), ff2->pin_Aclr()); + if (aset->is_linked()) + connect(aset->pin(0), ff2->pin_Aset()); #if 0 - if (ff->pin_Aset().is_linked()) - connect(ff->pin_Aset(), ff2->pin_Aset()); - if (ff->pin_Aclr().is_linked()) - connect(ff->pin_Aclr(), ff2->pin_Aclr()); if (ff->pin_Sset().is_linked()) connect(ff->pin_Sset(), ff2->pin_Sset()); if (ff->pin_Sclr().is_linked()) diff --git a/tgt-stub/stub.c b/tgt-stub/stub.c index b8a279c13..d3b932a41 100644 --- a/tgt-stub/stub.c +++ b/tgt-stub/stub.c @@ -517,8 +517,28 @@ static void show_lpm_ff(ivl_lpm_t net) } } + if (ivl_lpm_async_clr(net)) { + nex = ivl_lpm_async_clr(net); + fprintf(out, " Aclr: %p\n", nex); + if (width_of_nexus(nex) != 1) { + fprintf(out, " Aclr: ERROR: Nexus width is %u\n", + width_of_nexus(nex)); + stub_errors += 1; + } + } + + if (ivl_lpm_async_set(net)) { + nex = ivl_lpm_async_set(net); + fprintf(out, " Aset: %p\n", nex); + if (width_of_nexus(nex) != 1) { + fprintf(out, " Aset: ERROR: Nexus width is %u\n", + width_of_nexus(nex)); + stub_errors += 1; + } + } + nex = ivl_lpm_data(net,0); - fprintf(out, " D: %p\n", nex); + fprintf(out, " D: %p\n", nex); if (width_of_nexus(nex) != width) { fprintf(out, " D: ERROR: Nexus width is %u\n", width_of_nexus(nex)); @@ -526,7 +546,7 @@ static void show_lpm_ff(ivl_lpm_t net) } nex = ivl_lpm_q(net); - fprintf(out, " Q: %p\n", nex); + fprintf(out, " Q: %p\n", nex); if (width_of_nexus(nex) != width) { fprintf(out, " Q: ERROR: Nexus width is %u\n", width_of_nexus(nex)); diff --git a/tgt-vvp/vvp_scope.c b/tgt-vvp/vvp_scope.c index 14a3603e6..7cbadf913 100644 --- a/tgt-vvp/vvp_scope.c +++ b/tgt-vvp/vvp_scope.c @@ -1724,10 +1724,16 @@ static void draw_lpm_ff(ivl_lpm_t net) * generator in V0.10 and later for how this might be done. */ assert(ivl_lpm_sync_clr(net) == 0); assert(ivl_lpm_sync_set(net) == 0); - assert(ivl_lpm_async_clr(net) == 0); - assert(ivl_lpm_async_set(net) == 0); - fprintf(vvp_out, "L_%p .dff ", net); + if (ivl_lpm_async_clr(net)) { + assert(! ivl_lpm_async_set(net)); + fprintf(vvp_out, "L_%p .dff/aclr ", net); + } else if (ivl_lpm_async_set(net)) { + assert(! ivl_lpm_async_clr(net)); + fprintf(vvp_out, "L_%p .dff/aset ", net); + } else { + fprintf(vvp_out, "L_%p .dff ", net); + } nex = ivl_lpm_data(net,0); assert(nex); @@ -1747,8 +1753,13 @@ static void draw_lpm_ff(ivl_lpm_t net) fprintf(vvp_out, ", C4<1>"); } - /* Stub asynchronous input for now. */ - fprintf(vvp_out, ", C4"); + if ( (nex = ivl_lpm_async_clr(net)) ) { + fprintf(vvp_out, ", %s", draw_net_input(nex)); + } + + if ( (nex = ivl_lpm_async_set(net)) ) { + fprintf(vvp_out, ", %s", draw_net_input(nex)); + } fprintf(vvp_out, ";\n"); } diff --git a/vvp/README.txt b/vvp/README.txt index 0905425e2..c1a9c0409 100644 --- a/vvp/README.txt +++ b/vvp/README.txt @@ -192,16 +192,18 @@ 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: -