From 4bd91fbb11e60bc30bd5164d97d2577360d1fdc0 Mon Sep 17 00:00:00 2001 From: Akash Levy Date: Wed, 30 Apr 2025 08:06:59 -0700 Subject: [PATCH 01/74] Add `muldiv_c` peepopt pass --- Makefile | 1 + passes/opt/Makefile.inc | 1 + passes/opt/peepopt.cc | 11 + passes/opt/peepopt_muldiv_c.pmg | 125 ++++++++++++ tests/peepopt/.gitignore | 1 + tests/peepopt/muldiv_c.ys | 343 ++++++++++++++++++++++++++++++++ tests/peepopt/run-test.sh | 6 + 7 files changed, 488 insertions(+) create mode 100644 passes/opt/peepopt_muldiv_c.pmg create mode 100644 tests/peepopt/.gitignore create mode 100644 tests/peepopt/muldiv_c.ys create mode 100644 tests/peepopt/run-test.sh diff --git a/Makefile b/Makefile index 393408603..4933b6b18 100644 --- a/Makefile +++ b/Makefile @@ -888,6 +888,7 @@ SH_TEST_DIRS += tests/bram SH_TEST_DIRS += tests/svinterfaces SH_TEST_DIRS += tests/xprop SH_TEST_DIRS += tests/select +SH_TEST_DIRS += tests/peepopt SH_TEST_DIRS += tests/proc SH_TEST_DIRS += tests/blif SH_TEST_DIRS += tests/arch diff --git a/passes/opt/Makefile.inc b/passes/opt/Makefile.inc index b796535e3..08d8191c7 100644 --- a/passes/opt/Makefile.inc +++ b/passes/opt/Makefile.inc @@ -32,6 +32,7 @@ PEEPOPT_PATTERN = passes/opt/peepopt_shiftmul_right.pmg PEEPOPT_PATTERN += passes/opt/peepopt_shiftmul_left.pmg PEEPOPT_PATTERN += passes/opt/peepopt_shiftadd.pmg PEEPOPT_PATTERN += passes/opt/peepopt_muldiv.pmg +PEEPOPT_PATTERN += passes/opt/peepopt_muldiv_c.pmg PEEPOPT_PATTERN += passes/opt/peepopt_formal_clockgateff.pmg passes/opt/peepopt_pm.h: passes/pmgen/pmgen.py $(PEEPOPT_PATTERN) diff --git a/passes/opt/peepopt.cc b/passes/opt/peepopt.cc index faacfb304..fa7cf74a0 100644 --- a/passes/opt/peepopt.cc +++ b/passes/opt/peepopt.cc @@ -29,6 +29,14 @@ bool did_something; // scratchpad configurations for pmgen int shiftadd_max_ratio; +// Helper function, removes LSB 0s +SigSpec remove_bottom_padding(SigSpec sig) +{ + int i = 0; + for (; i < sig.size() - 1 && sig[i] == State::S0; i++); + return sig.extract(i, sig.size() - i); +} + #include "passes/opt/peepopt_pm.h" struct PeepoptPass : public Pass { @@ -45,6 +53,8 @@ struct PeepoptPass : public Pass { log("\n"); log(" * muldiv - Replace (A*B)/B with A\n"); log("\n"); + log(" * muldiv_c - Replace (A*B)/C with A*(B/C) when C is a const divisible by B.\n"); + log("\n"); log(" * shiftmul - Replace A>>(B*C) with A'>>(B<div into const->mul when b and c are divisible constants: +// y = (a * b_const) / c_const ===> a * eval(b_const / c_const) +// + +state a b_const mul_y + +match mul + // Select multiplier + select mul->type == $mul +endmatch + +code a b_const mul_y + // Get multiplier signals + a = port(mul, \A); + b_const = port(mul, \B); + mul_y = port(mul, \Y); + + // Fanout of each multiplier Y bit should be 1 (no bit-split) + if (nusers(mul_y) != 2) + reject; + + // A and B can be interchanged + branch; + std::swap(a, b_const); +endcode + +match div + // Select div of form (a * b_const) / c_const + select div->type == $div + + // Check that b_const and c_const is constant + filter b_const.is_fully_const() + filter port(div, \B).is_fully_const() + index remove_bottom_padding(port(div, \A)) === mul_y +endmatch + +code + // Get div signals + SigSpec div_a = port(div, \A); + SigSpec c_const = port(div, \B); + SigSpec div_y = port(div, \Y); + + // Get offset of multiplier result chunk in divider + int offset = GetSize(div_a) - GetSize(mul_y); + + // Get properties and values of b_const and c_const + // b_const may be coming from the A port + // But it is an RTLIL invariant that A_SIGNED equals B_SIGNED + bool b_const_signed = mul->getParam(ID::B_SIGNED).as_bool(); + bool c_const_signed = div->getParam(ID::B_SIGNED).as_bool(); + int b_const_int = b_const.as_int(b_const_signed); + int c_const_int = c_const.as_int(c_const_signed); + int b_const_int_shifted = b_const_int << offset; + + // Helper lambdas for two's complement math + auto sign2sComplement = [](auto value, int numBits) { + if (value & (1 << (numBits - 1))) { + return -1; + } else { + return 1; + } + }; + auto twosComplement = [](auto value, int numBits) { + if (value & (1 << (numBits - 1))) { + return (~value) + 1; // invert bits before adding 1 + } else { + return value; + } + }; + + // Two's complement conversion + if (b_const_signed) + b_const_int = sign2sComplement(b_const_int, GetSize(b_const)) * twosComplement(b_const_int, GetSize(b_const)); + if (c_const_signed) + c_const_int = sign2sComplement(c_const_int, GetSize(c_const)) * twosComplement(c_const_int, GetSize(c_const)); + // Calculate the constant and compress the width to fit the value + Const const_ratio; + Const b_const_actual; + // Avoid division by zero + if (c_const_int == 0) + reject; + b_const_actual = b_const_int_shifted; + b_const_actual.compress(b_const_signed); + + const_ratio = b_const_int_shifted / c_const_int; + const_ratio.compress(b_const_signed | c_const_signed); + + // Integer values should be lesser than 32 bits + // This is because we are using C++ types, and int is 32 bits + // FIXME: use long long or BigInteger to make pass work with >32 bits + if (GetSize(mul->getParam(ID::B_WIDTH)) > 32) + reject; + if (GetSize(b_const) > 32) + reject; + if (GetSize(c_const) + offset > 32) + reject; + + // Check for potential multiplier overflow + if (GetSize(b_const_actual) + GetSize(a) > GetSize(mul_y)) + reject; + + // Check that there are only zeros before offset + if (offset < 0 || !div_a.extract(0, offset).is_fully_zero()) + reject; + + // Check that b is divisible by c + if (b_const_int_shifted % c_const_int != 0) + reject; + + // Rewire to only keep multiplier + mul->setPort(\A, a); + mul->setPort(\B, const_ratio); + mul->setPort(\Y, div_y); + + // Remove divider + autoremove(div); + + // Log, fixup, accept + log("muldiv_const pattern in %s: mul=%s, div=%s\n", log_id(module), log_id(mul), log_id(div)); + mul->fixup_parameters(); + accept; +endcode diff --git a/tests/peepopt/.gitignore b/tests/peepopt/.gitignore new file mode 100644 index 000000000..50e13221d --- /dev/null +++ b/tests/peepopt/.gitignore @@ -0,0 +1 @@ +/*.log diff --git a/tests/peepopt/muldiv_c.ys b/tests/peepopt/muldiv_c.ys new file mode 100644 index 000000000..62777caab --- /dev/null +++ b/tests/peepopt/muldiv_c.ys @@ -0,0 +1,343 @@ +log -header "Test simple positive case" +log -push +design -reset +read_verilog < Date: Mon, 5 May 2025 13:12:08 +0200 Subject: [PATCH 02/74] driver: add --no-version to suppress writing Yosys version in command outputs --- backends/aiger/aiger.cc | 4 ++-- backends/aiger/xaiger.cc | 3 ++- backends/blif/blif.cc | 3 ++- backends/edif/edif.cc | 4 +++- backends/json/json.cc | 3 ++- backends/rtlil/rtlil_backend.cc | 4 +++- backends/smt2/smtio.py | 1 + backends/verilog/verilog_backend.cc | 4 +++- kernel/driver.cc | 2 ++ kernel/yosys.cc | 1 + kernel/yosys_common.h | 1 + passes/cmds/internal_stats.cc | 3 ++- passes/cmds/stat.cc | 3 ++- passes/sat/sat.cc | 8 +++++--- 14 files changed, 31 insertions(+), 13 deletions(-) diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index f2cb5d9bc..2b10f7082 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -662,8 +662,8 @@ struct AigerWriter f << std::endl; } } - - f << stringf("c\nGenerated by %s\n", yosys_version_str); + if (yosys_write_versions) + f << stringf("c\nGenerated by %s\n", yosys_version_str); } void write_map(std::ostream &f, bool verbose_map, bool no_startoffset) diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index baf504ba2..200ae1a3b 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -671,7 +671,8 @@ struct XAigerWriter //f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); //f.write(buffer_str.data(), buffer_str.size()); - f << stringf("Generated by %s\n", yosys_version_str); + if (yosys_write_versions) + f << stringf("Generated by %s\n", yosys_version_str); design->scratchpad_set_int("write_xaiger.num_ands", and_map.size()); design->scratchpad_set_int("write_xaiger.num_wires", aig_map.size()); diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index 049a3c680..01507c115 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -649,7 +649,8 @@ struct BlifBackend : public Backend { if (module->get_bool_attribute(ID::top)) top_module_name = module->name.str(); - *f << stringf("# Generated by %s\n", yosys_version_str); + if (yosys_write_versions) + *f << stringf("# Generated by %s\n", yosys_version_str); std::vector mod_list; diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index d751a5996..1b67d0b4d 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -231,7 +231,9 @@ struct EdifBackend : public Backend { *f << stringf(" (edifVersion 2 0 0)\n"); *f << stringf(" (edifLevel 0)\n"); *f << stringf(" (keywordMap (keywordLevel 0))\n"); - *f << stringf(" (comment \"Generated by %s\")\n", yosys_version_str); + + if (yosys_write_versions) + *f << stringf(" (comment \"Generated by %s\")\n", yosys_version_str); *f << stringf(" (external LIB\n"); *f << stringf(" (edifLevel 0)\n"); diff --git a/backends/json/json.cc b/backends/json/json.cc index 749fe1fc3..7108f5f77 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -291,7 +291,8 @@ struct JsonWriter design->sort(); f << stringf("{\n"); - f << stringf(" \"creator\": %s,\n", get_string(yosys_version_str).c_str()); + if (yosys_write_versions) + f << stringf(" \"creator\": %s,\n", get_string(yosys_version_str).c_str()); f << stringf(" \"modules\": {\n"); vector modules = use_selection ? design->selected_modules() : design->modules(); bool first_module = true; diff --git a/backends/rtlil/rtlil_backend.cc b/backends/rtlil/rtlil_backend.cc index ae60ee6c7..7a657d9e5 100644 --- a/backends/rtlil/rtlil_backend.cc +++ b/backends/rtlil/rtlil_backend.cc @@ -459,7 +459,9 @@ struct RTLILBackend : public Backend { design->sort(); log("Output filename: %s\n", filename.c_str()); - *f << stringf("# Generated by %s\n", yosys_version_str); + + if (yosys_write_versions) + *f << stringf("# Generated by %s\n", yosys_version_str); RTLIL_BACKEND::dump_design(*f, design, selected, true, false); } } RTLILBackend; diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index 2bc7daddc..ab25eee72 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -1289,6 +1289,7 @@ class MkVcd: assert t >= self.t if t != self.t: if self.t == -1: + # TODO if (yosys_write_versions) equivalent? print("$version Generated by Yosys-SMTBMC $end", file=self.f) print("$timescale 1ns $end", file=self.f) print("$var integer 32 t smt_step $end", file=self.f) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 2bc6ff3b8..98a8cc30d 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -2596,7 +2596,9 @@ struct VerilogBackend : public Backend { design->sort(); - *f << stringf("/* Generated by %s */\n", yosys_version_str); + if (yosys_write_versions) + *f << stringf("/* Generated by %s */\n", yosys_version_str); + for (auto module : design->modules()) { if (module->get_blackbox_attribute() != blackboxes) continue; diff --git a/kernel/driver.cc b/kernel/driver.cc index b7f0268db..e3a4cfa3e 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -252,6 +252,7 @@ int main(int argc, char **argv) options.add_options("logging") ("Q", "suppress printing of banner (copyright, disclaimer, version)") ("T", "suppress printing of footer (log hash, version, timing statistics)") + ("no-version", "suppress writing Yosys version in command outputs") ("q,quiet", "quiet operation. Only write warnings and error messages to console. " \ "Use this option twice to also quiet warning messages") ("v,verbose", "print log headers up to to the console. " \ @@ -318,6 +319,7 @@ int main(int argc, char **argv) if (result.count("A")) call_abort = true; if (result.count("Q")) print_banner = false; if (result.count("T")) print_stats = false; + if (result.count("no-version")) yosys_write_versions = false; if (result.count("V")) { std::cout << yosys_version_str << std::endl; exit(0); diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 9b0bc92ce..5b89fc9b1 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -81,6 +81,7 @@ YOSYS_NAMESPACE_BEGIN int autoidx = 1; int yosys_xtrace = 0; +bool yosys_write_versions = true; RTLIL::Design *yosys_design = NULL; CellTypes yosys_celltypes; diff --git a/kernel/yosys_common.h b/kernel/yosys_common.h index 6fadf788f..16215fb76 100644 --- a/kernel/yosys_common.h +++ b/kernel/yosys_common.h @@ -274,6 +274,7 @@ inline int GetSize(RTLIL::Wire *wire); extern int autoidx; extern int yosys_xtrace; +extern bool yosys_write_versions; RTLIL::IdString new_id(std::string file, int line, std::string func); RTLIL::IdString new_id_suffix(std::string file, int line, std::string func, std::string suffix); diff --git a/passes/cmds/internal_stats.cc b/passes/cmds/internal_stats.cc index cc35dcc5f..bdf556e81 100644 --- a/passes/cmds/internal_stats.cc +++ b/passes/cmds/internal_stats.cc @@ -99,7 +99,8 @@ struct InternalStatsPass : public Pass { if (json_mode) { log("{\n"); - log(" \"creator\": %s,\n", json11::Json(yosys_version_str).dump().c_str()); + if (yosys_write_versions) + log(" \"creator\": %s,\n", json11::Json(yosys_version_str).dump().c_str()); std::stringstream invocation; std::copy(args.begin(), args.end(), std::ostream_iterator(invocation, " ")); log(" \"invocation\": %s,\n", json11::Json(invocation.str()).dump().c_str()); diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 63926c6e7..4c1331d35 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -444,7 +444,8 @@ struct StatPass : public Pass { if (json_mode) { log("{\n"); - log(" \"creator\": %s,\n", json11::Json(yosys_version_str).dump().c_str()); + if (yosys_write_versions) + log(" \"creator\": %s,\n", json11::Json(yosys_version_str).dump().c_str()); std::stringstream invocation; std::copy(args.begin(), args.end(), std::ostream_iterator(invocation, " ")); log(" \"invocation\": %s,\n", json11::Json(invocation.str()).dump().c_str()); diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index 53f009e40..46cc00981 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -690,9 +690,11 @@ struct SatHelper fprintf(f, "$date\n"); fprintf(f, " %s\n", stime); fprintf(f, "$end\n"); - fprintf(f, "$version\n"); - fprintf(f, " Generated by %s\n", yosys_version_str); - fprintf(f, "$end\n"); + if (yosys_write_versions) { + fprintf(f, "$version\n"); + fprintf(f, " Generated by %s\n", yosys_version_str); + fprintf(f, "$end\n"); + } fprintf(f, "$comment\n"); fprintf(f, " Generated from SAT problem in module %s (declared at %s)\n", module->name.c_str(), module_fname.c_str()); From 7c89355b70c07536cdc8174ac3ddfe64bdc34bec Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Tue, 6 May 2025 09:57:34 +1200 Subject: [PATCH 03/74] cutpoint: Re-add whole module optimization Also add a test script for it. --- passes/sat/cutpoint.cc | 14 +++++++++ tests/various/cutpoint_whole.ys | 50 +++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 tests/various/cutpoint_whole.ys diff --git a/passes/sat/cutpoint.cc b/passes/sat/cutpoint.cc index 7f0dc2fcf..dcd399a57 100644 --- a/passes/sat/cutpoint.cc +++ b/passes/sat/cutpoint.cc @@ -86,6 +86,20 @@ struct CutpointPass : public Pass { for (auto module : design->all_selected_modules()) { + if (module->is_selected_whole()) { + log("Making all outputs of module %s cut points, removing module contents.\n", log_id(module)); + module->new_connections(std::vector()); + for (auto cell : vector(module->cells())) + module->remove(cell); + vector output_wires; + for (auto wire : module->wires()) + if (wire->port_output) + output_wires.push_back(wire); + for (auto wire : output_wires) + module->connect(wire, flag_undef ? Const(State::Sx, GetSize(wire)) : module->Anyseq(NEW_ID, GetSize(wire))); + continue; + } + SigMap sigmap(module); pool cutpoint_bits; diff --git a/tests/various/cutpoint_whole.ys b/tests/various/cutpoint_whole.ys new file mode 100644 index 000000000..174add205 --- /dev/null +++ b/tests/various/cutpoint_whole.ys @@ -0,0 +1,50 @@ +read_verilog << EOT +module top(input a, b, output o); + wire c, d, e; + bb bb1 (.a (a), .b (b), .o (c)); + sub_mod sub_inst (.a (a), .b (b), .o (e)); + some_mod some_inst (.a (c), .b (d), .c (e), .o (o)); +endmodule + +(* blackbox *) +module bb #( parameter SOME_PARAM=0 ) (input a, b, output o); +endmodule + +module sub_mod(input a, b, output o); + bb bb2 (.a (a), .b (b), .o (o)); +endmodule + +module some_mod(input a, b, c, output o); +assign o = a & (b | c); +endmodule +EOT + +hierarchy -top top +design -stash hier + +# removing cell +design -load hier +logger -expect log "Removing cell .*, making all cell outputs cutpoints" 1 +cutpoint sub_mod/bb2 +logger -check-expected +logger -werror "Removing cell .*, making all cell outputs cutpoints" + +# removing wires +design -load hier +logger -expect log "Making wire .* a cutpoint" 1 +cutpoint top/c +logger -check-expected +logger -werror "Making wire .* a cutpoint" + +# removing output wires +design -load hier +logger -expect log "Making output wire .* a cutpoint" 1 +cutpoint sub_mod/o +logger -check-expected +logger -werror "Making output wire .* a cutpoint" + +# whole module optimization, doesn't do any of the previous +design -load hier +logger -expect log "Making all outputs of module .* cut points, removing module contents" 1 +cutpoint sub_mod +logger -check-expected From 93780bb8691ebaf81fa5320b93ffedbfdaf406d8 Mon Sep 17 00:00:00 2001 From: mikesinouye Date: Tue, 6 May 2025 09:57:03 -0700 Subject: [PATCH 04/74] Add to haslib.h which uses std::optional --- kernel/hashlib.h | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel/hashlib.h b/kernel/hashlib.h index 6e3eb32a4..4144d701d 100644 --- a/kernel/hashlib.h +++ b/kernel/hashlib.h @@ -14,6 +14,7 @@ #include #include +#include #include #include #include From 90a2c92370e313d5b1443c925fa762381f78e5a6 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 7 May 2025 11:34:23 +0200 Subject: [PATCH 05/74] driver: allow --no-version still write things like Generated by Yosys --- backends/aiger/aiger.cc | 5 ++--- backends/aiger/xaiger.cc | 3 +-- backends/blif/blif.cc | 3 +-- backends/btor/btor.cc | 4 ++-- backends/edif/edif.cc | 3 +-- backends/jny/jny.cc | 2 +- backends/json/json.cc | 3 +-- backends/rtlil/rtlil_backend.cc | 3 +-- backends/smt2/smt2.cc | 2 +- backends/smt2/smtio.py | 1 - backends/smv/smv.cc | 4 ++-- backends/spice/spice.cc | 2 +- backends/verilog/verilog_backend.cc | 3 +-- kernel/driver.cc | 6 +++--- kernel/register.cc | 2 +- kernel/yosys.cc | 9 ++++++++- kernel/yosys.h | 1 + passes/cmds/internal_stats.cc | 3 +-- passes/cmds/stat.cc | 3 +-- passes/sat/sat.cc | 8 +++----- passes/sat/sim.cc | 6 +++--- 21 files changed, 36 insertions(+), 40 deletions(-) diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index 2b10f7082..617d7d85f 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -662,8 +662,7 @@ struct AigerWriter f << std::endl; } } - if (yosys_write_versions) - f << stringf("c\nGenerated by %s\n", yosys_version_str); + f << stringf("c\nGenerated by %s\n", yosys_maybe_version()); } void write_map(std::ostream &f, bool verbose_map, bool no_startoffset) @@ -746,7 +745,7 @@ struct AigerWriter { json.begin_object(); json.entry("version", "Yosys Witness Aiger map"); - json.entry("gennerator", yosys_version_str); + json.entry("gennerator", yosys_maybe_version()); json.entry("latch_count", aig_l); json.entry("input_count", aig_i); diff --git a/backends/aiger/xaiger.cc b/backends/aiger/xaiger.cc index 200ae1a3b..97dec40e4 100644 --- a/backends/aiger/xaiger.cc +++ b/backends/aiger/xaiger.cc @@ -671,8 +671,7 @@ struct XAigerWriter //f.write(reinterpret_cast(&buffer_size_be), sizeof(buffer_size_be)); //f.write(buffer_str.data(), buffer_str.size()); - if (yosys_write_versions) - f << stringf("Generated by %s\n", yosys_version_str); + f << stringf("Generated by %s\n", yosys_maybe_version()); design->scratchpad_set_int("write_xaiger.num_ands", and_map.size()); design->scratchpad_set_int("write_xaiger.num_wires", aig_map.size()); diff --git a/backends/blif/blif.cc b/backends/blif/blif.cc index 01507c115..5a5b9219f 100644 --- a/backends/blif/blif.cc +++ b/backends/blif/blif.cc @@ -649,8 +649,7 @@ struct BlifBackend : public Backend { if (module->get_bool_attribute(ID::top)) top_module_name = module->name.str(); - if (yosys_write_versions) - *f << stringf("# Generated by %s\n", yosys_version_str); + *f << stringf("# Generated by %s\n", yosys_maybe_version()); std::vector mod_list; diff --git a/backends/btor/btor.cc b/backends/btor/btor.cc index fa3cc728e..bfd293557 100644 --- a/backends/btor/btor.cc +++ b/backends/btor/btor.cc @@ -1499,7 +1499,7 @@ struct BtorWorker { ywmap_json.begin_object(); ywmap_json.entry("version", "Yosys Witness BTOR map"); - ywmap_json.entry("generator", yosys_version_str); + ywmap_json.entry("generator", yosys_maybe_version()); ywmap_json.name("clocks"); ywmap_json.begin_array(); @@ -1613,7 +1613,7 @@ struct BtorBackend : public Backend { log_cmd_error("No top module found.\n"); *f << stringf("; BTOR description generated by %s for module %s.\n", - yosys_version_str, log_id(topmod)); + yosys_maybe_version(), log_id(topmod)); BtorWorker(*f, topmod, verbose, single_bad, cover_mode, print_internal_names, info_filename, ywmap_filename); diff --git a/backends/edif/edif.cc b/backends/edif/edif.cc index 1b67d0b4d..581590287 100644 --- a/backends/edif/edif.cc +++ b/backends/edif/edif.cc @@ -232,8 +232,7 @@ struct EdifBackend : public Backend { *f << stringf(" (edifLevel 0)\n"); *f << stringf(" (keywordMap (keywordLevel 0))\n"); - if (yosys_write_versions) - *f << stringf(" (comment \"Generated by %s\")\n", yosys_version_str); + *f << stringf(" (comment \"Generated by %s\")\n", yosys_maybe_version()); *f << stringf(" (external LIB\n"); *f << stringf(" (edifLevel 0)\n"); diff --git a/backends/jny/jny.cc b/backends/jny/jny.cc index 1c163dba5..4aacb4e20 100644 --- a/backends/jny/jny.cc +++ b/backends/jny/jny.cc @@ -125,7 +125,7 @@ struct JnyWriter f << "{\n"; f << " \"$schema\": \"https://raw.githubusercontent.com/YosysHQ/yosys/main/misc/jny.schema.json\",\n"; - f << stringf(" \"generator\": \"%s\",\n", escape_string(yosys_version_str).c_str()); + f << stringf(" \"generator\": \"%s\",\n", escape_string(yosys_maybe_version()).c_str()); f << " \"version\": \"0.0.1\",\n"; f << " \"invocation\": \"" << escape_string(invk) << "\",\n"; f << " \"features\": ["; diff --git a/backends/json/json.cc b/backends/json/json.cc index 7108f5f77..98e929dfa 100644 --- a/backends/json/json.cc +++ b/backends/json/json.cc @@ -291,8 +291,7 @@ struct JsonWriter design->sort(); f << stringf("{\n"); - if (yosys_write_versions) - f << stringf(" \"creator\": %s,\n", get_string(yosys_version_str).c_str()); + f << stringf(" \"creator\": %s,\n", get_string(yosys_maybe_version()).c_str()); f << stringf(" \"modules\": {\n"); vector modules = use_selection ? design->selected_modules() : design->modules(); bool first_module = true; diff --git a/backends/rtlil/rtlil_backend.cc b/backends/rtlil/rtlil_backend.cc index 7a657d9e5..adde37356 100644 --- a/backends/rtlil/rtlil_backend.cc +++ b/backends/rtlil/rtlil_backend.cc @@ -460,8 +460,7 @@ struct RTLILBackend : public Backend { log("Output filename: %s\n", filename.c_str()); - if (yosys_write_versions) - *f << stringf("# Generated by %s\n", yosys_version_str); + *f << stringf("# Generated by %s\n", yosys_maybe_version()); RTLIL_BACKEND::dump_design(*f, design, selected, true, false); } } RTLILBackend; diff --git a/backends/smt2/smt2.cc b/backends/smt2/smt2.cc index 02784b975..87f5a08c8 100644 --- a/backends/smt2/smt2.cc +++ b/backends/smt2/smt2.cc @@ -1831,7 +1831,7 @@ struct Smt2Backend : public Backend { } } - *f << stringf("; SMT-LIBv2 description generated by %s\n", yosys_version_str); + *f << stringf("; SMT-LIBv2 description generated by %s\n", yosys_maybe_version()); if (!bvmode) *f << stringf("; yosys-smt2-nobv\n"); diff --git a/backends/smt2/smtio.py b/backends/smt2/smtio.py index ab25eee72..2bc7daddc 100644 --- a/backends/smt2/smtio.py +++ b/backends/smt2/smtio.py @@ -1289,7 +1289,6 @@ class MkVcd: assert t >= self.t if t != self.t: if self.t == -1: - # TODO if (yosys_write_versions) equivalent? print("$version Generated by Yosys-SMTBMC $end", file=self.f) print("$timescale 1ns $end", file=self.f) print("$var integer 32 t smt_step $end", file=self.f) diff --git a/backends/smv/smv.cc b/backends/smv/smv.cc index 44e200384..1c2b2a224 100644 --- a/backends/smv/smv.cc +++ b/backends/smv/smv.cc @@ -797,7 +797,7 @@ struct SmvBackend : public Backend { if (module == nullptr) log_error("Module '%s' not found.\n", stmt[1].c_str()); - *f << stringf("-- SMV description generated by %s\n", yosys_version_str); + *f << stringf("-- SMV description generated by %s\n", yosys_maybe_version()); log("Creating SMV representation of module %s.\n", log_id(module)); SmvWorker worker(module, verbose, *f); @@ -816,7 +816,7 @@ struct SmvBackend : public Backend { if (!modules.empty()) { - *f << stringf("-- SMV description generated by %s\n", yosys_version_str); + *f << stringf("-- SMV description generated by %s\n", yosys_maybe_version()); for (auto module : modules) { log("Creating SMV representation of module %s.\n", log_id(module)); diff --git a/backends/spice/spice.cc b/backends/spice/spice.cc index 1160a01a1..e55db95e1 100644 --- a/backends/spice/spice.cc +++ b/backends/spice/spice.cc @@ -215,7 +215,7 @@ struct SpiceBackend : public Backend { if (module->get_bool_attribute(ID::top)) top_module_name = module->name.str(); - *f << stringf("* SPICE netlist generated by %s\n", yosys_version_str); + *f << stringf("* SPICE netlist generated by %s\n", yosys_maybe_version()); *f << stringf("\n"); for (auto module : design->modules()) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 98a8cc30d..19be9914e 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -2596,8 +2596,7 @@ struct VerilogBackend : public Backend { design->sort(); - if (yosys_write_versions) - *f << stringf("/* Generated by %s */\n", yosys_version_str); + *f << stringf("/* Generated by %s */\n", yosys_maybe_version()); for (auto module : design->modules()) { if (module->get_blackbox_attribute() != blackboxes) diff --git a/kernel/driver.cc b/kernel/driver.cc index e3a4cfa3e..9acc58dc4 100644 --- a/kernel/driver.cc +++ b/kernel/driver.cc @@ -252,7 +252,7 @@ int main(int argc, char **argv) options.add_options("logging") ("Q", "suppress printing of banner (copyright, disclaimer, version)") ("T", "suppress printing of footer (log hash, version, timing statistics)") - ("no-version", "suppress writing Yosys version in command outputs") + ("no-version", "suppress writing out Yosys version anywhere excluding -V, --version") ("q,quiet", "quiet operation. Only write warnings and error messages to console. " \ "Use this option twice to also quiet warning messages") ("v,verbose", "print log headers up to to the console. " \ @@ -693,7 +693,7 @@ int main(int argc, char **argv) stats_divider.c_str(), ru_buffer.ru_utime.tv_sec + 1e-6 * ru_buffer.ru_utime.tv_usec, ru_buffer.ru_stime.tv_sec + 1e-6 * ru_buffer.ru_stime.tv_usec, meminfo.c_str()); #endif - log("%s\n", yosys_version_str); + log("%s\n", yosys_maybe_version()); int64_t total_ns = 0; std::set> timedat; @@ -733,7 +733,7 @@ int main(int argc, char **argv) log_error("Can't open performance log file for writing: %s\n", strerror(errno)); fprintf(f, "{\n"); - fprintf(f, " \"generator\": \"%s\",\n", yosys_version_str); + fprintf(f, " \"generator\": \"%s\",\n", yosys_maybe_version()); fprintf(f, " \"total_ns\": %" PRIu64 ",\n", total_ns); fprintf(f, " \"passes\": {"); diff --git a/kernel/register.cc b/kernel/register.cc index a82f93555..af1823b5b 100644 --- a/kernel/register.cc +++ b/kernel/register.cc @@ -860,7 +860,7 @@ struct HelpPass : public Pass { // init json json.begin_object(); json.entry("version", "Yosys internal cells"); - json.entry("generator", yosys_version_str); + json.entry("generator", yosys_maybe_version()); dict> groups; dict> cells; diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 5b89fc9b1..60b1bef4d 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -82,6 +82,13 @@ YOSYS_NAMESPACE_BEGIN int autoidx = 1; int yosys_xtrace = 0; bool yosys_write_versions = true; +const char* yosys_maybe_version() { + if (yosys_write_versions) + return yosys_version_str; + else + return "Yosys"; +} + RTLIL::Design *yosys_design = NULL; CellTypes yosys_celltypes; @@ -145,7 +152,7 @@ void yosys_banner() log(" | Copyright (C) 2012 - 2025 Claire Xenia Wolf |\n"); log(" | Distributed under an ISC-like license, type \"license\" to see terms |\n"); log(" \\----------------------------------------------------------------------------/\n"); - log(" %s\n", yosys_version_str); + log(" %s\n", yosys_maybe_version()); } #if !defined(YOSYS_DISABLE_SPAWN) diff --git a/kernel/yosys.h b/kernel/yosys.h index d0359aea8..7dfe8aa0b 100644 --- a/kernel/yosys.h +++ b/kernel/yosys.h @@ -81,6 +81,7 @@ extern std::set yosys_input_files, yosys_output_files; // from kernel/version_*.o (cc source generated from Makefile) extern const char *yosys_version_str; +const char* yosys_maybe_version(); // from passes/cmds/design.cc extern std::map saved_designs; diff --git a/passes/cmds/internal_stats.cc b/passes/cmds/internal_stats.cc index bdf556e81..28822f237 100644 --- a/passes/cmds/internal_stats.cc +++ b/passes/cmds/internal_stats.cc @@ -99,8 +99,7 @@ struct InternalStatsPass : public Pass { if (json_mode) { log("{\n"); - if (yosys_write_versions) - log(" \"creator\": %s,\n", json11::Json(yosys_version_str).dump().c_str()); + log(" \"creator\": %s,\n", json11::Json(yosys_maybe_version()).dump().c_str()); std::stringstream invocation; std::copy(args.begin(), args.end(), std::ostream_iterator(invocation, " ")); log(" \"invocation\": %s,\n", json11::Json(invocation.str()).dump().c_str()); diff --git a/passes/cmds/stat.cc b/passes/cmds/stat.cc index 4c1331d35..6b93621f1 100644 --- a/passes/cmds/stat.cc +++ b/passes/cmds/stat.cc @@ -444,8 +444,7 @@ struct StatPass : public Pass { if (json_mode) { log("{\n"); - if (yosys_write_versions) - log(" \"creator\": %s,\n", json11::Json(yosys_version_str).dump().c_str()); + log(" \"creator\": %s,\n", json11::Json(yosys_maybe_version()).dump().c_str()); std::stringstream invocation; std::copy(args.begin(), args.end(), std::ostream_iterator(invocation, " ")); log(" \"invocation\": %s,\n", json11::Json(invocation.str()).dump().c_str()); diff --git a/passes/sat/sat.cc b/passes/sat/sat.cc index 46cc00981..0c2143fc9 100644 --- a/passes/sat/sat.cc +++ b/passes/sat/sat.cc @@ -690,11 +690,9 @@ struct SatHelper fprintf(f, "$date\n"); fprintf(f, " %s\n", stime); fprintf(f, "$end\n"); - if (yosys_write_versions) { - fprintf(f, "$version\n"); - fprintf(f, " Generated by %s\n", yosys_version_str); - fprintf(f, "$end\n"); - } + fprintf(f, "$version\n"); + fprintf(f, " Generated by %s\n", yosys_maybe_version()); + fprintf(f, "$end\n"); fprintf(f, "$comment\n"); fprintf(f, " Generated from SAT problem in module %s (declared at %s)\n", module->name.c_str(), module_fname.c_str()); diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index dd2f1d255..bb4eb3d82 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -2065,7 +2065,7 @@ struct SimWorker : SimShared json.begin_object(); json.entry("version", "Yosys sim summary"); - json.entry("generator", yosys_version_str); + json.entry("generator", yosys_maybe_version()); json.entry("steps", step); json.entry("top", log_id(top->module->name)); json.name("assertions"); @@ -2344,7 +2344,7 @@ struct VCDWriter : public OutputWriter void write(std::map &use_signal) override { if (!vcdfile.is_open()) return; - vcdfile << stringf("$version %s $end\n", worker->date ? yosys_version_str : "Yosys"); + vcdfile << stringf("$version %s $end\n", worker->date ? yosys_maybe_version() : "Yosys"); if (worker->date) { std::time_t t = std::time(nullptr); @@ -2412,7 +2412,7 @@ struct FSTWriter : public OutputWriter { if (!fstfile) return; std::time_t t = std::time(nullptr); - fstWriterSetVersion(fstfile, worker->date ? yosys_version_str : "Yosys"); + fstWriterSetVersion(fstfile, worker->date ? yosys_maybe_version() : "Yosys"); if (worker->date) fstWriterSetDate(fstfile, asctime(std::localtime(&t))); else From 7cbe6ed048ab647f2be7ba11173bda3251d68a41 Mon Sep 17 00:00:00 2001 From: George Rennie Date: Wed, 7 May 2025 14:36:48 +0200 Subject: [PATCH 06/74] kernel: add safer variants of as_int --- kernel/rtlil.cc | 56 +++++++++++++++++++++++++++++++++++++++++++++++++ kernel/rtlil.h | 6 ++++++ 2 files changed, 62 insertions(+) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index dd78b202d..9f5972c32 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -380,6 +380,30 @@ int RTLIL::Const::as_int(bool is_signed) const return ret; } +bool RTLIL::Const::convertible_to_int(bool is_signed) const +{ + auto size = get_min_size(is_signed); + return (size > 0 && size <= 32); +} + +std::optional RTLIL::Const::try_as_int(bool is_signed) const +{ + if (!convertible_to_int(is_signed)) + return std::nullopt; + return as_int(is_signed); +} + +int RTLIL::Const::as_int_saturating(bool is_signed) const +{ + if (!convertible_to_int(is_signed)) { + const auto min_size = get_min_size(is_signed); + log_assert(min_size > 0); + const auto neg = get_bits().at(min_size - 1); + return neg ? std::numeric_limits::min() : std::numeric_limits::max(); + } + return as_int(is_signed); +} + int RTLIL::Const::get_min_size(bool is_signed) const { if (empty()) return 0; @@ -5462,6 +5486,38 @@ int RTLIL::SigSpec::as_int(bool is_signed) const return 0; } +bool RTLIL::SigSpec::convertible_to_int(bool is_signed) const +{ + cover("kernel.rtlil.sigspec.convertible_to_int"); + + pack(); + if (!is_fully_const()) + return false; + + return RTLIL::Const(chunks_[0].data).convertible_to_int(is_signed); +} + +std::optional RTLIL::SigSpec::try_as_int(bool is_signed) const +{ + cover("kernel.rtlil.sigspec.try_as_int"); + + pack(); + if (!is_fully_const()) + return std::nullopt; + + return RTLIL::Const(chunks_[0].data).try_as_int(is_signed); +} + +int RTLIL::SigSpec::as_int_saturating(bool is_signed) const +{ + cover("kernel.rtlil.sigspec.try_as_int"); + + pack(); + log_assert(is_fully_const() && GetSize(chunks_) <= 1); + log_assert(!empty()); + return RTLIL::Const(chunks_[0].data).as_int_saturating(is_signed); +} + std::string RTLIL::SigSpec::as_string() const { cover("kernel.rtlil.sigspec.as_string"); diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 96c8c523b..50c96c71b 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -754,6 +754,9 @@ public: std::vector& bits(); bool as_bool() const; int as_int(bool is_signed = false) const; + bool convertible_to_int(bool is_signed = false) const; + std::optional try_as_int(bool is_signed = false) const; + int as_int_saturating(bool is_signed = false) const; std::string as_string(const char* any = "-") const; static Const from_string(const std::string &str); std::vector to_bits() const; @@ -1131,6 +1134,9 @@ public: bool as_bool() const; int as_int(bool is_signed = false) const; + bool convertible_to_int(bool is_signed = false) const; + std::optional try_as_int(bool is_signed = false) const; + int as_int_saturating(bool is_signed = false) const; std::string as_string() const; RTLIL::Const as_const() const; RTLIL::Wire *as_wire() const; From 0dcd94b6ad22612e884cb55337c1ec0441715805 Mon Sep 17 00:00:00 2001 From: George Rennie Date: Wed, 7 May 2025 14:41:13 +0200 Subject: [PATCH 07/74] opt_expr: saturate shift amount instead of overflowing for large shifts --- passes/opt/opt_expr.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 74f5b386a..1c8bb4feb 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -1307,7 +1307,12 @@ skip_fine_alu: if (cell->type.in(ID($shl), ID($shr), ID($sshl), ID($sshr), ID($shift), ID($shiftx)) && (keepdc ? assign_map(cell->getPort(ID::B)).is_fully_def() : assign_map(cell->getPort(ID::B)).is_fully_const())) { bool sign_ext = cell->type == ID($sshr) && cell->getParam(ID::A_SIGNED).as_bool(); - int shift_bits = assign_map(cell->getPort(ID::B)).as_int(cell->type.in(ID($shift), ID($shiftx)) && cell->getParam(ID::B_SIGNED).as_bool()); + RTLIL::SigSpec sig_b = assign_map(cell->getPort(ID::B)); + const bool b_sign_ext = cell->type.in(ID($shift), ID($shiftx)) && cell->getParam(ID::B_SIGNED).as_bool(); + // We saturate the value to prevent overflow, but note that this could + // cause incorrect opimization in the impractical case that A is 2^32 bits + // wide + int shift_bits = sig_b.as_int_saturating(b_sign_ext); if (cell->type.in(ID($shl), ID($sshl))) shift_bits *= -1; From af933b4f3801fa560e0ec4a4f33f99ff41265920 Mon Sep 17 00:00:00 2001 From: George Rennie Date: Wed, 7 May 2025 15:12:33 +0200 Subject: [PATCH 08/74] tests: check shifts by amounts that overflow int --- tests/opt/opt_expr_shift.ys | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/tests/opt/opt_expr_shift.ys b/tests/opt/opt_expr_shift.ys index aac2e6f62..5944bfa33 100644 --- a/tests/opt/opt_expr_shift.ys +++ b/tests/opt/opt_expr_shift.ys @@ -48,3 +48,25 @@ select -assert-none t:$shl select -assert-none t:$shr select -assert-none t:$sshl select -assert-none t:$sshr + +design -reset + +read_verilog <> 36'hfffffffff); + wire signed [35:0] shamt = 36'hfffffffff; + assign out2 = (in >> shamt); +endmodule +EOT + +equiv_opt opt_expr + +design -load postopt +select -assert-none t:$shl +select -assert-none t:$shr +select -assert-none t:$sshl +select -assert-none t:$sshr From e2485000c7d7158097be01e29a6e18d7fe899d00 Mon Sep 17 00:00:00 2001 From: George Rennie Date: Thu, 8 May 2025 11:08:20 +0200 Subject: [PATCH 09/74] kernel: handle unsigned case for as_int_saturating correctly * This fixes #5105 --- kernel/rtlil.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 9f5972c32..c08e78dce 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -396,6 +396,9 @@ std::optional RTLIL::Const::try_as_int(bool is_signed) const int RTLIL::Const::as_int_saturating(bool is_signed) const { if (!convertible_to_int(is_signed)) { + if (!is_signed) + return std::numeric_limits::max(); + const auto min_size = get_min_size(is_signed); log_assert(min_size > 0); const auto neg = get_bits().at(min_size - 1); From d59380b3a0e6596f141e8f96de1b58b7540385f2 Mon Sep 17 00:00:00 2001 From: George Rennie Date: Thu, 8 May 2025 11:09:01 +0200 Subject: [PATCH 10/74] tests: more complete testing of shift edgecases --- tests/opt/opt_expr_shift.ys | 55 ++++++++++++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 7 deletions(-) diff --git a/tests/opt/opt_expr_shift.ys b/tests/opt/opt_expr_shift.ys index 5944bfa33..943d370dc 100644 --- a/tests/opt/opt_expr_shift.ys +++ b/tests/opt/opt_expr_shift.ys @@ -20,7 +20,11 @@ module top ( output wire [7:0] sshr_uu, output wire signed [7:0] sshr_us, output wire [7:0] sshr_su, - output wire signed [7:0] sshr_ss + output wire signed [7:0] sshr_ss, + output wire [7:0] shiftx_uu, + output wire signed [7:0] shiftx_us, + output wire [7:0] shiftx_su, + output wire signed [7:0] shiftx_ss ); assign shl_uu = in_u << 20; assign shl_us = in_u << 20; @@ -38,9 +42,20 @@ module top ( assign sshr_us = in_u >>> 20; assign sshr_su = in_s >>> 20; assign sshr_ss = in_s >>> 20; + wire [7:0] shamt = 20; + assign shiftx_uu = in_u[shamt +: 8]; + assign shiftx_us = in_u[shamt +: 8]; + assign shiftx_su = in_s[shamt +: 8]; + assign shiftx_ss = in_s[shamt +: 8]; endmodule EOT +select -assert-count 4 t:$shl +select -assert-count 4 t:$shr +select -assert-count 4 t:$sshl +select -assert-count 4 t:$sshr +select -assert-count 4 t:$shiftx + equiv_opt opt_expr design -load postopt @@ -48,21 +63,46 @@ select -assert-none t:$shl select -assert-none t:$shr select -assert-none t:$sshl select -assert-none t:$sshr +select -assert-none t:$shiftx design -reset read_verilog <> 36'hfffffffff; + assign sshl = in <<< 36'hfffffffff; + assign sshr = in >>> 36'hfffffffff; + assign shiftx = in[36'hfffffffff +: 8]; - assign out1 = (in >> 36'hfffffffff); wire signed [35:0] shamt = 36'hfffffffff; - assign out2 = (in >> shamt); + assign shl_s = in << shamt; + assign shr_s = in >> shamt; + assign sshl_s = in <<< shamt; + assign sshr_s = in >>> shamt; + assign shiftx_s = in[shamt +: 8]; endmodule EOT +select -assert-count 2 t:$shl +select -assert-count 2 t:$shr +select -assert-count 2 t:$sshl +select -assert-count 2 t:$sshr +select -assert-count 1 t:$shiftx + equiv_opt opt_expr design -load postopt @@ -70,3 +110,4 @@ select -assert-none t:$shl select -assert-none t:$shr select -assert-none t:$sshl select -assert-none t:$sshr +select -assert-none t:$shiftx From 55bd950af404741a97f595c9f40c2b5c871868fb Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 9 May 2025 00:27:47 +0000 Subject: [PATCH 11/74] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5986b1091..5692ba3c1 100644 --- a/Makefile +++ b/Makefile @@ -160,7 +160,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.53+3 +YOSYS_VER := 0.53+11 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2) From 0d621ecc110641bf912dd61efe031ef2bd066843 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Fri, 9 May 2025 11:36:39 +0200 Subject: [PATCH 12/74] libcache: add -quiet and -verbose --- passes/techmap/libcache.cc | 29 +++++++++++++++++++++++++---- passes/techmap/libparse.cc | 6 ++++-- passes/techmap/libparse.h | 1 + 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/passes/techmap/libcache.cc b/passes/techmap/libcache.cc index 19f1fa87d..177258e7f 100644 --- a/passes/techmap/libcache.cc +++ b/passes/techmap/libcache.cc @@ -29,7 +29,7 @@ { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" libcache {-enable|-disable|-purge} { -all | [path]... }\n"); + log(" libcache [-verbose] {-enable|-disable|-purge} { -all | [path]... }\n"); log("\n"); log("Controls the default and per path caching of liberty file data.\n"); log("\n"); @@ -47,6 +47,13 @@ log("\n"); log("Displays the current cache settings and cached paths.\n"); log("\n"); + log(" libcache {-verbose|-quiet}\n"); + log("\n"); + log("Controls cache use logging.\n"); + log("\n"); + log(" -verbose Enable printing info when cache is used\n"); + log(" -quiet Disable printing info when cache is used (default)\n"); + log("\n"); } void execute(std::vector args, RTLIL::Design *) override { @@ -55,6 +62,8 @@ bool purge = false; bool all = false; bool list = false; + bool verbose = false; + bool quiet = false; std::vector paths; size_t argidx; @@ -79,16 +88,24 @@ list = true; continue; } + if (args[argidx] == "-verbose") { + verbose = true; + continue; + } + if (args[argidx] == "-quiet") { + quiet = true; + continue; + } std::string fname = args[argidx]; rewrite_filename(fname); paths.push_back(fname); break; } - int modes = enable + disable + purge + list; + int modes = enable + disable + purge + list + verbose + quiet; if (modes == 0) - log_cmd_error("At least one of -enable, -disable, -purge or -list is required.\n"); + log_cmd_error("At least one of -enable, -disable, -purge, -list,\n-verbose, or -quiet is required.\n"); if (modes > 1) - log_cmd_error("Only one of -enable, -disable, -purge or -list may be present.\n"); + log_cmd_error("Only one of -enable, -disable, -purge, -list,\n-verbose, or -quiet may be present.\n"); if (all && !paths.empty()) log_cmd_error("The -all option cannot be combined with a list of paths.\n"); @@ -121,6 +138,10 @@ LibertyAstCache::instance.cache_path.erase(path); } } + } else if (verbose) { + LibertyAstCache::instance.verbose = true; + } else if (quiet) { + LibertyAstCache::instance.verbose = false; } else { log_assert(false); } diff --git a/passes/techmap/libparse.cc b/passes/techmap/libparse.cc index 5594d5443..85ed35ea1 100644 --- a/passes/techmap/libparse.cc +++ b/passes/techmap/libparse.cc @@ -41,7 +41,8 @@ std::shared_ptr LibertyAstCache::cached_ast(const std::string auto it = cached.find(fname); if (it == cached.end()) return nullptr; - log("Using cached data for liberty file `%s'\n", fname.c_str()); + if (verbose) + log("Using cached data for liberty file `%s'\n", fname.c_str()); return it->second; } @@ -51,7 +52,8 @@ void LibertyAstCache::parsed_ast(const std::string &fname, const std::shared_ptr bool should_cache = it == cache_path.end() ? cache_by_default : it->second; if (!should_cache) return; - log("Caching data for liberty file `%s'\n", fname.c_str()); + if (verbose) + log("Caching data for liberty file `%s'\n", fname.c_str()); cached.emplace(fname, ast); } diff --git a/passes/techmap/libparse.h b/passes/techmap/libparse.h index 61dc83867..949adbdcf 100644 --- a/passes/techmap/libparse.h +++ b/passes/techmap/libparse.h @@ -140,6 +140,7 @@ namespace Yosys dict> cached; bool cache_by_default = false; + bool verbose = false; dict cache_path; std::shared_ptr cached_ast(const std::string &fname); From 9d2f9f7557c145daa156d7fefcbdba838ff61616 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Fri, 9 May 2025 12:40:38 +0200 Subject: [PATCH 13/74] libcache: fix test --- tests/liberty/libcache.ys | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/tests/liberty/libcache.ys b/tests/liberty/libcache.ys index a741a9df1..04257aa92 100644 --- a/tests/liberty/libcache.ys +++ b/tests/liberty/libcache.ys @@ -1,3 +1,4 @@ +libcache -verbose libcache -enable busdef.lib logger -expect log "Caching is disabled by default." 1 @@ -14,8 +15,8 @@ logger -expect log "Caching data" 1 read_liberty -lib busdef.lib; design -reset logger -check-expected -logger -expect log "Using caching data" 1 -log Using caching data +logger -expect log "Using cached data" 1 +log Using cached data read_liberty normal.lib; design -reset logger -check-expected @@ -23,6 +24,13 @@ logger -expect log "Using cached data" 1 read_liberty -lib busdef.lib; design -reset logger -check-expected +libcache -quiet +logger -expect log "Using cached data" 1 +log Using cached data +read_liberty -lib busdef.lib; design -reset +logger -check-expected +libcache -verbose + libcache -purge busdef.lib logger -expect log "Caching is disabled by default." 1 From 2ca2ecaa1cc93f4449862f3283ffd696b9c7e204 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Fri, 9 May 2025 12:40:45 +0200 Subject: [PATCH 14/74] libcache: fix help --- passes/techmap/libcache.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/techmap/libcache.cc b/passes/techmap/libcache.cc index 177258e7f..e299f43ec 100644 --- a/passes/techmap/libcache.cc +++ b/passes/techmap/libcache.cc @@ -29,7 +29,7 @@ { // |---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---|---v---| log("\n"); - log(" libcache [-verbose] {-enable|-disable|-purge} { -all | [path]... }\n"); + log(" libcache {-enable|-disable|-purge} { -all | [path]... }\n"); log("\n"); log("Controls the default and per path caching of liberty file data.\n"); log("\n"); From c4a49f0c550190a172c970c4fd6a56b7db805909 Mon Sep 17 00:00:00 2001 From: Adrien Prost-Boucle Date: Fri, 9 May 2025 14:16:03 +0200 Subject: [PATCH 15/74] Create a single-port URAM mapping to support memories 2048 x 144b --- techlibs/xilinx/urams.txt | 23 ++++++ techlibs/xilinx/urams_map.v | 138 ++++++++++++++++++++++++++++++++++++ 2 files changed, 161 insertions(+) diff --git a/techlibs/xilinx/urams.txt b/techlibs/xilinx/urams.txt index 6a5920468..2f881e583 100644 --- a/techlibs/xilinx/urams.txt +++ b/techlibs/xilinx/urams.txt @@ -35,3 +35,26 @@ ram huge $__XILINX_URAM_ { wrbe_separate; } } + +ram huge $__XILINX_URAM_SP_ { + abits 11; + width 144; + cost 1024; + option "BYTEWIDTH" 8 byte 8; + option "BYTEWIDTH" 9 byte 9; + init zero; + port srsw "A" { + clock anyedge "C"; + clken; + rdwr no_change; + rdinit zero; + portoption "RST_MODE" "SYNC" { + rdsrst zero ungated; + } + portoption "RST_MODE" "ASYNC" { + rdarst zero; + } + wrtrans all new; + wrbe_separate; + } +} diff --git a/techlibs/xilinx/urams_map.v b/techlibs/xilinx/urams_map.v index 3ecbe704e..6f861143b 100644 --- a/techlibs/xilinx/urams_map.v +++ b/techlibs/xilinx/urams_map.v @@ -150,3 +150,141 @@ module $__XILINX_URAM_ (...); .SLEEP(1'b0) ); endmodule + +module $__XILINX_URAM_SP_ (...); + parameter OPTION_BYTEWIDTH = 8; + localparam WR_BE_WIDTH = 144 / OPTION_BYTEWIDTH; + + parameter CLK_C_POL = 1; + parameter PORT_A_CLK_POL = 1; + parameter PORT_A_OPTION_RST_MODE = "SYNC"; + + input CLK_C; + + input PORT_A_CLK; + input PORT_A_CLK_EN; + input PORT_A_RD_SRST; + input PORT_A_RD_ARST; + input PORT_A_WR_EN; + input [WR_BE_WIDTH-1:0] PORT_A_WR_BE; + input [10:0] PORT_A_ADDR; + input [143:0] PORT_A_WR_DATA; + output [143:0] PORT_A_RD_DATA; + + wire [71:0] DIN_A, DIN_B, DOUT_A, DOUT_B; + + generate + if (OPTION_BYTEWIDTH == 8) begin + assign DIN_A = PORT_A_WR_DATA[71:0]; + assign DIN_B = PORT_A_WR_DATA[143:72]; + assign PORT_A_RD_DATA = {DOUT_B, DOUT_A}; + end else begin + assign DIN_A = { + PORT_A_WR_DATA[71], + PORT_A_WR_DATA[62], + PORT_A_WR_DATA[53], + PORT_A_WR_DATA[44], + PORT_A_WR_DATA[35], + PORT_A_WR_DATA[26], + PORT_A_WR_DATA[17], + PORT_A_WR_DATA[8], + PORT_A_WR_DATA[70:63], + PORT_A_WR_DATA[61:54], + PORT_A_WR_DATA[52:45], + PORT_A_WR_DATA[43:36], + PORT_A_WR_DATA[34:27], + PORT_A_WR_DATA[25:18], + PORT_A_WR_DATA[16:9], + PORT_A_WR_DATA[7:0] + }; + assign DIN_B = { + PORT_A_WR_DATA[72+71], + PORT_A_WR_DATA[72+62], + PORT_A_WR_DATA[72+53], + PORT_A_WR_DATA[72+44], + PORT_A_WR_DATA[72+35], + PORT_A_WR_DATA[72+26], + PORT_A_WR_DATA[72+17], + PORT_A_WR_DATA[72+8], + PORT_A_WR_DATA[72+70:72+63], + PORT_A_WR_DATA[72+61:72+54], + PORT_A_WR_DATA[72+52:72+45], + PORT_A_WR_DATA[72+43:72+36], + PORT_A_WR_DATA[72+34:72+27], + PORT_A_WR_DATA[72+25:72+18], + PORT_A_WR_DATA[72+16:72+ 9], + PORT_A_WR_DATA[72+ 7:72+ 0] + }; + assign PORT_A_RD_DATA = { + DOUT_B[71], + DOUT_B[63:56], + DOUT_B[70], + DOUT_B[55:48], + DOUT_B[69], + DOUT_B[47:40], + DOUT_B[68], + DOUT_B[39:32], + DOUT_B[67], + DOUT_B[31:24], + DOUT_B[66], + DOUT_B[23:16], + DOUT_B[65], + DOUT_B[15:8], + DOUT_B[64], + DOUT_B[7:0], + DOUT_A[71], + DOUT_A[63:56], + DOUT_A[70], + DOUT_A[55:48], + DOUT_A[69], + DOUT_A[47:40], + DOUT_A[68], + DOUT_A[39:32], + DOUT_A[67], + DOUT_A[31:24], + DOUT_A[66], + DOUT_A[23:16], + DOUT_A[65], + DOUT_A[15:8], + DOUT_A[64], + DOUT_A[7:0] + }; + end + endgenerate + + URAM288 #( + .BWE_MODE_A(OPTION_BYTEWIDTH == 8 ? "PARITY_INDEPENDENT" : "PARITY_INTERLEAVED"), + .BWE_MODE_B(OPTION_BYTEWIDTH == 8 ? "PARITY_INDEPENDENT" : "PARITY_INTERLEAVED"), + .EN_AUTO_SLEEP_MODE("FALSE"), + .IREG_PRE_A("FALSE"), + .IREG_PRE_B("FALSE"), + .IS_CLK_INVERTED(!CLK_C_POL), + .OREG_A("FALSE"), + .OREG_B("FALSE"), + .RST_MODE_A(PORT_A_OPTION_RST_MODE), + .RST_MODE_B(PORT_A_OPTION_RST_MODE), + ) _TECHMAP_REPLACE_ ( + .ADDR_A({10'b0, PORT_A_ADDR, 1'b0}), + .BWE_A(PORT_A_WR_BE[WR_BE_WIDTH/2-1:0]), + .EN_A(PORT_A_CLK_EN), + .RDB_WR_A(PORT_A_WR_EN), + .INJECT_DBITERR_A(1'b0), + .INJECT_SBITERR_A(1'b0), + .RST_A(PORT_A_OPTION_RST_MODE == "SYNC" ? PORT_A_RD_SRST : PORT_A_RD_ARST), + .DIN_A(DIN_A), + .DOUT_A(DOUT_A), + + .ADDR_B({10'b0, PORT_A_ADDR, 1'b1}), + .BWE_B(PORT_A_WR_BE[WR_BE_WIDTH-1:WR_BE_WIDTH]/2), + .EN_B(PORT_A_CLK_EN), + .RDB_WR_B(PORT_A_WR_EN), + .INJECT_DBITERR_B(1'b0), + .INJECT_SBITERR_B(1'b0), + .RST_B(PORT_A_OPTION_RST_MODE == "SYNC" ? PORT_A_RD_SRST : PORT_A_RD_ARST), + .DIN_B(DIN_B), + .DOUT_B(DOUT_B), + + .CLK(CLK_C), + .SLEEP(1'b0) + ); +endmodule From 2522bcd49272d9a2b9ef68cbe8bf2bd27a581cbb Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Fri, 9 May 2025 14:21:10 +0200 Subject: [PATCH 16/74] aiger: fix -map and -vmap --- backends/aiger/aiger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index f2cb5d9bc..0e5706a75 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -698,7 +698,7 @@ struct AigerWriter } if (wire->port_output) { - int o = ordered_outputs.at(sig[i]); + int o = ordered_outputs.at(SigSpec(wire, i)); output_lines[o] += stringf("output %d %d %s\n", o, index, log_id(wire)); } From c7de5312314a060542d17d7b647f6027be04cf86 Mon Sep 17 00:00:00 2001 From: Adrien Prost-Boucle Date: Fri, 9 May 2025 15:09:11 +0200 Subject: [PATCH 17/74] URAM mapping : Fix port indexes according to Yosys warnings --- techlibs/xilinx/urams_map.v | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/techlibs/xilinx/urams_map.v b/techlibs/xilinx/urams_map.v index 6f861143b..c0af64825 100644 --- a/techlibs/xilinx/urams_map.v +++ b/techlibs/xilinx/urams_map.v @@ -264,7 +264,7 @@ module $__XILINX_URAM_SP_ (...); .RST_MODE_A(PORT_A_OPTION_RST_MODE), .RST_MODE_B(PORT_A_OPTION_RST_MODE), ) _TECHMAP_REPLACE_ ( - .ADDR_A({10'b0, PORT_A_ADDR, 1'b0}), + .ADDR_A({11'b0, PORT_A_ADDR, 1'b0}), .BWE_A(PORT_A_WR_BE[WR_BE_WIDTH/2-1:0]), .EN_A(PORT_A_CLK_EN), .RDB_WR_A(PORT_A_WR_EN), @@ -274,8 +274,8 @@ module $__XILINX_URAM_SP_ (...); .DIN_A(DIN_A), .DOUT_A(DOUT_A), - .ADDR_B({10'b0, PORT_A_ADDR, 1'b1}), - .BWE_B(PORT_A_WR_BE[WR_BE_WIDTH-1:WR_BE_WIDTH]/2), + .ADDR_B({11'b0, PORT_A_ADDR, 1'b1}), + .BWE_B(PORT_A_WR_BE[WR_BE_WIDTH-1:WR_BE_WIDTH/2]), .EN_B(PORT_A_CLK_EN), .RDB_WR_B(PORT_A_WR_EN), .INJECT_DBITERR_B(1'b0), From cbf069849ec48669b67b8252e04662acc3a75eb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emil=20Ji=C5=99=C3=AD=20Tywoniak?= Date: Fri, 9 May 2025 16:01:47 +0200 Subject: [PATCH 18/74] aiger: add regression test for sliced output segfault --- tests/aiger/io.ys | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/aiger/io.ys diff --git a/tests/aiger/io.ys b/tests/aiger/io.ys new file mode 100644 index 000000000..eae7f358d --- /dev/null +++ b/tests/aiger/io.ys @@ -0,0 +1,10 @@ +read_verilog < Date: Fri, 9 May 2025 22:30:43 +0200 Subject: [PATCH 19/74] io: don't accept a directory when file expected --- kernel/io.cc | 15 ++++++++++++--- kernel/io.h | 17 +++++++++++++++++ kernel/yosys.cc | 10 +++++----- kernel/yosys_common.h | 17 ----------------- 4 files changed, 34 insertions(+), 25 deletions(-) diff --git a/kernel/io.cc b/kernel/io.cc index 5331e2ed8..d5d2994b2 100644 --- a/kernel/io.cc +++ b/kernel/io.cc @@ -247,7 +247,7 @@ std::string make_temp_dir(std::string template_str) #endif } -bool check_directory_exists(const std::string& dirname) +bool check_is_directory(const std::string& dirname) { #if defined(_WIN32) struct _stat info; @@ -267,17 +267,26 @@ bool check_directory_exists(const std::string& dirname) } #ifdef _WIN32 -bool check_file_exists(std::string filename, bool) +bool check_accessible(const std::string& filename, bool) { return _access(filename.c_str(), 0) == 0; } #else -bool check_file_exists(std::string filename, bool is_exec) +bool check_accessible(const std::string& filename, bool is_exec) { return access(filename.c_str(), is_exec ? X_OK : F_OK) == 0; } #endif +bool check_file_exists(const std::string& filename, bool is_exec) +{ + return check_accessible(filename, is_exec) && !check_is_directory(filename); +} +bool check_directory_exists(const std::string& filename, bool is_exec) +{ + return check_accessible(filename, is_exec) && check_is_directory(filename); +} + bool is_absolute_path(std::string filename) { #ifdef _WIN32 diff --git a/kernel/io.h b/kernel/io.h index b21d4d9c8..91699d775 100644 --- a/kernel/io.h +++ b/kernel/io.h @@ -64,6 +64,23 @@ inline std::string stringf(const char *fmt, ...) return string; } +int readsome(std::istream &f, char *s, int n); +std::string next_token(std::string &text, const char *sep = " \t\r\n", bool long_strings = false); +std::vector split_tokens(const std::string &text, const char *sep = " \t\r\n"); +bool patmatch(const char *pattern, const char *string); +#if !defined(YOSYS_DISABLE_SPAWN) +int run_command(const std::string &command, std::function process_line = std::function()); +#endif +std::string get_base_tmpdir(); +std::string make_temp_file(std::string template_str = get_base_tmpdir() + "/yosys_XXXXXX"); +std::string make_temp_dir(std::string template_str = get_base_tmpdir() + "/yosys_XXXXXX"); +bool check_file_exists(const std::string& filename, bool is_exec = false); +bool check_directory_exists(const std::string& dirname, bool is_exec = false); +bool is_absolute_path(std::string filename); +void remove_directory(std::string dirname); +bool create_directory(const std::string& dirname); +std::string escape_filename_spaces(const std::string& filename); + YOSYS_NAMESPACE_END #endif // YOSYS_IO_H diff --git a/kernel/yosys.cc b/kernel/yosys.cc index 60b1bef4d..7d0d688fc 100644 --- a/kernel/yosys.cc +++ b/kernel/yosys.cc @@ -556,29 +556,29 @@ void init_share_dirname() std::string proc_self_path = proc_self_dirname(); # if defined(_WIN32) && !defined(YOSYS_WIN32_UNIX_DIR) std::string proc_share_path = proc_self_path + "share\\"; - if (check_file_exists(proc_share_path, true)) { + if (check_directory_exists(proc_share_path, true)) { yosys_share_dirname = proc_share_path; return; } proc_share_path = proc_self_path + "..\\share\\"; - if (check_file_exists(proc_share_path, true)) { + if (check_directory_exists(proc_share_path, true)) { yosys_share_dirname = proc_share_path; return; } # else std::string proc_share_path = proc_self_path + "share/"; - if (check_file_exists(proc_share_path, true)) { + if (check_directory_exists(proc_share_path, true)) { yosys_share_dirname = proc_share_path; return; } proc_share_path = proc_self_path + "../share/" + proc_program_prefix()+ "yosys/"; - if (check_file_exists(proc_share_path, true)) { + if (check_directory_exists(proc_share_path, true)) { yosys_share_dirname = proc_share_path; return; } # ifdef YOSYS_DATDIR proc_share_path = YOSYS_DATDIR "/"; - if (check_file_exists(proc_share_path, true)) { + if (check_directory_exists(proc_share_path, true)) { yosys_share_dirname = proc_share_path; return; } diff --git a/kernel/yosys_common.h b/kernel/yosys_common.h index 16215fb76..e84676bc0 100644 --- a/kernel/yosys_common.h +++ b/kernel/yosys_common.h @@ -252,23 +252,6 @@ inline void memhasher() { if (memhasher_active) memhasher_do(); } void yosys_banner(); int ceil_log2(int x) YS_ATTRIBUTE(const); -int readsome(std::istream &f, char *s, int n); -std::string next_token(std::string &text, const char *sep = " \t\r\n", bool long_strings = false); -std::vector split_tokens(const std::string &text, const char *sep = " \t\r\n"); -bool patmatch(const char *pattern, const char *string); -#if !defined(YOSYS_DISABLE_SPAWN) -int run_command(const std::string &command, std::function process_line = std::function()); -#endif -std::string get_base_tmpdir(); -std::string make_temp_file(std::string template_str = get_base_tmpdir() + "/yosys_XXXXXX"); -std::string make_temp_dir(std::string template_str = get_base_tmpdir() + "/yosys_XXXXXX"); -bool check_file_exists(std::string filename, bool is_exec = false); -bool check_directory_exists(const std::string& dirname); -bool is_absolute_path(std::string filename); -void remove_directory(std::string dirname); -bool create_directory(const std::string& dirname); -std::string escape_filename_spaces(const std::string& filename); - template int GetSize(const T &obj) { return obj.size(); } inline int GetSize(RTLIL::Wire *wire); From 2e9a194ce90e0f0021f5c23caaa09aac0c71107f Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Fri, 9 May 2025 21:23:34 +0200 Subject: [PATCH 20/74] gzip: reject uncompressing directories --- kernel/gzip.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel/gzip.cc b/kernel/gzip.cc index 4567fe03b..6790b536e 100644 --- a/kernel/gzip.cc +++ b/kernel/gzip.cc @@ -102,6 +102,8 @@ gzip_istream::ibuf::~ibuf() { // returns the original ifstream, rewound to the start. // Never returns nullptr or failed state istream* std::istream* uncompressed(const std::string filename, std::ios_base::openmode mode) { + if (!check_file_exists(filename)) + log_cmd_error("File `%s' not found or is a directory\n", filename.c_str()); std::ifstream* f = new std::ifstream(); f->open(filename, mode); if (f->fail()) From 1e2d6508d0261f1e616ad2c0a7b1d1be261531e3 Mon Sep 17 00:00:00 2001 From: KrystalDelusion <93062060+KrystalDelusion@users.noreply.github.com> Date: Sat, 10 May 2025 09:09:30 +1200 Subject: [PATCH 21/74] Makefile: Conditional assignment of python exe Using `:=` while providing an override (either in Makefile.conf or on the command line) does not correctly apply the override in other simply expanded variables (using `:=`). Instead, passing an explicit `PYTHON_EXECUTABLE=python3.15` while leaving `PYTHON_CONFIG` implicitly defined results in it being set to `python3-config` instead of the expected `python3.15-config`. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5692ba3c1..c386dc47e 100644 --- a/Makefile +++ b/Makefile @@ -204,7 +204,7 @@ endif include Makefile.conf endif -PYTHON_EXECUTABLE := $(shell if python3 -c ""; then echo "python3"; else echo "python"; fi) +PYTHON_EXECUTABLE ?= $(shell if python3 -c ""; then echo "python3"; else echo "python"; fi) ifeq ($(ENABLE_PYOSYS),1) PYTHON_VERSION_TESTCODE := "import sys;t='{v[0]}.{v[1]}'.format(v=list(sys.version_info[:2]));print(t)" PYTHON_VERSION := $(shell $(PYTHON_EXECUTABLE) -c ""$(PYTHON_VERSION_TESTCODE)"") From af75dce660c9eaf743839df346a7eb0f9c69b08c Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Sat, 10 May 2025 09:59:13 +1200 Subject: [PATCH 22/74] Fix Crashes with GCC 15 #5088 When building `WITH_PYTHON`, where a global list of modules is maintained, deleting a module also erases the entry in said global list. This can lead to memory corruption if the global list is destructed before the module. Using `on_shutdown()` instead means the module destructor is explicitly called before the global list can be destructed, preventing the issue. Also add a comment to `Pass::~Pass()` to suggest the same for future passes that might try to use that (and see this commit in the blame if they need a reason why). --- kernel/register.h | 1 + passes/cmds/design.cc | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/register.h b/kernel/register.h index 25ea9f232..f4e2127e1 100644 --- a/kernel/register.h +++ b/kernel/register.h @@ -29,6 +29,7 @@ struct Pass { std::string pass_name, short_help; Pass(std::string name, std::string short_help = "** document me **"); + // Prefer overriding 'Pass::on_shutdown()' if possible virtual ~Pass(); virtual void help(); diff --git a/passes/cmds/design.cc b/passes/cmds/design.cc index efc72dfb7..a2ae45ef3 100644 --- a/passes/cmds/design.cc +++ b/passes/cmds/design.cc @@ -28,7 +28,7 @@ std::vector pushed_designs; struct DesignPass : public Pass { DesignPass() : Pass("design", "save, restore and reset current design") { } - ~DesignPass() override { + void on_shutdown() override { for (auto &it : saved_designs) delete it.second; saved_designs.clear(); From 6900818105f23cef4111a8ac0aa5e903b63577e8 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 10 May 2025 00:22:55 +0000 Subject: [PATCH 23/74] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5692ba3c1..f733eed8f 100644 --- a/Makefile +++ b/Makefile @@ -160,7 +160,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.53+11 +YOSYS_VER := 0.53+15 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2) From fe0abb7026f82af901f6d030279edd54e4bd1049 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Sat, 10 May 2025 17:10:47 +1200 Subject: [PATCH 24/74] simplify.cc: Fix mem leak --- frontends/ast/simplify.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 3411d6c03..2fa33d508 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1932,6 +1932,8 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin // Prepare replacement node. newNode = template_node->clone(); newNode->str = str; + if (newNode->attributes.count(ID::wiretype)) + delete newNode->attributes[ID::wiretype]; newNode->set_attribute(ID::wiretype, mkconst_str(resolved_type_node->str)); newNode->is_input = is_input; newNode->is_output = is_output; From 6bf758733825e2cf09996ec7bd3ff7d4a5f2dfc8 Mon Sep 17 00:00:00 2001 From: Adrien Prost-Boucle Date: Sat, 10 May 2025 14:53:56 +0200 Subject: [PATCH 25/74] URAM mapping : Add test for 2048 x 144b --- techlibs/xilinx/urams.txt | 1 - tests/arch/xilinx/priority_memory.v | 40 +++++++++++++++++++++++----- tests/arch/xilinx/priority_memory.ys | 10 +++++++ 3 files changed, 43 insertions(+), 8 deletions(-) diff --git a/techlibs/xilinx/urams.txt b/techlibs/xilinx/urams.txt index 2f881e583..f3d9602a3 100644 --- a/techlibs/xilinx/urams.txt +++ b/techlibs/xilinx/urams.txt @@ -54,7 +54,6 @@ ram huge $__XILINX_URAM_SP_ { portoption "RST_MODE" "ASYNC" { rdarst zero; } - wrtrans all new; wrbe_separate; } } diff --git a/tests/arch/xilinx/priority_memory.v b/tests/arch/xilinx/priority_memory.v index fc943e209..8aaa2792c 100644 --- a/tests/arch/xilinx/priority_memory.v +++ b/tests/arch/xilinx/priority_memory.v @@ -2,7 +2,7 @@ module priority_memory ( clk, wren_a, rden_a, addr_a, wdata_a, rdata_a, wren_b, rden_b, addr_b, wdata_b, rdata_b ); - + parameter ABITS = 12; parameter WIDTH = 72; @@ -30,7 +30,7 @@ module priority_memory ( mem[addr_a] <= wdata_a; else if (rden_a) rdata_a <= mem[addr_a]; - + // B port if (wren_b) mem[addr_b] <= wdata_b; @@ -47,7 +47,7 @@ module priority_memory ( mem[addr_b] <= wdata_b; else if (rden_b) rdata_b <= mem[addr_b]; - + // B port if (wren_a) mem[addr_a] <= wdata_a; @@ -79,12 +79,11 @@ module sp_write_first (clk, wren_a, rden_a, addr_a, wdata_a, rdata_a); rdata_a <= 'h0; end - always @(posedge clk) begin // A port if (wren_a) mem[addr_a] <= wdata_a; - if (rden_a) + if (rden_a) if (wren_a) rdata_a <= wdata_a; else @@ -111,12 +110,39 @@ module sp_read_first (clk, wren_a, rden_a, addr_a, wdata_a, rdata_a); rdata_a <= 'h0; end - always @(posedge clk) begin // A port if (wren_a) mem[addr_a] <= wdata_a; - if (rden_a) + if (rden_a) rdata_a <= mem[addr_a]; end endmodule + +module sp_read_or_write (clk, wren_a, rden_a, addr_a, wdata_a, rdata_a); + + parameter ABITS = 11; + parameter WIDTH = 144; + + input clk; + input wren_a, rden_a; + input [ABITS-1:0] addr_a; + input [WIDTH-1:0] wdata_a; + output reg [WIDTH-1:0] rdata_a; + + (* ram_style = "huge" *) + reg [WIDTH-1:0] mem [0:2**ABITS-1]; + + integer i; + initial begin + rdata_a <= 'h0; + end + + always @(posedge clk) begin + if (wren_a) + mem[addr_a] <= wdata_a; + else if (rden_a) + rdata_a <= mem[addr_a]; + end + +endmodule diff --git a/tests/arch/xilinx/priority_memory.ys b/tests/arch/xilinx/priority_memory.ys index d0b2a16ad..9f1d2fb78 100644 --- a/tests/arch/xilinx/priority_memory.ys +++ b/tests/arch/xilinx/priority_memory.ys @@ -58,3 +58,13 @@ select -assert-count 1 t:URAM288 # see above for details select -assert-count 1 t:URAM288 %co:+[DOUT_A] w:rdata_a %i select -assert-none 1 t:URAM288 %co:+[DOUT_B] w:rdata_a %i + +# sp read or write for size 2048 x 144b +# the two URAM ports A and B are concatenated, with port A serving LSBs and port B serving MSBs +design -reset +read_verilog priority_memory.v +synth_xilinx -family xcup -top sp_read_or_write -noiopad +select -assert-count 1 t:URAM288 +# we expect no more than 1 LUT2 to control the hardware enable ports +# see above for details about this command +select -assert-max 1 t:LUT* n:*blif* %d From cc402ee0657992555e48a5562c2a176176b3b3b9 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Mon, 12 May 2025 10:21:06 +1200 Subject: [PATCH 26/74] libs/fst: Update upstream libfst is no longer included in gtkwave and instead has its own repo. There has also been some refactoring, so the patches need to update to match, as does sim.cc. --- libs/fst/00_PATCH_i386_endian.patch | 20 +- libs/fst/00_PATCH_win_io.patch | 6 +- libs/fst/00_PATCH_win_zlib.patch | 8 +- libs/fst/00_PATCH_wx_len_overread.patch | 12 +- libs/fst/00_UPDATE.sh | 7 +- libs/fst/fstapi.cc | 10227 +++++++++++----------- libs/fst/fstapi.h | 733 +- passes/sat/sim.cc | 4 +- 8 files changed, 5441 insertions(+), 5576 deletions(-) diff --git a/libs/fst/00_PATCH_i386_endian.patch b/libs/fst/00_PATCH_i386_endian.patch index 3857f1fdf..5c987fbe4 100644 --- a/libs/fst/00_PATCH_i386_endian.patch +++ b/libs/fst/00_PATCH_i386_endian.patch @@ -1,14 +1,14 @@ --- fstapi.cc +++ fstapi.cc @@ -4723,7 +4723,10 @@ if(gzread_pass_status) - 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); -+ /* -+ * Yosys patch: Fix double endian check for i386 targets built in modern gcc -+ */ -+ xc->double_endian_match = (dcheck == (double)FST_DOUBLE_ENDTEST); - if(!xc->double_endian_match) - { - union { + fstFread(&dcheck, 8, 1, xc->f); +- xc->double_endian_match = (dcheck == FST_DOUBLE_ENDTEST); ++ /* ++ * Yosys patch: Fix double endian check for i386 targets built in modern gcc ++ */ ++ xc->double_endian_match = (dcheck == (double)FST_DOUBLE_ENDTEST); + if (!xc->double_endian_match) { + union + { diff --git a/libs/fst/00_PATCH_win_io.patch b/libs/fst/00_PATCH_win_io.patch index a5bc989a8..807b4ab07 100644 --- a/libs/fst/00_PATCH_win_io.patch +++ b/libs/fst/00_PATCH_win_io.patch @@ -23,9 +23,9 @@ @@ -137,7 +137,7 @@ void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint3 #include #endif - --#if defined(FST_MACOSX) || defined(__MINGW32__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) -+#if defined(FST_MACOSX) || defined(__MINGW32__) || defined(_MSC_VER) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) + #if defined(FST_MACOSX) || defined(__MINGW32__) || defined(__OpenBSD__) || defined(__FreeBSD__) || \ +- defined(__NetBSD__) ++ defined(__NetBSD__) || defined(_MSC_VER) #define FST_UNBUFFERED_IO #endif diff --git a/libs/fst/00_PATCH_win_zlib.patch b/libs/fst/00_PATCH_win_zlib.patch index 125e7cf58..762e0f4df 100644 --- a/libs/fst/00_PATCH_win_zlib.patch +++ b/libs/fst/00_PATCH_win_zlib.patch @@ -7,10 +7,10 @@ -#include #include #if defined(_MSC_VER) -+ #include "libs/zlib/zlib.h" - #include "fst_win_unistd.h" ++#include "libs/zlib/zlib.h" + #include "fst_win_unistd.h" #else -+ #include - #include ++#include + #include #endif #include diff --git a/libs/fst/00_PATCH_wx_len_overread.patch b/libs/fst/00_PATCH_wx_len_overread.patch index 7fba1c2d6..43a5fd476 100644 --- a/libs/fst/00_PATCH_wx_len_overread.patch +++ b/libs/fst/00_PATCH_wx_len_overread.patch @@ -1,10 +1,10 @@ --- fstapi.cc +++ fstapi.cc @@ -6072,6 +6072,7 @@ for(;;) - } + } - wx_len = snprintf(wx_buf, 32, "r%.16g", d); -+ if (wx_len > 32 || wx_len < 0) wx_len = 32; - fstWritex(xc, wx_buf, wx_len); - } - } + wx_len = snprintf(wx_buf, 32, "r%.16g", d); ++ if (wx_len > 32 || wx_len < 0) wx_len = 32; + fstWritex(xc, wx_buf, wx_len); + } + } diff --git a/libs/fst/00_UPDATE.sh b/libs/fst/00_UPDATE.sh index 302e187f2..91dcd84ff 100755 --- a/libs/fst/00_UPDATE.sh +++ b/libs/fst/00_UPDATE.sh @@ -2,9 +2,10 @@ mv config.h config.h.bak rm -f *.txt *.cc *.h -git clone --depth 1 https://github.com/gtkwave/gtkwave fst_upstream -rm fst_upstream/lib/libfst/CMakeLists.txt -mv fst_upstream/lib/libfst/*.{h,c,txt} . +git clone --depth 1 https://github.com/gtkwave/libfst fst_upstream +rm fst_upstream/src/meson.build +mv fst_upstream/src/*.{h,c} . +mv fst_upstream/doc/block_format.txt . rm -rf fst_upstream for src in *.c; do diff --git a/libs/fst/fstapi.cc b/libs/fst/fstapi.cc index 2463e6f15..47f07fa82 100644 --- a/libs/fst/fstapi.cc +++ b/libs/fst/fstapi.cc @@ -34,14 +34,12 @@ * 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 - * _WAVE_HAVE_JUDY : use Judy arrays instead of Jenkins (undefine if LGPL is not acceptable) * */ -#ifndef FST_CONFIG_INCLUDE -# define FST_CONFIG_INCLUDE "config.h" +#ifdef FST_INCLUDE_CONFIG +#include "config.h" #endif -#include FST_CONFIG_INCLUDE #include "fstapi.h" #include "fastlz.h" @@ -61,21 +59,6 @@ #include #endif -#ifdef HAVE_ALLOCA_H -#include -#elif defined(__GNUC__) -#ifndef __MINGW32__ -#ifndef alloca -#define alloca __builtin_alloca -#endif -#else -#include -#endif -#elif defined(_MSC_VER) -#include -#define alloca _alloca -#endif - #ifndef PATH_MAX #define PATH_MAX (4096) #endif @@ -86,58 +69,48 @@ typedef int64_t fst_off_t; typedef off_t fst_off_t; #endif -/* note that Judy versus Jenkins requires more experimentation: they are */ -/* functionally equivalent though it appears Jenkins is slightly faster. */ -/* in addition, Jenkins is not bound by the LGPL. */ -#ifdef _WAVE_HAVE_JUDY -#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; -#define JudyHSIns(a,b,c,d) JenkinsIns((a),(b),(c),(hashmask)) -#define JudyHSFreeArray(a,b) JenkinsFree((a),(hashmask)) void JenkinsFree(void *base_i, uint32_t hashmask); void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint32_t hashmask); -#endif - #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) +#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 (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_ZWRAPPER_HDR_SIZE (1+8+8) +#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_ZWRAPPER_HDR_SIZE (1 + 8 + 8) #if defined(__APPLE__) && defined(__MACH__) #define FST_MACOSX #include #endif -#if defined(FST_MACOSX) || defined(__MINGW32__) || defined(_MSC_VER) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__NetBSD__) +#if defined(FST_MACOSX) || defined(__MINGW32__) || defined(__OpenBSD__) || defined(__FreeBSD__) || \ + defined(__NetBSD__) || defined(_MSC_VER) #define FST_UNBUFFERED_IO #endif @@ -175,138 +148,131 @@ void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint3 * 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)) -#define FST_RCV_U (1 | (3<<1)) -#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_X (1 | (0 << 1)) +#define FST_RCV_Z (1 | (1 << 1)) +#define FST_RCV_H (1 | (2 << 1)) +#define FST_RCV_U (1 | (3 << 1)) +#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 */ - /* * report abort messages */ static void chk_report_abort(const char *s) { -fprintf(stderr,"Triggered %s security check, exiting.\n", s); -abort(); + fprintf(stderr, "Triggered %s security check, exiting.\n", s); + abort(); } - /* * prevent old file overwrite when currently being read */ static FILE *unlink_fopen(const char *nam, const char *mode) { -unlink(nam); -return(fopen(nam, mode)); + unlink(nam); + return (fopen(nam, mode)); } - /* * system-specific temp file handling */ #ifdef __MINGW32__ -static FILE* tmpfile_open(char **nam) +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; + 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 */ - { + 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, FST_APIMESS "GetTempPath() failed in " __FILE__ " line %d, exiting.\n", __LINE__); + if ((dwRetVal > MAX_PATH) || (dwRetVal == 0)) { + fprintf(stderr, + FST_APIMESS "GetTempPath() failed in " __FILE__ " line %d, exiting.\n", + __LINE__); + exit(255); + } else { + uRetVal = GetTempFileName(lpTempPathBuffer, TEXT("FSTW"), 0, szTempFileName); + if (uRetVal == 0) { + fprintf(stderr, + FST_APIMESS "GetTempFileName() failed in " __FILE__ " line %d, exiting.\n", + __LINE__); exit(255); - } - else - { - uRetVal = GetTempFileName(lpTempPathBuffer, TEXT("FSTW"), 0, szTempFileName); - if (uRetVal == 0) - { - fprintf(stderr, FST_APIMESS "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"); - } + } else { + fname = strdup(szTempFileName); + } } -return(fh); + if (fname) { + *nam = fname; + fh = unlink_fopen(fname, "w+b"); + } + } + + return (fh); } #else -static FILE* tmpfile_open(char **nam) +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); + 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 (f) { + if (*f) { + fclose(*f); + *f = NULL; } + } -if(nam) - { - if(*nam) - { - unlink(*nam); - free(*nam); - *nam = 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) */ static size_t fstFread(void *buf, size_t siz, size_t cnt, FILE *fp) { -return(fread(buf, siz, cnt, fp)); + return (fread(buf, siz, cnt, fp)); } static size_t fstFwrite(const void *buf, size_t siz, size_t cnt, FILE *fp) { -return(fwrite(buf, siz, cnt, fp)); + return (fwrite(buf, siz, cnt, fp)); } static int fstFtruncate(int fd, fst_off_t length) { -return(ftruncate(fd, length)); + return (ftruncate(fd, length)); } - /* * realpath compatibility */ @@ -314,50 +280,57 @@ static char *fstRealpath(const char *path, char *resolved_path) { #if defined __USE_BSD || defined __USE_XOPEN_EXTENDED || defined __CYGWIN__ || defined HAVE_REALPATH #if (defined(__MACH__) && defined(__APPLE__)) -if(!resolved_path) - { - resolved_path = (char *)malloc(PATH_MAX+1); /* fixes bug on Leopard when resolved_path == NULL */ - } + if (!resolved_path) { + resolved_path = + (char *)malloc(PATH_MAX + 1); /* fixes bug on Leopard when resolved_path == NULL */ + } #endif -return(realpath(path, resolved_path)); + return (realpath(path, resolved_path)); #else #ifdef __MINGW32__ -if(!resolved_path) - { - resolved_path = (char *)malloc(PATH_MAX+1); - } -return(_fullpath(resolved_path, path, PATH_MAX)); + if (!resolved_path) { + resolved_path = (char *)malloc(PATH_MAX + 1); + } + return (_fullpath(resolved_path, path, PATH_MAX)); #else -(void)path; -(void)resolved_path; -return(NULL); + (void)path; + (void)resolved_path; + return (NULL); #endif #endif } - /* * mmap compatibility */ #if defined __MINGW32__ || defined _MSC_VER #include -#define fstMmap(__addr,__len,__prot,__flags,__fd,__off) fstMmap2((__len), (__fd), (__off)) -#define fstMunmap(__addr,__len) UnmapViewOfFile((LPCVOID)__addr) +#define fstMmap(__addr, __len, __prot, __flags, __fd, __off) fstMmap2((__len), (__fd), (__off)) +#define fstMunmap(__addr, __len) UnmapViewOfFile((LPCVOID)__addr) static void *fstMmap2(size_t __len, int __fd, fst_off_t __off) { -DWORD64 len64 = __len; /* Must be 64-bit for shift below */ -HANDLE handle = CreateFileMapping((HANDLE)_get_osfhandle(__fd), NULL, - PAGE_READWRITE, (DWORD)(len64 >> 32), - (DWORD)__len, NULL); -if (!handle) { return NULL; } + DWORD64 len64 = __len; /* Must be 64-bit for shift below */ + HANDLE handle = CreateFileMapping((HANDLE)_get_osfhandle(__fd), + NULL, + PAGE_READWRITE, + (DWORD)(len64 >> 32), + (DWORD)__len, + NULL); + if (!handle) { + return NULL; + } -void *ptr = MapViewOfFileEx(handle, FILE_MAP_READ | FILE_MAP_WRITE, - 0, (DWORD)__off, (SIZE_T)__len, (LPVOID)NULL); -CloseHandle(handle); -return ptr; + void *ptr = MapViewOfFileEx(handle, + FILE_MAP_READ | FILE_MAP_WRITE, + 0, + (DWORD)__off, + (SIZE_T)__len, + (LPVOID)NULL); + CloseHandle(handle); + return ptr; } #else #include @@ -366,366 +339,333 @@ return ptr; #else #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 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)); \ + } #endif - /* * regular and variable-length integer access functions */ static uint32_t fstGetUint32(unsigned char *mem) { -uint32_t u32; -unsigned char *buf = (unsigned char *)(&u32); + uint32_t u32; + unsigned char *buf = (unsigned char *)(&u32); -memcpy(buf, mem, sizeof(uint32_t)); + memcpy(buf, mem, sizeof(uint32_t)); -return(*(uint32_t *)buf); + return (*(uint32_t *)buf); } - static int fstWriterUint64(FILE *handle, uint64_t v) { -unsigned char buf[8]; -int i; + unsigned char buf[8]; + int i; -for(i=7;i>=0;i--) - { + for (i = 7; i >= 0; i--) { buf[i] = v & 0xff; v >>= 8; - } + } -fstFwrite(buf, 8, 1, handle); -return(8); + fstFwrite(buf, 8, 1, handle); + return (8); } - static uint64_t fstReaderUint64(FILE *f) { -uint64_t val = 0; -unsigned char buf[sizeof(uint64_t)]; -unsigned int i; + uint64_t val = 0; + unsigned char buf[sizeof(uint64_t)]; + 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 */ - { + while ((nxt = nxt >> + 7)) /* determine len to avoid temp buffer copying to cut down on load-hit-store */ + { cnt++; - } + } -pnt -= cnt; -spnt = pnt; -cnt--; + pnt -= cnt; + spnt = pnt; + cnt--; -for(i=0;i>7; + for (i = 0; i < cnt; i++) /* now generate left to right as normal */ + { + nxt = v >> 7; *(spnt++) = ((unsigned char)v) | 0x80; v = nxt; - } -*spnt = (unsigned char)v; + } + *spnt = (unsigned char)v; -return(pnt); + return (pnt); } - static unsigned char *fstCopyVarint64ToRight(unsigned char *pnt, uint64_t v) { -uint64_t nxt; + uint64_t nxt; -while((nxt = v>>7)) - { + while ((nxt = v >> 7)) { *(pnt++) = ((unsigned char)v) | 0x80; v = nxt; - } -*(pnt++) = (unsigned char)v; + } + *(pnt++) = (unsigned char)v; -return(pnt); + return (pnt); } - static uint64_t fstGetVarint64(unsigned char *mem, int *skiplen) { -unsigned char *mem_orig = mem; -uint64_t rc = 0; -while(*mem & 0x80) - { + unsigned char *mem_orig = mem; + uint64_t rc = 0; + while (*mem & 0x80) { mem++; - } + } -*skiplen = mem - mem_orig + 1; -for(;;) - { + *skiplen = mem - mem_orig + 1; + for (;;) { rc <<= 7; rc |= (uint64_t)(*mem & 0x7f); - if(mem == mem_orig) - { - break; - } - mem--; + if (mem == mem_orig) { + break; } + mem--; + } -return(rc); + return (rc); } - static uint32_t fstReaderVarint32(FILE *f) { -const int chk_len_max = 5; /* TALOS-2023-1783 */ -int chk_len = chk_len_max; -unsigned char buf[chk_len_max]; -unsigned char *mem = buf; -uint32_t rc = 0; -int ch; + const int chk_len_max = 5; /* TALOS-2023-1783 */ + int chk_len = chk_len_max; + unsigned char buf[chk_len_max]; + unsigned char *mem = buf; + uint32_t rc = 0; + int ch; -do - { + do { ch = fgetc(f); *(mem++) = ch; - } while((ch & 0x80) && (--chk_len)); + } while ((ch & 0x80) && (--chk_len)); -if(ch & 0x80) chk_report_abort("TALOS-2023-1783"); -mem--; + if (ch & 0x80) + chk_report_abort("TALOS-2023-1783"); + mem--; -for(;;) - { + for (;;) { rc <<= 7; rc |= (uint32_t)(*mem & 0x7f); - if(mem == buf) - { - break; - } - mem--; + if (mem == buf) { + break; } + mem--; + } -return(rc); + return (rc); } - static uint32_t fstReaderVarint32WithSkip(FILE *f, uint32_t *skiplen) { -const int chk_len_max = 5; /* TALOS-2023-1783 */ -int chk_len = chk_len_max; -unsigned char buf[chk_len_max]; -unsigned char *mem = buf; -uint32_t rc = 0; -int ch; + const int chk_len_max = 5; /* TALOS-2023-1783 */ + int chk_len = chk_len_max; + unsigned char buf[chk_len_max]; + unsigned char *mem = buf; + uint32_t rc = 0; + int ch; -do - { + do { ch = fgetc(f); *(mem++) = ch; - } while((ch & 0x80) && (--chk_len)); + } while ((ch & 0x80) && (--chk_len)); -if(ch & 0x80) chk_report_abort("TALOS-2023-1783"); -*skiplen = mem - buf; -mem--; + if (ch & 0x80) + chk_report_abort("TALOS-2023-1783"); + *skiplen = mem - buf; + mem--; -for(;;) - { + for (;;) { rc <<= 7; rc |= (uint32_t)(*mem & 0x7f); - if(mem == buf) - { - break; - } - mem--; + if (mem == buf) { + break; } + mem--; + } -return(rc); + return (rc); } - static uint64_t fstReaderVarint64(FILE *f) { -const int chk_len_max = 16; /* TALOS-2023-1783 */ -int chk_len = chk_len_max; -unsigned char buf[chk_len_max]; -unsigned char *mem = buf; -uint64_t rc = 0; -int ch; + const int chk_len_max = 16; /* TALOS-2023-1783 */ + int chk_len = chk_len_max; + unsigned char buf[chk_len_max]; + unsigned char *mem = buf; + uint64_t rc = 0; + int ch; -do - { + do { ch = fgetc(f); *(mem++) = ch; - } while((ch & 0x80) && (--chk_len)); + } while ((ch & 0x80) && (--chk_len)); -if(ch & 0x80) chk_report_abort("TALOS-2023-1783"); -mem--; + if (ch & 0x80) + chk_report_abort("TALOS-2023-1783"); + mem--; - -for(;;) - { + for (;;) { rc <<= 7; rc |= (uint64_t)(*mem & 0x7f); - if(mem == buf) - { - break; - } - mem--; + if (mem == buf) { + break; } + mem--; + } -return(rc); + return (rc); } - static int fstWriterVarint(FILE *handle, uint64_t v) { -uint64_t nxt; -unsigned char buf[10]; /* ceil(64/7) = 10 */ -unsigned char *pnt = buf; -int len; + uint64_t nxt; + unsigned char buf[10]; /* ceil(64/7) = 10 */ + unsigned char *pnt = buf; + int len; -while((nxt = v>>7)) - { + while ((nxt = v >> 7)) { *(pnt++) = ((unsigned char)v) | 0x80; v = nxt; - } -*(pnt++) = (unsigned char)v; + } + *(pnt++) = (unsigned char)v; -len = pnt-buf; -fstFwrite(buf, len, 1, handle); -return(len); + 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; + 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 { + do { byt = *(mem++); rc |= ((int64_t)(byt & 0x7f)) << shift; shift += 7; - } while(byt & 0x80); + } while (byt & 0x80); -if((shift>= 7; - if (((!v) && (!(byt & 0x40))) || ((v == -1) && (byt & 0x40))) - { - more = 0; - byt &= 0x7f; - } + if (((!v) && (!(byt & 0x40))) || ((v == -1) && (byt & 0x40))) { + more = 0; + byt &= 0x7f; + } *(pnt++) = byt; - } while(more); + } while (more); -len = pnt-buf; -fstFwrite(buf, len, 1, handle); -return(len); + len = pnt - buf; + fstFwrite(buf, len, 1, handle); + return (len); } #endif - /***********************/ /*** ***/ /*** writer function ***/ @@ -737,330 +677,347 @@ return(len); */ struct fstBlackoutChain { -struct fstBlackoutChain *next; -uint64_t tim; -unsigned active : 1; + struct fstBlackoutChain *next; + uint64_t tim; + unsigned active : 1; }; - struct fstWriterContext { -FILE *handle; -FILE *hier_handle; -FILE *geom_handle; -FILE *valpos_handle; -FILE *curval_handle; -FILE *tchn_handle; + FILE *handle; + FILE *hier_handle; + FILE *geom_handle; + FILE *valpos_handle; + FILE *curval_handle; + FILE *tchn_handle; -unsigned char *vchg_mem; + unsigned char *vchg_mem; -fst_off_t hier_file_len; + fst_off_t hier_file_len; -uint32_t *valpos_mem; -unsigned char *curval_mem; + uint32_t *valpos_mem; + unsigned char *curval_mem; -unsigned char *outval_mem; /* for two-state / Verilator-style value changes */ -uint32_t outval_alloc_siz; + unsigned char *outval_mem; /* for two-state / Verilator-style value changes */ + uint32_t outval_alloc_siz; -char *filename; + char *filename; -fstHandle maxhandle; -fstHandle numsigs; -uint32_t maxvalpos; + fstHandle maxhandle; + fstHandle numsigs; + uint32_t maxvalpos; -unsigned vc_emitted : 1; -unsigned is_initial_time : 1; -unsigned fourpack : 1; -unsigned fastpack : 1; + unsigned vc_emitted : 1; + unsigned is_initial_time : 1; + unsigned fourpack : 1; + unsigned fastpack : 1; -int64_t timezero; -fst_off_t section_header_truncpos; -uint32_t tchn_cnt, tchn_idx; -uint64_t curtime; -uint64_t firsttime; -uint32_t vchg_siz; -uint32_t vchg_alloc_siz; + int64_t timezero; + fst_off_t section_header_truncpos; + uint32_t tchn_cnt, tchn_idx; + uint64_t curtime; + uint64_t firsttime; + uint32_t vchg_siz; + uint32_t vchg_alloc_siz; -uint32_t secnum; -fst_off_t section_start; + uint32_t secnum; + fst_off_t section_start; -uint32_t numscopes; -double nan; /* nan value for uninitialized doubles */ + uint32_t numscopes; + double nan; /* nan value for uninitialized doubles */ -struct fstBlackoutChain *blackout_head; -struct fstBlackoutChain *blackout_curr; -uint32_t num_blackouts; + struct fstBlackoutChain *blackout_head; + struct fstBlackoutChain *blackout_curr; + uint32_t num_blackouts; -uint64_t dump_size_limit; + uint64_t dump_size_limit; -unsigned char filetype; /* default is 0, FST_FT_VERILOG */ + unsigned char filetype; /* default is 0, FST_FT_VERILOG */ -unsigned compress_hier : 1; -unsigned repack_on_close : 1; -unsigned skip_writing_section_hdr : 1; -unsigned size_limit_locked : 1; -unsigned section_header_only : 1; -unsigned flush_context_pending : 1; -unsigned parallel_enabled : 1; -unsigned parallel_was_enabled : 1; + unsigned compress_hier : 1; + unsigned repack_on_close : 1; + unsigned skip_writing_section_hdr : 1; + unsigned size_limit_locked : 1; + unsigned section_header_only : 1; + unsigned flush_context_pending : 1; + unsigned parallel_enabled : 1; + unsigned parallel_was_enabled : 1; -/* should really be semaphores, but are bytes to cut down on read-modify-write window size */ -unsigned char already_in_flush; /* in case control-c handlers interrupt */ -unsigned char already_in_close; /* in case control-c handlers interrupt */ + /* should really be semaphores, but are bytes to cut down on read-modify-write window size */ + unsigned char already_in_flush; /* in case control-c handlers interrupt */ + unsigned char already_in_close; /* in case control-c handlers interrupt */ #ifdef FST_WRITER_PARALLEL -pthread_mutex_t mutex; -pthread_t thread; -pthread_attr_t thread_attr; -struct fstWriterContext *xc_parent; + pthread_mutex_t mutex; + pthread_t thread; + pthread_attr_t thread_attr; + struct fstWriterContext *xc_parent; #endif -unsigned in_pthread : 1; + unsigned in_pthread : 1; -size_t fst_orig_break_size; -size_t fst_orig_break_add_size; + size_t fst_orig_break_size; + size_t fst_orig_break_add_size; -size_t fst_break_size; -size_t fst_break_add_size; + size_t fst_break_size; + size_t fst_break_add_size; -size_t fst_huge_break_size; + size_t fst_huge_break_size; -fstHandle next_huge_break; + fstHandle next_huge_break; -Pvoid_t path_array; -uint32_t path_array_count; + Pvoid_t path_array; + uint32_t path_array_count; -unsigned fseek_failed : 1; + unsigned fseek_failed : 1; -char *geom_handle_nam; -char *valpos_handle_nam; -char *curval_handle_nam; -char *tchn_handle_nam; + char *geom_handle_nam; + char *valpos_handle_nam; + char *curval_handle_nam; + char *tchn_handle_nam; -fstEnumHandle max_enumhandle; + fstEnumHandle max_enumhandle; }; - static int fstWriterFseeko(struct fstWriterContext *xc, FILE *stream, fst_off_t offset, int whence) { -int rc = fseeko(stream, offset, whence); + int rc = fseeko(stream, offset, whence); -if(rc<0) - { + if (rc < 0) { xc->fseek_failed = 1; #ifdef FST_DEBUG fprintf(stderr, FST_APIMESS "Seek to #%" PRId64 " (whence = %d) failed!\n", offset, whence); perror("Why"); #endif - } + } -return(rc); + return (rc); } - -static uint32_t fstWriterUint32WithVarint32(struct fstWriterContext *xc, uint32_t *u, uint32_t v, const void *dbuf, uint32_t siz) +static uint32_t fstWriterUint32WithVarint32(struct fstWriterContext *xc, + uint32_t *u, + uint32_t v, + const void *dbuf, + uint32_t siz) { -unsigned char *buf = xc->vchg_mem + xc->vchg_siz; -unsigned char *pnt = buf; -uint32_t nxt; -uint32_t len; + unsigned char *buf = xc->vchg_mem + xc->vchg_siz; + unsigned char *pnt = buf; + uint32_t nxt; + uint32_t len; -memcpy(pnt, u, sizeof(uint32_t)); -pnt += 4; + memcpy(pnt, u, sizeof(uint32_t)); + pnt += 4; -while((nxt = v>>7)) - { + while ((nxt = v >> 7)) { *(pnt++) = ((unsigned char)v) | 0x80; v = nxt; - } -*(pnt++) = (unsigned char)v; -memcpy(pnt, dbuf, siz); + } + *(pnt++) = (unsigned char)v; + memcpy(pnt, dbuf, siz); -len = pnt-buf + siz; -return(len); + len = pnt - buf + siz; + return (len); } - -static uint32_t fstWriterUint32WithVarint32AndLength(struct fstWriterContext *xc, uint32_t *u, uint32_t v, const void *dbuf, uint32_t siz) +static uint32_t fstWriterUint32WithVarint32AndLength(struct fstWriterContext *xc, + uint32_t *u, + uint32_t v, + const void *dbuf, + uint32_t siz) { -unsigned char *buf = xc->vchg_mem + xc->vchg_siz; -unsigned char *pnt = buf; -uint32_t nxt; -uint32_t len; + unsigned char *buf = xc->vchg_mem + xc->vchg_siz; + unsigned char *pnt = buf; + uint32_t nxt; + uint32_t len; -memcpy(pnt, u, sizeof(uint32_t)); -pnt += 4; + memcpy(pnt, u, sizeof(uint32_t)); + pnt += 4; -while((nxt = v>>7)) - { + while ((nxt = v >> 7)) { *(pnt++) = ((unsigned char)v) | 0x80; v = nxt; - } -*(pnt++) = (unsigned char)v; + } + *(pnt++) = (unsigned char)v; -v = siz; -while((nxt = v>>7)) - { + v = siz; + while ((nxt = v >> 7)) { *(pnt++) = ((unsigned char)v) | 0x80; v = nxt; - } -*(pnt++) = (unsigned char)v; + } + *(pnt++) = (unsigned char)v; -memcpy(pnt, dbuf, siz); + memcpy(pnt, dbuf, siz); -len = pnt-buf + siz; -return(len); + len = pnt - buf + siz; + return (len); } - /* * header bytes, write here so defines are set up before anything else * that needs to use them */ static void fstWriterEmitHdrBytes(struct fstWriterContext *xc) { -char vbuf[FST_HDR_SIM_VERSION_SIZE]; -char dbuf[FST_HDR_DATE_SIZE]; -double endtest = FST_DOUBLE_ENDTEST; -time_t walltime; + char vbuf[FST_HDR_SIM_VERSION_SIZE]; + 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) -fstWriterUint64(xc->handle, xc->fst_break_size);/* +33 memory used by writer */ +#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) -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_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) -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 */ +#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 */ -/* date size is deliberately overspecified at 119 bytes (originally 128) in order to provide backfill for new args */ + /* 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 */ -fflush(xc->handle); +#define FST_HDR_LENGTH (FST_HDR_OFFS_TIMEZERO + FST_HDR_TIMEZERO_SIZE) + /* +330 next section starts here */ + fflush(xc->handle); } - /* * mmap functions */ static void fstWriterMmapSanity(void *pnt, const char *file, int line, const char *usage) { -if(pnt == NULL + if (pnt == NULL #ifdef MAP_FAILED - || pnt == MAP_FAILED + || pnt == MAP_FAILED #endif - ) - { - fprintf(stderr, "fstMmap() assigned to %s failed: errno: %d, file %s, line %d.\n", usage, errno, file, line); + ) { + fprintf(stderr, + "fstMmap() assigned to %s failed: errno: %d, file %s, line %d.\n", + usage, + errno, + file, + line); #if !defined(__MINGW32__) - perror("Why"); + perror("Why"); #else - LPSTR mbuf = NULL; - FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM - | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), - MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), - (LPSTR)&mbuf, 0, NULL); - fprintf(stderr, "%s", mbuf); - LocalFree(mbuf); + LPSTR mbuf = NULL; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, + GetLastError(), + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPSTR)&mbuf, + 0, + NULL); + fprintf(stderr, "%s", mbuf); + LocalFree(mbuf); #endif - pnt = NULL; - } + pnt = NULL; + } } - static void fstWriterCreateMmaps(struct fstWriterContext *xc) { -fst_off_t curpos = ftello(xc->handle); + fst_off_t curpos = ftello(xc->handle); -fflush(xc->hier_handle); + fflush(xc->hier_handle); -/* write out intermediate 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); -fstWriterFseeko(xc, xc->handle, curpos, SEEK_SET); -fflush(xc->handle); + /* write out intermediate 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); + fstWriterFseeko(xc, xc->handle, curpos, SEEK_SET); + fflush(xc->handle); -/* do mappings */ -if(!xc->valpos_mem) - { + /* do mappings */ + if (!xc->valpos_mem) { fflush(xc->valpos_handle); - errno = 0; - if(xc->maxhandle) - { - fstWriterMmapSanity(xc->valpos_mem = (uint32_t *)fstMmap(NULL, xc->maxhandle * 4 * sizeof(uint32_t), PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->valpos_handle), 0), __FILE__, __LINE__, "xc->valpos_mem"); - } + errno = 0; + if (xc->maxhandle) { + fstWriterMmapSanity(xc->valpos_mem = + (uint32_t *)fstMmap(NULL, + xc->maxhandle * 4 * sizeof(uint32_t), + PROT_READ | PROT_WRITE, + MAP_SHARED, + fileno(xc->valpos_handle), + 0), + __FILE__, + __LINE__, + "xc->valpos_mem"); } -if(!xc->curval_mem) - { + } + if (!xc->curval_mem) { fflush(xc->curval_handle); - errno = 0; - if(xc->maxvalpos) - { - fstWriterMmapSanity(xc->curval_mem = (unsigned char *)fstMmap(NULL, xc->maxvalpos, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->curval_handle), 0), __FILE__, __LINE__, "xc->curval_handle"); - } + errno = 0; + if (xc->maxvalpos) { + fstWriterMmapSanity(xc->curval_mem = (unsigned char *)fstMmap(NULL, + xc->maxvalpos, + PROT_READ | PROT_WRITE, + MAP_SHARED, + fileno(xc->curval_handle), + 0), + __FILE__, + __LINE__, + "xc->curval_handle"); } + } } - static void fstDestroyMmaps(struct fstWriterContext *xc, int is_closing) { -(void)is_closing; + (void)is_closing; -fstMunmap(xc->valpos_mem, xc->maxhandle * 4 * sizeof(uint32_t)); -xc->valpos_mem = NULL; + fstMunmap(xc->valpos_mem, xc->maxhandle * 4 * sizeof(uint32_t)); + xc->valpos_mem = NULL; -fstMunmap(xc->curval_mem, xc->maxvalpos); -xc->curval_mem = NULL; + fstMunmap(xc->curval_mem, xc->maxvalpos); + xc->curval_mem = NULL; } - /* * set up large and small memory usages * crossover point in model is FST_ACTIVATE_HUGE_BREAK number of signals @@ -1068,105 +1025,89 @@ xc->curval_mem = NULL; static void fstDetermineBreakSize(struct fstWriterContext *xc) { #if defined(__linux__) || defined(FST_MACOSX) -int was_set = 0; + int was_set = 0; #ifdef __linux__ -FILE *f = fopen("/proc/meminfo", "rb"); + FILE *f = fopen("/proc/meminfo", "rb"); -if(f) - { + 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; - } - - xc->fst_huge_break_size = v; - was_set = 1; - break; - } - } + 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; + } } + } + } fclose(f); - } + } -if(!was_set) - { + if (!was_set) { xc->fst_huge_break_size = FST_BREAK_SIZE; - } + } #else -int mib[2]; -int64_t v; -size_t length; + 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)) - { + mib[0] = CTL_HW; + mib[1] = HW_MEMSIZE; + length = sizeof(int64_t); + if (!sysctl(mib, 2, &v, &length, NULL, 0)) { v /= 8; - if(v > (int64_t)FST_BREAK_SIZE) - { - if(v > (int64_t)FST_BREAK_SIZE_MAX) - { - v = FST_BREAK_SIZE_MAX; - } + if (v > (int64_t)FST_BREAK_SIZE) { + if (v > (int64_t)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) - { + if (!was_set) { xc->fst_huge_break_size = FST_BREAK_SIZE; - } + } #endif #else -xc->fst_huge_break_size = FST_BREAK_SIZE; + 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; -xc->next_huge_break = FST_ACTIVATE_HUGE_BREAK; + 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; + xc->next_huge_break = FST_ACTIVATE_HUGE_BREAK; } - /* * file creation and close */ -void *fstWriterCreate(const char *nam, int use_compressed_hier) +fstWriterContext *fstWriterCreate(const char *nam, int use_compressed_hier) { -struct fstWriterContext *xc = (struct fstWriterContext *)calloc(1, sizeof(struct fstWriterContext)); + fstWriterContext *xc = (fstWriterContext *)calloc(1, sizeof(fstWriterContext)); -xc->compress_hier = use_compressed_hier; -fstDetermineBreakSize(xc); + 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; - } - else - { + xc = NULL; + } else { int flen = strlen(nam); char *hf = (char *)calloc(1, flen + 6); @@ -1174,671 +1115,651 @@ if((!nam)|| 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->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 = (unsigned char *)malloc(xc->vchg_alloc_siz); - if(xc->hier_handle && xc->geom_handle && xc->valpos_handle && xc->curval_handle && xc->vchg_mem && xc->tchn_handle) - { - 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; - } - - free(hf); + } 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; } -return(xc); -} + free(hf); + } + return (xc); +} /* * generation and writing out of value change data sections */ -static void fstWriterEmitSectionHeader(void *ctx) +static void fstWriterEmitSectionHeader(fstWriterContext *xc) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; - -if(xc) - { + if (xc) { unsigned long destlen; unsigned char *dmem; int rc; destlen = xc->maxvalpos; dmem = (unsigned char *)malloc(compressBound(destlen)); - rc = compress2(dmem, &destlen, xc->curval_mem, xc->maxvalpos, 4); /* was 9...which caused performance drag on traces with many signals */ + 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 */ + 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); - } + } } - /* * only to be called directly by fst code...otherwise must * be synced up with time changes */ #ifdef FST_WRITER_PARALLEL -static void fstWriterFlushContextPrivate2(void *ctx) +static void fstWriterFlushContextPrivate2(fstWriterContext *xc) #else -static void fstWriterFlushContextPrivate(void *ctx) +static void fstWriterFlushContextPrivate(fstWriterContext *xc) #endif { #ifdef FST_DEBUG -int cnt = 0; + int cnt = 0; #endif -unsigned int i; -unsigned char *vchg_mem; -FILE *f; -fst_off_t fpos, indxpos, endpos; -uint32_t prevpos; -int zerocnt; -unsigned char *scratchpad; -unsigned char *scratchpnt; -unsigned char *tmem; -fst_off_t tlen; -fst_off_t unc_memreq = 0; /* for reader */ -unsigned char *packmem; -unsigned int packmemlen; -uint32_t *vm4ip; -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; + unsigned int i; + unsigned char *vchg_mem; + FILE *f; + fst_off_t fpos, indxpos, endpos; + uint32_t prevpos; + int zerocnt; + unsigned char *scratchpad; + unsigned char *scratchpnt; + unsigned char *tmem; + fst_off_t tlen; + fst_off_t unc_memreq = 0; /* for reader */ + unsigned char *packmem; + unsigned int packmemlen; + uint32_t *vm4ip; #ifdef FST_WRITER_PARALLEL -struct fstWriterContext *xc2 = xc->xc_parent; + struct fstWriterContext *xc2 = xc->xc_parent; #else -struct fstWriterContext *xc2 = xc; + struct fstWriterContext *xc2 = xc; #endif #ifndef FST_DYNAMIC_ALIAS_DISABLE -Pvoid_t PJHSArray = (Pvoid_t) NULL; -#ifndef _WAVE_HAVE_JUDY -uint32_t hashmask = xc->maxhandle; -hashmask |= hashmask >> 1; -hashmask |= hashmask >> 2; -hashmask |= hashmask >> 4; -hashmask |= hashmask >> 8; -hashmask |= hashmask >> 16; -#endif + Pvoid_t PJHSArray = (Pvoid_t)NULL; + uint32_t hashmask = xc->maxhandle; + hashmask |= hashmask >> 1; + hashmask |= hashmask >> 2; + hashmask |= hashmask >> 4; + hashmask |= hashmask >> 8; + hashmask |= hashmask >> 16; #endif -if((xc->vchg_siz <= 1)||(xc->already_in_flush)) return; -xc->already_in_flush = 1; /* should really do this with a semaphore */ + if ((xc->vchg_siz <= 1) || (xc->already_in_flush)) + return; + xc->already_in_flush = 1; /* should really do this with a semaphore */ -xc->section_header_only = 0; -scratchpad = (unsigned char *)malloc(xc->vchg_siz); + xc->section_header_only = 0; + scratchpad = (unsigned char *)malloc(xc->vchg_siz); -vchg_mem = xc->vchg_mem; + vchg_mem = xc->vchg_mem; -f = xc->handle; -fstWriterVarint(f, xc->maxhandle); /* emit current number of handles */ -fputc(xc->fourpack ? '4' : (xc->fastpack ? 'F' : 'Z'), f); -fpos = 1; + f = xc->handle; + 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 = (unsigned char *)malloc(packmemlen); /* prevent continual malloc...free every loop iter */ + packmemlen = 1024; /* maintain a running "longest" allocation to */ + packmem = + (unsigned char *)malloc(packmemlen); /* prevent continual malloc...free every loop iter */ -for(i=0;imaxhandle;i++) - { - vm4ip = &(xc->valpos_mem[4*i]); + for (i = 0; i < xc->maxhandle; i++) { + vm4ip = &(xc->valpos_mem[4 * i]); - if(vm4ip[2]) - { - uint32_t offs = vm4ip[2]; - uint32_t next_offs; - unsigned 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, (int *)&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; - } - - 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, (int *)&wrlen); - pnt += wrlen; - record_len = fstGetVarint32(pnt, (int *)&wrlen); - pnt += wrlen; - - 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 */ -#ifndef FST_REMOVE_DUPLICATE_VC - memcpy(xc->curval_mem + vm4ip[0], vchg_mem + offs + 4 + wrlen, vm4ip[1]); /* checkpoint variable */ -#endif - while(offs) - { - unsigned int idx; - char is_binary = 1; - unsigned char *pnt; - uint32_t time_delta; - - next_offs = fstGetUint32(vchg_mem + offs); - offs += 4; - - time_delta = fstGetVarint32(vchg_mem + offs, (int *)&wrlen); - - pnt = vchg_mem+offs+wrlen; - offs = next_offs; - - for(idx=0;idxvchg_siz - scratchpnt; - unc_memreq += wrlen; - if(wrlen > 32) - { - unsigned long destlen = wrlen; - unsigned char *dmem; - unsigned int rc; + 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; - if(!xc->fastpack) - { - if(wrlen <= packmemlen) - { - dmem = packmem; - } - else - { - free(packmem); - dmem = packmem = (unsigned char *)malloc(compressBound(packmemlen = 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; - 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 = (intptr_t)(*pv); - vm4ip[2] = -pvi; - } - else - { - *pv = (void *)(intptr_t)(i+1); -#endif - fpos += fstWriterVarint(f, wrlen); - fpos += destlen; - fstFwrite(dmem, destlen, 1, f); -#ifndef FST_DYNAMIC_ALIAS_DISABLE - } -#endif - } - else - { -#ifndef FST_DYNAMIC_ALIAS_DISABLE - PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL); - if(*pv) - { - uint32_t pvi = (intptr_t)(*pv); - vm4ip[2] = -pvi; - } - else - { - *pv = (void *)(intptr_t)(i+1); -#endif - 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 = (unsigned char *)malloc(packmemlen = (wrlen * 2) + 2); - } + scratchpnt -= record_len; + memcpy(scratchpnt, pnt, record_len); - rc = (xc->fourpack) ? LZ4_compress_default((char *)scratchpnt, (char *)dmem, wrlen, packmemlen) : 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 = (intptr_t)(*pv); - vm4ip[2] = -pvi; - } - else - { - *pv = (void *)(intptr_t)(i+1); -#endif - fpos += fstWriterVarint(f, wrlen); - fpos += rc; - fstFwrite(dmem, rc, 1, f); -#ifndef FST_DYNAMIC_ALIAS_DISABLE - } -#endif - } - else - { -#ifndef FST_DYNAMIC_ALIAS_DISABLE - PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL); - if(*pv) - { - uint32_t pvi = (intptr_t)(*pv); - vm4ip[2] = -pvi; - } - else - { - *pv = (void *)(intptr_t)(i+1); -#endif - fpos += fstWriterVarint(f, 0); - fpos += wrlen; - fstFwrite(scratchpnt, wrlen, 1, f); -#ifndef FST_DYNAMIC_ALIAS_DISABLE - } -#endif - } - } - } - else - { -#ifndef FST_DYNAMIC_ALIAS_DISABLE - PPvoid_t pv = JudyHSIns(&PJHSArray, scratchpnt, wrlen, NULL); - if(*pv) - { - uint32_t pvi = (intptr_t)(*pv); - vm4ip[2] = -pvi; - } - else - { - *pv = (void *)(intptr_t)(i+1); -#endif - fpos += fstWriterVarint(f, 0); - fpos += wrlen; - fstFwrite(scratchpnt, wrlen, 1, f); -#ifndef FST_DYNAMIC_ALIAS_DISABLE - } -#endif - } - - /* vm4ip[3] = 0; ...redundant with clearing below */ -#ifdef FST_DEBUG - cnt++; -#endif + 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 */ +#endif + while (offs) { + unsigned int idx; + char is_binary = 1; + unsigned char *pnt; + uint32_t time_delta; + + next_offs = fstGetUint32(vchg_mem + offs); + offs += 4; + + time_delta = fstGetVarint32(vchg_mem + offs, (int *)&wrlen); + + pnt = vchg_mem + offs + wrlen; + offs = next_offs; + + for (idx = 0; idx < vm4ip[1]; idx++) { + if ((pnt[idx] == '0') || (pnt[idx] == '1')) { + continue; + } else { + is_binary = 0; + break; + } + } + + if (is_binary) { + unsigned char acc = 0; + /* new algorithm */ + idx = ((vm4ip[1] + 7) & ~7); + switch (vm4ip[1] & 7) { + case 0: + do { + acc = (pnt[idx + 7 - 8] & 1) << 0; /* fallthrough */ + case 7: + acc |= (pnt[idx + 6 - 8] & 1) << 1; /* fallthrough */ + case 6: + acc |= (pnt[idx + 5 - 8] & 1) << 2; /* fallthrough */ + case 5: + acc |= (pnt[idx + 4 - 8] & 1) << 3; /* fallthrough */ + case 4: + acc |= (pnt[idx + 3 - 8] & 1) << 4; /* fallthrough */ + case 3: + acc |= (pnt[idx + 2 - 8] & 1) << 5; /* fallthrough */ + case 2: + acc |= (pnt[idx + 1 - 8] & 1) << 6; /* fallthrough */ + case 1: + acc |= (pnt[idx + 0 - 8] & 1) << 7; + *(--scratchpnt) = acc; + idx -= 8; + } while (idx); + } + + scratchpnt = fstCopyVarint32ToLeft(scratchpnt, (time_delta << 1)); + } else { + scratchpnt -= vm4ip[1]; + memcpy(scratchpnt, pnt, vm4ip[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; + unsigned int rc; + + if (!xc->fastpack) { + if (wrlen <= packmemlen) { + dmem = packmem; + } else { + free(packmem); + dmem = packmem = (unsigned char *)malloc(compressBound(packmemlen = wrlen)); + } + + rc = compress2(dmem, &destlen, scratchpnt, wrlen, 4); + if (rc == Z_OK) { +#ifndef FST_DYNAMIC_ALIAS_DISABLE + PPvoid_t pv = JenkinsIns(&PJHSArray, dmem, destlen, hashmask); + if (*pv) { + uint32_t pvi = (intptr_t)(*pv); + vm4ip[2] = -pvi; + } else { + *pv = (void *)(intptr_t)(i + 1); +#endif + fpos += fstWriterVarint(f, wrlen); + fpos += destlen; + fstFwrite(dmem, destlen, 1, f); +#ifndef FST_DYNAMIC_ALIAS_DISABLE + } +#endif + } else { +#ifndef FST_DYNAMIC_ALIAS_DISABLE + PPvoid_t pv = JenkinsIns(&PJHSArray, scratchpnt, wrlen, hashmask); + if (*pv) { + uint32_t pvi = (intptr_t)(*pv); + vm4ip[2] = -pvi; + } else { + *pv = (void *)(intptr_t)(i + 1); +#endif + 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 = (unsigned char *)malloc(packmemlen = (wrlen * 2) + 2); + } + + rc = (xc->fourpack) ? LZ4_compress_default((char *)scratchpnt, + (char *)dmem, + wrlen, + packmemlen) + : fastlz_compress(scratchpnt, wrlen, dmem); + if (rc < destlen) { +#ifndef FST_DYNAMIC_ALIAS_DISABLE + PPvoid_t pv = JenkinsIns(&PJHSArray, dmem, rc, hashmask); + if (*pv) { + uint32_t pvi = (intptr_t)(*pv); + vm4ip[2] = -pvi; + } else { + *pv = (void *)(intptr_t)(i + 1); +#endif + fpos += fstWriterVarint(f, wrlen); + fpos += rc; + fstFwrite(dmem, rc, 1, f); +#ifndef FST_DYNAMIC_ALIAS_DISABLE + } +#endif + } else { +#ifndef FST_DYNAMIC_ALIAS_DISABLE + PPvoid_t pv = JenkinsIns(&PJHSArray, scratchpnt, wrlen, hashmask); + if (*pv) { + uint32_t pvi = (intptr_t)(*pv); + vm4ip[2] = -pvi; + } else { + *pv = (void *)(intptr_t)(i + 1); +#endif + fpos += fstWriterVarint(f, 0); + fpos += wrlen; + fstFwrite(scratchpnt, wrlen, 1, f); +#ifndef FST_DYNAMIC_ALIAS_DISABLE + } +#endif + } + } + } else { +#ifndef FST_DYNAMIC_ALIAS_DISABLE + PPvoid_t pv = JenkinsIns(&PJHSArray, scratchpnt, wrlen, hashmask); + if (*pv) { + uint32_t pvi = (intptr_t)(*pv); + vm4ip[2] = -pvi; + } else { + *pv = (void *)(intptr_t)(i + 1); +#endif + fpos += fstWriterVarint(f, 0); + fpos += wrlen; + fstFwrite(scratchpnt, wrlen, 1, f); +#ifndef FST_DYNAMIC_ALIAS_DISABLE + } +#endif + } + + /* vm4ip[3] = 0; ...redundant with clearing below */ +#ifdef FST_DEBUG + cnt++; +#endif } + } #ifndef FST_DYNAMIC_ALIAS_DISABLE -JudyHSFreeArray(&PJHSArray, NULL); + JenkinsFree(&PJHSArray, hashmask); #endif -free(packmem); packmem = NULL; /* packmemlen = 0; */ /* scan-build */ + free(packmem); + packmem = NULL; /* packmemlen = 0; */ /* scan-build */ -prevpos = 0; zerocnt = 0; -free(scratchpad); scratchpad = NULL; + prevpos = 0; + zerocnt = 0; + free(scratchpad); + scratchpad = NULL; -indxpos = ftello(f); -xc->secnum++; + indxpos = ftello(f); + xc->secnum++; #ifndef FST_DYNAMIC_ALIAS2_DISABLE -if(1) - { + if (1) { uint32_t prev_alias = 0; - for(i=0;imaxhandle;i++) - { - vm4ip = &(xc->valpos_mem[4*i]); + for (i = 0; i < xc->maxhandle; i++) { + vm4ip = &(xc->valpos_mem[4 * i]); - if(vm4ip[2]) - { - if(zerocnt) - { - fpos += fstWriterVarint(f, (zerocnt << 1)); - zerocnt = 0; - } - - if(vm4ip[2] & 0x80000000) - { - if(vm4ip[2] != prev_alias) - { - int32_t t_i32 = ((int32_t)(prev_alias = vm4ip[2])); /* vm4ip is generic unsigned data */ - int64_t t_i64 = (int64_t)t_i32; /* convert to signed */ - uint64_t t_u64 = (uint64_t)t_i64; /* sign extend through 64b */ - - fpos += fstWriterSVarint(f, (int64_t)((t_u64 << 1) | 1)); /* all in this block was: 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++; - } + if (vm4ip[2]) { + if (zerocnt) { + fpos += fstWriterVarint(f, (zerocnt << 1)); + zerocnt = 0; } + + if (vm4ip[2] & 0x80000000) { + if (vm4ip[2] != prev_alias) { + int32_t t_i32 = + ((int32_t)(prev_alias = vm4ip[2])); /* vm4ip is generic unsigned data */ + int64_t t_i64 = (int64_t)t_i32; /* convert to signed */ + uint64_t t_u64 = (uint64_t)t_i64; /* sign extend through 64b */ + + fpos += fstWriterSVarint( + f, + (int64_t)((t_u64 << 1) | + 1)); /* all in this block was: 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 + } else #endif - { - for(i=0;imaxhandle;i++) - { - vm4ip = &(xc->valpos_mem[4*i]); + { + for (i = 0; i < xc->maxhandle; 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 (vm4ip[2]) { + if (zerocnt) { + fpos += fstWriterVarint(f, (zerocnt << 1)); + zerocnt = 0; } - } -if(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 */ - } + } #ifdef FST_DEBUG -fprintf(stderr, FST_APIMESS "value chains: %d\n", cnt); + fprintf(stderr, FST_APIMESS "value chains: %d\n", cnt); #endif -xc->vchg_mem[0] = '!'; -xc->vchg_siz = 1; + 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 */ + endpos = ftello(xc->handle); + fstWriterUint64(xc->handle, + endpos - indxpos); /* write delta index position at very end of block */ -/*emit time changes for block */ -fflush(xc->tchn_handle); -tlen = ftello(xc->tchn_handle); -fstWriterFseeko(xc, xc->tchn_handle, 0, SEEK_SET); + /*emit time changes for block */ + fflush(xc->tchn_handle); + tlen = ftello(xc->tchn_handle); + fstWriterFseeko(xc, xc->tchn_handle, 0, SEEK_SET); -errno = 0; -fstWriterMmapSanity(tmem = (unsigned char *)fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->tchn_handle), 0), __FILE__, __LINE__, "tmem"); -if(tmem) - { + errno = 0; + fstWriterMmapSanity( + tmem = (unsigned char *) + fstMmap(NULL, tlen, PROT_READ | PROT_WRITE, MAP_SHARED, fileno(xc->tchn_handle), 0), + __FILE__, + __LINE__, + "tmem"); + if (tmem) { unsigned long destlen = tlen; unsigned char *dmem = (unsigned char *)malloc(compressBound(destlen)); int rc = compress2(dmem, &destlen, tmem, tlen, 9); - if((rc == Z_OK) && (((fst_off_t)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; - } + if ((rc == Z_OK) && (((fst_off_t)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 */ - } + 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); -fstFtruncate(fileno(xc->tchn_handle), 0); + xc->tchn_cnt = xc->tchn_idx = 0; + fstWriterFseeko(xc, xc->tchn_handle, 0, SEEK_SET); + 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 */ -fflush(xc->handle); + /* 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 */ + 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 -fputc(FST_BL_VCDATA_DYN_ALIAS2, xc->handle); + fputc(FST_BL_VCDATA_DYN_ALIAS2, xc->handle); #else -fputc(FST_BL_VCDATA_DYN_ALIAS, xc->handle); + fputc(FST_BL_VCDATA_DYN_ALIAS, xc->handle); #endif #else -fputc(FST_BL_VCDATA, xc->handle); + fputc(FST_BL_VCDATA, xc->handle); #endif -fflush(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 */ -if(xc->dump_size_limit) - { - if(endpos >= ((fst_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 */ + xc2->section_header_truncpos = endpos; /* cache in case of need to truncate */ + if (xc->dump_size_limit) { + if (endpos >= ((fst_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, FST_APIMESS "<< dump file size limit reached, stopping dumping >>\n"); + fprintf(stderr, FST_APIMESS "<< dump file size limit reached, stopping dumping >>\n"); #endif - } } + } -if(!xc2->skip_writing_section_hdr) - { - fstWriterEmitSectionHeader(xc); /* emit next section header */ - } -fflush(xc->handle); + if (!xc2->skip_writing_section_hdr) { + fstWriterEmitSectionHeader(xc); /* emit next section header */ + } + fflush(xc->handle); -xc->already_in_flush = 0; + xc->already_in_flush = 0; } - #ifdef FST_WRITER_PARALLEL static void *fstWriterFlushContextPrivate1(void *ctx) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -struct fstWriterContext *xc_parent; + struct fstWriterContext *xc = (struct fstWriterContext *)ctx; + struct fstWriterContext *xc_parent; -pthread_mutex_lock(&(xc->xc_parent->mutex)); -fstWriterFlushContextPrivate2(xc); + pthread_mutex_lock(&(xc->xc_parent->mutex)); + fstWriterFlushContextPrivate2(xc); #ifdef FST_REMOVE_DUPLICATE_VC -free(xc->curval_mem); + free(xc->curval_mem); #endif -free(xc->valpos_mem); -free(xc->vchg_mem); -tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam); -xc_parent = xc->xc_parent; -free(xc); + free(xc->valpos_mem); + free(xc->vchg_mem); + tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam); + xc_parent = xc->xc_parent; + free(xc); -xc_parent->in_pthread = 0; -pthread_mutex_unlock(&(xc_parent->mutex)); + xc_parent->in_pthread = 0; + pthread_mutex_unlock(&(xc_parent->mutex)); -return(NULL); + return (NULL); } - -static void fstWriterFlushContextPrivate(void *ctx) +static void fstWriterFlushContextPrivate(fstWriterContext *xc) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; - -if(xc->parallel_enabled) - { - struct fstWriterContext *xc2 = (struct fstWriterContext *)malloc(sizeof(struct fstWriterContext)); + if (xc->parallel_enabled) { + struct fstWriterContext *xc2 = + (struct fstWriterContext *)malloc(sizeof(struct fstWriterContext)); unsigned int i; pthread_mutex_lock(&xc->mutex); @@ -1847,13 +1768,13 @@ if(xc->parallel_enabled) xc->xc_parent = xc; memcpy(xc2, xc, sizeof(struct fstWriterContext)); - if(sizeof(size_t) < sizeof(uint64_t)) - { - /* TALOS-2023-1777 for 32b overflow */ - uint64_t chk_64 = xc->maxhandle * 4 * sizeof(uint32_t); - size_t chk_32 = xc->maxhandle * 4 * sizeof(uint32_t); - if(chk_64 != chk_32) chk_report_abort("TALOS-2023-1777"); - } + if (sizeof(size_t) < sizeof(uint64_t)) { + /* TALOS-2023-1777 for 32b overflow */ + uint64_t chk_64 = xc->maxhandle * 4 * sizeof(uint32_t); + size_t chk_32 = xc->maxhandle * 4 * sizeof(uint32_t); + if (chk_64 != chk_32) + chk_report_abort("TALOS-2023-1777"); + } xc2->valpos_mem = (uint32_t *)malloc(xc->maxhandle * 4 * sizeof(uint32_t)); memcpy(xc2->valpos_mem, xc->valpos_mem, xc->maxhandle * 4 * sizeof(uint32_t)); @@ -1868,303 +1789,309 @@ if(xc->parallel_enabled) 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; i < xc->maxhandle; 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 */ + 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++; - while (xc->in_pthread) - { - pthread_mutex_lock(&xc->mutex); - pthread_mutex_unlock(&xc->mutex); - }; + while (xc->in_pthread) { + pthread_mutex_lock(&xc->mutex); + pthread_mutex_unlock(&xc->mutex); + }; pthread_mutex_lock(&xc->mutex); - xc->in_pthread = 1; + xc->in_pthread = 1; pthread_mutex_unlock(&xc->mutex); pthread_create(&xc->thread, &xc->thread_attr, fstWriterFlushContextPrivate1, xc2); - } - else + } else { + if (xc->parallel_was_enabled) /* conservatively block */ { - if(xc->parallel_was_enabled) /* conservatively block */ - { - pthread_mutex_lock(&xc->mutex); - pthread_mutex_unlock(&xc->mutex); - } + pthread_mutex_lock(&xc->mutex); + pthread_mutex_unlock(&xc->mutex); + } xc->xc_parent = xc; fstWriterFlushContextPrivate2(xc); - } + } } #endif - /* * queues up a flush context operation */ -void fstWriterFlushContext(void *ctx) +void fstWriterFlushContext(fstWriterContext *xc) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -if(xc) - { - if(xc->tchn_idx > 1) - { - xc->flush_context_pending = 1; - } + if (xc) { + if (xc->tchn_idx > 1) { + xc->flush_context_pending = 1; } + } } - /* * close out FST file */ -void fstWriterClose(void *ctx) +void fstWriterClose(fstWriterContext *xc) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; - #ifdef FST_WRITER_PARALLEL -if(xc) - { + if (xc) { pthread_mutex_lock(&xc->mutex); pthread_mutex_unlock(&xc->mutex); - } + } #endif -if(xc && !xc->already_in_close && !xc->already_in_flush) - { + if (xc && !xc->already_in_close && !xc->already_in_flush) { unsigned char *tmem = NULL; fst_off_t fixup_offs, tlen, hlen; 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)) + 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 (FST_UNLIKELY(xc->is_initial_time)) /* simulation time never advanced so mock up + the changes as time zero ones */ { - 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(FST_UNLIKELY(xc->is_initial_time)) /* simulation time never advanced so mock up the changes as time zero ones */ - { - fstHandle dupe_idx; + 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); - while (xc->in_pthread) - { - pthread_mutex_lock(&xc->mutex); - pthread_mutex_unlock(&xc->mutex); - }; + while (xc->in_pthread) { + pthread_mutex_lock(&xc->mutex); + pthread_mutex_unlock(&xc->mutex); + }; #endif - } - } + } + } fstDestroyMmaps(xc, 1); - if(xc->outval_mem) - { - free(xc->outval_mem); xc->outval_mem = NULL; - xc->outval_alloc_siz = 0; - } + if (xc->outval_mem) { + free(xc->outval_mem); + xc->outval_mem = NULL; + xc->outval_alloc_siz = 0; + } /* write out geom section */ fflush(xc->geom_handle); tlen = ftello(xc->geom_handle); - errno = 0; - if(tlen) - { - fstWriterMmapSanity(tmem = (unsigned char *)fstMmap(NULL, tlen, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->geom_handle), 0), __FILE__, __LINE__, "tmem"); - } + errno = 0; + if (tlen) { + fstWriterMmapSanity(tmem = (unsigned char *)fstMmap(NULL, + tlen, + PROT_READ | PROT_WRITE, + MAP_SHARED, + fileno(xc->geom_handle), + 0), + __FILE__, + __LINE__, + "tmem"); + } - if(tmem) - { - unsigned long destlen = tlen; - unsigned char *dmem = (unsigned char *)malloc(compressBound(destlen)); - int rc = compress2(dmem, &destlen, tmem, tlen, 9); + if (tmem) { + unsigned long destlen = tlen; + unsigned char *dmem = (unsigned char *)malloc(compressBound(destlen)); + int rc = compress2(dmem, &destlen, tmem, tlen, 9); - if((rc != Z_OK) || (((fst_off_t)destlen) > tlen)) - { - destlen = tlen; - } + if ((rc != Z_OK) || (((fst_off_t)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((((fst_off_t)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((((fst_off_t)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; - fst_off_t bpos, eos; - uint32_t i; + if (xc->num_blackouts) { + uint64_t cur_bl = 0; + fst_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; i < xc->num_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) - { - fst_off_t hl, eos; - gzFile zhandle; - int zfd; - int fourpack_duo = 0; + if (xc->compress_hier) { + fst_off_t hl, eos; + gzFile zhandle; + int zfd; + int fourpack_duo = 0; #ifndef __MINGW32__ - int fnam_len = strlen(xc->filename) + 5 + 1; - char *fnam = (char *)malloc(fnam_len); + int fnam_len = strlen(xc->filename) + 5 + 1; + char *fnam = (char *)malloc(fnam_len); #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 = (unsigned char *)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 = NULL; - int packed_len; + if (!xc->fourpack) { + unsigned char *mem = (unsigned char *)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 = NULL; + int packed_len; - fflush(xc->handle); - - lz4_maxlen = LZ4_compressBound(xc->hier_file_len); - mem = (unsigned char *)malloc(lz4_maxlen); - errno = 0; - if(xc->hier_file_len) - { - fstWriterMmapSanity(hmem = (unsigned char *)fstMmap(NULL, xc->hier_file_len, PROT_READ|PROT_WRITE, MAP_SHARED, fileno(xc->hier_handle), 0), __FILE__, __LINE__, "hmem"); - } - packed_len = LZ4_compress_default((char *)hmem, (char *)mem, xc->hier_file_len, lz4_maxlen); - 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 = (unsigned char *)malloc(lz4_maxlen_duo); - packed_len_duo = LZ4_compress_default((char *)mem, (char *)mem_duo, packed_len, lz4_maxlen_duo); - - 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); - } - - 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 */ + lz4_maxlen = LZ4_compressBound(xc->hier_file_len); + mem = (unsigned char *)malloc(lz4_maxlen); + errno = 0; + if (xc->hier_file_len) { + fstWriterMmapSanity(hmem = (unsigned char *)fstMmap(NULL, + xc->hier_file_len, + PROT_READ | PROT_WRITE, + MAP_SHARED, + fileno(xc->hier_handle), + 0), + __FILE__, + __LINE__, + "hmem"); + } + packed_len = + LZ4_compress_default((char *)hmem, (char *)mem, xc->hier_file_len, lz4_maxlen); + fstMunmap(hmem, xc->hier_file_len); - fstWriterFseeko(xc, xc->handle, 0, SEEK_END); /* move file pointer to end for any section adds */ - fflush(xc->handle); + 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 = (unsigned char *)malloc(lz4_maxlen_duo); + packed_len_duo = LZ4_compress_default((char *)mem, + (char *)mem_duo, + packed_len, + lz4_maxlen_duo); + + 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); + } + + 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, + 0, + SEEK_END); /* move file pointer to end for any section adds */ + fflush(xc->handle); #ifndef __MINGW32__ - snprintf(fnam, fnam_len, "%s.hier", xc->filename); - unlink(fnam); - free(fnam); + snprintf(fnam, fnam_len, "%s.hier", xc->filename); + unlink(fnam); + free(fnam); #endif - } + } /* finalize out header */ fstWriterFseeko(xc, xc->handle, FST_HDR_OFFS_START_TIME, SEEK_SET); @@ -2178,92 +2105,88 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) fflush(xc->handle); tmpfile_close(&xc->tchn_handle, &xc->tchn_handle_nam); - free(xc->vchg_mem); xc->vchg_mem = NULL; + 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; - fst_off_t offpnt, uclen; - int flen = strlen(xc->filename); - char *hf = (char *)calloc(1, flen + 5); + if (xc->hier_handle) { + fclose(xc->hier_handle); + xc->hier_handle = NULL; + } + if (xc->handle) { + if (xc->repack_on_close) { + FILE *fp; + fst_off_t offpnt, uclen; + int flen = strlen(xc->filename); + char *hf = (char *)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) - { - gzFile dsth; - int zfd; - char gz_membuf[FST_GZIO_LEN]; + if (fp) { + gzFile 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; - - 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; + 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; } + free(hf); + } else { + fclose(xc->handle); + xc->handle = NULL; + } + } + #ifdef __MINGW32__ { - int flen = strlen(xc->filename); - char *hf = (char *)calloc(1, flen + 6); - strcpy(hf, xc->filename); + int flen = strlen(xc->filename); + char *hf = (char *)calloc(1, flen + 6); + strcpy(hf, xc->filename); - if(xc->compress_hier) - { + 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 @@ -2272,28 +2195,23 @@ if(xc && !xc->already_in_close && !xc->already_in_flush) pthread_attr_destroy(&xc->thread_attr); #endif - if(xc->path_array) - { -#ifndef _WAVE_HAVE_JUDY - const uint32_t hashmask = FST_PATH_HASHMASK; -#endif - JudyHSFreeArray(&(xc->path_array), NULL); - } - - free(xc->filename); xc->filename = NULL; - free(xc); + if (xc->path_array) { + const uint32_t hashmask = FST_PATH_HASHMASK; + JenkinsFree(&(xc->path_array), hashmask); } -} + free(xc->filename); + xc->filename = NULL; + free(xc); + } +} /* * functions to set miscellaneous header/block information */ -void fstWriterSetDate(void *ctx, const char *dat) +void fstWriterSetDate(fstWriterContext *xc, const char *dat) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -if(xc) - { + if (xc) { char s[FST_HDR_DATE_SIZE]; fst_off_t fpos = ftello(xc->handle); int len = strlen(dat); @@ -2304,15 +2222,12 @@ if(xc) fstFwrite(s, FST_HDR_DATE_SIZE, 1, xc->handle); fflush(xc->handle); fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET); - } + } } - -void fstWriterSetVersion(void *ctx, const char *vers) +void fstWriterSetVersion(fstWriterContext *xc, const char *vers) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -if(xc && vers) - { + if (xc && vers) { char s[FST_HDR_SIM_VERSION_SIZE]; fst_off_t fpos = ftello(xc->handle); int len = strlen(vers); @@ -2323,972 +2238,935 @@ if(xc && vers) fstFwrite(s, FST_HDR_SIM_VERSION_SIZE, 1, xc->handle); fflush(xc->handle); fstWriterFseeko(xc, xc->handle, fpos, SEEK_SET); - } + } } - -void fstWriterSetFileType(void *ctx, enum fstFileType filetype) +void fstWriterSetFileType(fstWriterContext *xc, enum fstFileType filetype) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -if(xc) - { - if(/*(filetype >= FST_FT_MIN) &&*/ (filetype <= FST_FT_MAX)) - { - fst_off_t fpos = ftello(xc->handle); + if (xc) { + if (/*(filetype >= FST_FT_MIN) &&*/ (filetype <= FST_FT_MAX)) { + fst_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); } + } } - -static void fstWriterSetAttrDoubleArgGeneric(void *ctx, int typ, uint64_t arg1, uint64_t arg2) +static void fstWriterSetAttrDoubleArgGeneric(fstWriterContext *xc, + int typ, + uint64_t arg1, + uint64_t arg2) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -if(xc) - { + 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 */ - } + 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); - } + } } - -static void fstWriterSetAttrGeneric(void *ctx, const char *comm, int typ, uint64_t arg) +static void fstWriterSetAttrGeneric(fstWriterContext *xc, const char *comm, int typ, uint64_t arg) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -if(xc && comm) - { + if (xc && comm) { 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); - } + } } - -static void fstWriterSetSourceStem_2(void *ctx, const char *path, unsigned int line, unsigned int use_realpath, int typ) +static void fstWriterSetSourceStem_2(fstWriterContext *xc, + const char *path, + unsigned int line, + unsigned int use_realpath, + int typ) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; - -if(xc && path && path[0]) - { + if (xc && path && path[0]) { 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; - PPvoid_t pv; -#else - char *path2 = (char *)alloca(slen + 1); /* judy lacks const qualifier in its JudyHSIns definition */ - PPvoid_t pv; - strcpy(path2, path); -#endif + PPvoid_t pv; - pv = JudyHSIns(&(xc->path_array), path2, slen, NULL); - if(*pv) - { - sidx = (intptr_t)(*pv); - } - else - { - char *rp = NULL; + pv = JenkinsIns(&(xc->path_array), path2, slen, hashmask); + if (*pv) { + sidx = (intptr_t)(*pv); + } else { + char *rp = NULL; - sidx = ++xc->path_array_count; - *pv = (void *)(intptr_t)(xc->path_array_count); + sidx = ++xc->path_array_count; + *pv = (void *)(intptr_t)(xc->path_array_count); - if(use_realpath) - { - rp = fstRealpath( -#ifndef _WAVE_HAVE_JUDY - (const char *) -#endif - path2, NULL); - } + if (use_realpath) { + rp = fstRealpath((const char *)path2, NULL); + } - fstWriterSetAttrGeneric(xc, rp ? rp : -#ifndef _WAVE_HAVE_JUDY - (const char *) -#endif - path2, FST_MT_PATHNAME, sidx); + fstWriterSetAttrGeneric(xc, rp ? rp : (const char *)path2, FST_MT_PATHNAME, sidx); - if(rp) - { - free(rp); - } - } + if (rp) { + free(rp); + } + } fstWriterSetAttrDoubleArgGeneric(xc, typ, sidx, line); - } + } } - -void fstWriterSetSourceStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath) +void fstWriterSetSourceStem(fstWriterContext *ctx, + const char *path, + unsigned int line, + unsigned int use_realpath) { -fstWriterSetSourceStem_2(ctx, path, line, use_realpath, FST_MT_SOURCESTEM); + fstWriterSetSourceStem_2(ctx, path, line, use_realpath, FST_MT_SOURCESTEM); } - -void fstWriterSetSourceInstantiationStem(void *ctx, const char *path, unsigned int line, unsigned int use_realpath) +void fstWriterSetSourceInstantiationStem(fstWriterContext *ctx, + const char *path, + unsigned int line, + unsigned int use_realpath) { -fstWriterSetSourceStem_2(ctx, path, line, use_realpath, FST_MT_SOURCEISTEM); + fstWriterSetSourceStem_2(ctx, path, line, use_realpath, FST_MT_SOURCEISTEM); } - -void fstWriterSetComment(void *ctx, const char *comm) +void fstWriterSetComment(fstWriterContext *ctx, const char *comm) { -fstWriterSetAttrGeneric(ctx, comm, FST_MT_COMMENT, 0); + fstWriterSetAttrGeneric(ctx, comm, FST_MT_COMMENT, 0); } - -void fstWriterSetValueList(void *ctx, const char *vl) +void fstWriterSetValueList(fstWriterContext *ctx, const char *vl) { -fstWriterSetAttrGeneric(ctx, vl, FST_MT_VALUELIST, 0); + fstWriterSetAttrGeneric(ctx, vl, FST_MT_VALUELIST, 0); } - -void fstWriterSetEnvVar(void *ctx, const char *envvar) +void fstWriterSetEnvVar(fstWriterContext *ctx, const char *envvar) { -fstWriterSetAttrGeneric(ctx, envvar, FST_MT_ENVVAR, 0); + fstWriterSetAttrGeneric(ctx, envvar, FST_MT_ENVVAR, 0); } - -void fstWriterSetTimescale(void *ctx, int ts) +void fstWriterSetTimescale(fstWriterContext *xc, int ts) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -if(xc) - { + if (xc) { fst_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); - } + } } - -void fstWriterSetTimescaleFromString(void *ctx, const char *s) +void fstWriterSetTimescaleFromString(fstWriterContext *xc, const char *s) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -if(xc && s) - { + if (xc && s) { int mat = 0; int seconds_exp = -9; int tv = atoi(s); const char *pnt = s; - 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; - case 'p': seconds_exp = -12; mat = 1; break; - case 'f': seconds_exp = -15; mat = 1; break; - case 'a': seconds_exp = -18; mat = 1; break; - case 'z': seconds_exp = -21; mat = 1; break; - case 's': seconds_exp = 0; mat = 1; break; - default: break; - } + 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; + case 'p': + seconds_exp = -12; + mat = 1; + break; + case 'f': + seconds_exp = -15; + mat = 1; + break; + case 'a': + seconds_exp = -18; + mat = 1; + break; + case 'z': + seconds_exp = -21; + mat = 1; + break; + case 's': + seconds_exp = 0; + mat = 1; + break; + default: + break; + } - if(mat) break; - pnt++; - } - - if(tv == 10) - { - seconds_exp++; - } - else - if(tv == 100) - { - seconds_exp+=2; - } - - fstWriterSetTimescale(ctx, seconds_exp); + if (mat) + break; + pnt++; } + + if (tv == 10) { + seconds_exp++; + } else if (tv == 100) { + seconds_exp += 2; + } + + fstWriterSetTimescale(xc, seconds_exp); + } } - -void fstWriterSetTimezero(void *ctx, int64_t tim) +void fstWriterSetTimezero(fstWriterContext *xc, int64_t tim) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -if(xc) - { + if (xc) { fst_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); - } + } } - -void fstWriterSetPackType(void *ctx, enum fstWriterPackType typ) +void fstWriterSetPackType(fstWriterContext *xc, 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); - } + if (xc) { + xc->fastpack = (typ != FST_WR_PT_ZLIB); + xc->fourpack = (typ == FST_WR_PT_LZ4); + } } - -void fstWriterSetRepackOnClose(void *ctx, int enable) +void fstWriterSetRepackOnClose(fstWriterContext *xc, int enable) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -if(xc) - { + if (xc) { xc->repack_on_close = (enable != 0); - } + } } - -void fstWriterSetParallelMode(void *ctx, int enable) +void fstWriterSetParallelMode(fstWriterContext *xc, int enable) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -if(xc) - { + if (xc) { xc->parallel_was_enabled |= xc->parallel_enabled; /* make sticky */ xc->parallel_enabled = (enable != 0); #ifndef FST_WRITER_PARALLEL - if(xc->parallel_enabled) - { - fprintf(stderr, FST_APIMESS "fstWriterSetParallelMode(), FST_WRITER_PARALLEL not enabled during compile, exiting.\n"); - exit(255); - } + if (xc->parallel_enabled) { + fprintf(stderr, + FST_APIMESS "fstWriterSetParallelMode(), FST_WRITER_PARALLEL not enabled " + "during compile, exiting.\n"); + exit(255); + } #endif - } + } } - -void fstWriterSetDumpSizeLimit(void *ctx, uint64_t numbytes) +void fstWriterSetDumpSizeLimit(fstWriterContext *xc, uint64_t numbytes) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -if(xc) - { + if (xc) { xc->dump_size_limit = numbytes; - } + } } - -int fstWriterGetDumpSizeLimitReached(void *ctx) +int fstWriterGetDumpSizeLimitReached(fstWriterContext *xc) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -if(xc) - { - return(xc->size_limit_locked != 0); - } + if (xc) { + return (xc->size_limit_locked != 0); + } -return(0); + return (0); } - -int fstWriterGetFseekFailed(void *ctx) +int fstWriterGetFseekFailed(fstWriterContext *xc) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -if(xc) - { - return(xc->fseek_failed != 0); - } + if (xc) { + return (xc->fseek_failed != 0); + } -return(0); + return (0); } +static int fstWriterGetFlushContextPendingInternal(fstWriterContext *xc) +{ + return (xc->vchg_siz >= xc->fst_break_size) || (xc->flush_context_pending); +} + +int fstWriterGetFlushContextPending(fstWriterContext *xc) +{ + return xc && !xc->is_initial_time && fstWriterGetFlushContextPendingInternal(xc); +} /* * writer attr/scope/var creation: * fstWriterCreateVar2() is used to dump VHDL or other languages, but the * underlying variable needs to map to Verilog/SV via the proper fstVarType vt */ -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) +fstHandle fstWriterCreateVar2(fstWriterContext *ctx, + enum fstVarType vt, + enum fstVarDir vd, + uint32_t len, + const char *nam, + fstHandle aliasHandle, + const char *type, + enum fstSupplementalVarType svt, + enum fstSupplementalDataType sdt) { -fstWriterSetAttrGeneric(ctx, type ? type : "", FST_MT_SUPVAR, (svt<valpos_mem) - { - fstDestroyMmaps(xc, 0); - } + if (xc && nam) { + 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); + 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); - if(aliasHandle > xc->maxhandle) aliasHandle = 0; + 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 (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 = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz); - } - } - } - - 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 */ - } - - 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 */ - } - - xc->maxvalpos+=len; - xc->maxhandle++; - return(xc->maxhandle); - } - else - { - return(aliasHandle); + xc->vchg_alloc_siz = xc->fst_break_size + xc->fst_break_add_size; + if (xc->vchg_mem) { + xc->vchg_mem = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz); } + } } -return(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 */ + } + + 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; i < len; i++) { + fputc('x', xc->curval_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); + } + } + + return (0); } - -void fstWriterSetScope(void *ctx, enum fstScopeType scopetype, - const char *scopename, const char *scopecomp) +void fstWriterSetScope(fstWriterContext *xc, + enum fstScopeType scopetype, + const char *scopename, + const char *scopecomp) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; - -if(xc) - { + 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; } + 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); + 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++; - } + } } - -void fstWriterSetUpscope(void *ctx) +void fstWriterSetUpscope(fstWriterContext *xc) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; - -if(xc) - { + if (xc) { fputc(FST_ST_VCD_UPSCOPE, xc->hier_handle); xc->hier_file_len++; - } + } } - -void fstWriterSetAttrBegin(void *ctx, enum fstAttrType attrtype, int subtype, - const char *attrname, uint64_t arg) +void fstWriterSetAttrBegin(fstWriterContext *xc, + enum fstAttrType attrtype, + int subtype, + const char *attrname, + uint64_t arg) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; - -if(xc) - { + 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; } + 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); + fprintf(xc->hier_handle, "%s%c", attrname ? attrname : "", 0); - 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); + 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); + } } - -void fstWriterSetAttrEnd(void *ctx) +void fstWriterSetAttrEnd(fstWriterContext *xc) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; - -if(xc) - { + if (xc) { fputc(FST_ST_GEN_ATTREND, xc->hier_handle); xc->hier_file_len++; - } + } } - -fstEnumHandle fstWriterCreateEnumTable(void *ctx, const char *name, uint32_t elem_count, unsigned int min_valbits, const char **literal_arr, const char **val_arr) +fstEnumHandle fstWriterCreateEnumTable(fstWriterContext *xc, + const char *name, + uint32_t elem_count, + unsigned int min_valbits, + const char **literal_arr, + const char **val_arr) { -fstEnumHandle handle = 0; -unsigned int *literal_lens = NULL; -unsigned int *val_lens = NULL; -int lit_len_tot = 0; -int val_len_tot = 0; -int name_len; -char elem_count_buf[16]; -int elem_count_len; -int total_len; -int pos = 0; -char *attr_str = NULL; + fstEnumHandle handle = 0; + unsigned int *literal_lens = NULL; + unsigned int *val_lens = NULL; + int lit_len_tot = 0; + int val_len_tot = 0; + int name_len; + char elem_count_buf[16]; + int elem_count_len; + int total_len; + int pos = 0; + char *attr_str = NULL; -if(ctx && name && literal_arr && val_arr && (elem_count != 0)) - { - struct fstWriterContext *xc = (struct fstWriterContext *)ctx; + if (xc && name && literal_arr && val_arr && (elem_count != 0)) { + uint32_t i; - uint32_t i; + name_len = strlen(name); + elem_count_len = snprintf(elem_count_buf, 16, "%" PRIu32, elem_count); - name_len = strlen(name); - elem_count_len = snprintf(elem_count_buf, 16, "%" PRIu32, elem_count); + literal_lens = (unsigned int *)calloc(elem_count, sizeof(unsigned int)); + val_lens = (unsigned int *)calloc(elem_count, sizeof(unsigned int)); - literal_lens = (unsigned int *)calloc(elem_count, sizeof(unsigned int)); - val_lens = (unsigned int *)calloc(elem_count, sizeof(unsigned int)); + for (i = 0; i < elem_count; i++) { + literal_lens[i] = strlen(literal_arr[i]); + lit_len_tot += + fstUtilityBinToEscConvertedLen((unsigned char *)literal_arr[i], literal_lens[i]); - for(i=0;i 0) { + if (val_lens[i] < min_valbits) { + val_len_tot += + (min_valbits - + val_lens[i]); /* additional converted len is same for '0' character */ + } + } + } - if(min_valbits > 0) - { - if(val_lens[i] < min_valbits) - { - val_len_tot += (min_valbits - val_lens[i]); /* additional converted len is same for '0' character */ - } - } - } + total_len = + name_len + 1 + elem_count_len + 1 + lit_len_tot + elem_count + val_len_tot + elem_count; - total_len = name_len + 1 + elem_count_len + 1 + lit_len_tot + elem_count + val_len_tot + elem_count; + attr_str = (char *)malloc(total_len); + pos = 0; - attr_str = (char*)malloc(total_len); - pos = 0; + memcpy(attr_str + pos, name, name_len); + pos += name_len; + attr_str[pos++] = ' '; - memcpy(attr_str+pos, name, name_len); - pos += name_len; - attr_str[pos++] = ' '; + memcpy(attr_str + pos, elem_count_buf, elem_count_len); + pos += elem_count_len; + attr_str[pos++] = ' '; - memcpy(attr_str+pos, elem_count_buf, elem_count_len); - pos += elem_count_len; - attr_str[pos++] = ' '; + for (i = 0; i < elem_count; i++) { + pos += fstUtilityBinToEsc((unsigned char *)attr_str + pos, + (unsigned char *)literal_arr[i], + literal_lens[i]); + attr_str[pos++] = ' '; + } - for(i=0;i 0) { + if (val_lens[i] < min_valbits) { + memset(attr_str + pos, '0', min_valbits - val_lens[i]); + pos += (min_valbits - val_lens[i]); + } + } - for(i=0;i 0) - { - if(val_lens[i] < min_valbits) - { - memset(attr_str+pos, '0', min_valbits - val_lens[i]); - pos += (min_valbits - val_lens[i]); - } - } + pos += fstUtilityBinToEsc((unsigned char *)attr_str + pos, + (unsigned char *)val_arr[i], + val_lens[i]); + attr_str[pos++] = ' '; + } - pos += fstUtilityBinToEsc((unsigned char*)attr_str+pos, (unsigned char*)val_arr[i], val_lens[i]); - attr_str[pos++] = ' '; - } - - attr_str[pos-1] = 0; + attr_str[pos - 1] = 0; #ifdef FST_DEBUG - fprintf(stderr, FST_APIMESS "fstWriterCreateEnumTable() total_len: %d, pos: %d\n", total_len, pos); - fprintf(stderr, FST_APIMESS "*%s*\n", attr_str); + fprintf(stderr, + FST_APIMESS "fstWriterCreateEnumTable() total_len: %d, pos: %d\n", + total_len, + pos); + fprintf(stderr, FST_APIMESS "*%s*\n", attr_str); #endif - fstWriterSetAttrBegin(xc, FST_AT_MISC, FST_MT_ENUMTABLE, attr_str, handle = ++xc->max_enumhandle); + fstWriterSetAttrBegin(xc, + FST_AT_MISC, + FST_MT_ENUMTABLE, + attr_str, + handle = ++xc->max_enumhandle); - free(attr_str); - free(val_lens); - free(literal_lens); - } + free(attr_str); + free(val_lens); + free(literal_lens); + } -return(handle); + return (handle); } - -void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle) +void fstWriterEmitEnumTableRef(fstWriterContext *xc, fstEnumHandle handle) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -if(xc && handle) - { - fstWriterSetAttrBegin(xc, FST_AT_MISC, FST_MT_ENUMTABLE, NULL, handle); - } + if (xc && handle) { + fstWriterSetAttrBegin(xc, FST_AT_MISC, FST_MT_ENUMTABLE, NULL, handle); + } } - /* * value and time change emission */ -void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val) +void fstWriterEmitValueChange(fstWriterContext *xc, fstHandle handle, const void *val) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -const unsigned char *buf = (const unsigned char *)val; -uint32_t offs; -int len; + const unsigned char *buf = (const unsigned char *)val; + uint32_t offs; + int len; -if(FST_LIKELY((xc) && (handle <= xc->maxhandle))) - { + if (FST_LIKELY((xc) && (handle <= xc->maxhandle))) { uint32_t fpos; uint32_t *vm4ip; - if(FST_UNLIKELY(!xc->valpos_mem)) - { - xc->vc_emitted = 1; - fstWriterCreateMmaps(xc); - } + if (FST_UNLIKELY(!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]); + vm4ip = &(xc->valpos_mem[4 * handle]); - len = vm4ip[1]; - if(FST_LIKELY(len)) /* len of zero = variable length, use fstWriterEmitVariableLengthValueChange */ - { - if(FST_LIKELY(!xc->is_initial_time)) - { - fpos = xc->vchg_siz; - - if(FST_UNLIKELY((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 = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz); - if(FST_UNLIKELY(!xc->vchg_mem)) - { - fprintf(stderr, FST_APIMESS "Could not realloc() in fstWriterEmitValueChange, exiting.\n"); - exit(255); - } - } -#ifdef FST_REMOVE_DUPLICATE_VC - 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 */ - - 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); - } - 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; - } -#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); - } - } - } -} - -void fstWriterEmitValueChange32(void *ctx, fstHandle handle, - uint32_t bits, uint32_t val) { - char buf[32]; - char *s = buf; - uint32_t i; - for (i = 0; i < bits; ++i) + len = vm4ip[1]; + if (FST_LIKELY(len)) /* len of zero = variable length, use + fstWriterEmitVariableLengthValueChange */ { - *s++ = '0' + ((val >> (bits - i - 1)) & 1); - } - fstWriterEmitValueChange(ctx, handle, buf); -} -void fstWriterEmitValueChange64(void *ctx, fstHandle handle, - uint32_t bits, uint64_t val) { - char buf[64]; - char *s = buf; - uint32_t i; - for (i = 0; i < bits; ++i) - { - *s++ = '0' + ((val >> (bits - i - 1)) & 1); - } - fstWriterEmitValueChange(ctx, handle, buf); -} -void fstWriterEmitValueChangeVec32(void *ctx, fstHandle handle, - uint32_t bits, const uint32_t *val) { - struct fstWriterContext *xc = (struct fstWriterContext *)ctx; - if (FST_UNLIKELY(bits <= 32)) - { - fstWriterEmitValueChange32(ctx, handle, bits, val[0]); - } - else if(FST_LIKELY(xc)) - { - int bq = bits / 32; - int br = bits & 31; - int i; - int w; - uint32_t v; - unsigned char* s; - if (FST_UNLIKELY(bits > xc->outval_alloc_siz)) - { - xc->outval_alloc_siz = bits*2 + 1; - xc->outval_mem = (unsigned char*)realloc(xc->outval_mem, xc->outval_alloc_siz); - if (FST_UNLIKELY(!xc->outval_mem)) - { - fprintf(stderr, - FST_APIMESS "Could not realloc() in fstWriterEmitValueChangeVec32, exiting.\n"); - exit(255); - } - } - s = xc->outval_mem; - { - w = bq; - v = val[w]; - for (i = 0; i < br; ++i) - { - *s++ = '0' + ((v >> (br - i - 1)) & 1); - } - } - for (w = bq - 1; w >= 0; --w) - { - v = val[w]; - for (i = (32 - 4); i >= 0; i -= 4) { - s[0] = '0' + ((v >> (i + 3)) & 1); - s[1] = '0' + ((v >> (i + 2)) & 1); - s[2] = '0' + ((v >> (i + 1)) & 1); - s[3] = '0' + ((v >> (i + 0)) & 1); - s += 4; - } - } - fstWriterEmitValueChange(ctx, handle, xc->outval_mem); - } -} -void fstWriterEmitValueChangeVec64(void *ctx, fstHandle handle, - uint32_t bits, const uint64_t *val) { - struct fstWriterContext *xc = (struct fstWriterContext *)ctx; - if (FST_UNLIKELY(bits <= 64)) - { - fstWriterEmitValueChange64(ctx, handle, bits, val[0]); - } - else if(FST_LIKELY(xc)) - { - int bq = bits / 64; - int br = bits & 63; - int i; - int w; - uint32_t v; - unsigned char* s; - if (FST_UNLIKELY(bits > xc->outval_alloc_siz)) - { - xc->outval_alloc_siz = bits*2 + 1; - xc->outval_mem = (unsigned char*)realloc(xc->outval_mem, xc->outval_alloc_siz); - if (FST_UNLIKELY(!xc->outval_mem)) - { - fprintf(stderr, - FST_APIMESS "Could not realloc() in fstWriterEmitValueChangeVec64, exiting.\n"); - exit(255); - } - } - s = xc->outval_mem; - { - w = bq; - v = val[w]; - for (i = 0; i < br; ++i) - { - *s++ = '0' + ((v >> (br - i - 1)) & 1); - } - } - for (w = bq - 1; w >= 0; --w) { - v = val[w]; - for (i = (64 - 4); i >= 0; i -= 4) - { - s[0] = '0' + ((v >> (i + 3)) & 1); - s[1] = '0' + ((v >> (i + 2)) & 1); - s[2] = '0' + ((v >> (i + 1)) & 1); - s[3] = '0' + ((v >> (i + 0)) & 1); - s += 4; - } - } - fstWriterEmitValueChange(ctx, handle, xc->outval_mem); - } -} - - -void fstWriterEmitVariableLengthValueChange(void *ctx, fstHandle handle, const void *val, uint32_t len) -{ -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -const unsigned char *buf = (const unsigned char *)val; - -if(FST_LIKELY((xc) && (handle <= xc->maxhandle))) - { - uint32_t fpos; - uint32_t *vm4ip; - - if(FST_UNLIKELY(!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]); - - /* there is no initial time dump for variable length value changes */ - if(FST_LIKELY(!vm4ip[1])) /* len of zero = variable length */ - { + if (FST_LIKELY(!xc->is_initial_time)) { fpos = xc->vchg_siz; - if(FST_UNLIKELY((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 = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz); - if(FST_UNLIKELY(!xc->vchg_mem)) - { - fprintf(stderr, FST_APIMESS "Could not realloc() in fstWriterEmitVariableLengthValueChange, exiting.\n"); - exit(255); - } - } + if (FST_UNLIKELY((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 = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz); + if (FST_UNLIKELY(!xc->vchg_mem)) { + fprintf(stderr, + FST_APIMESS + "Could not realloc() in fstWriterEmitValueChange, exiting.\n"); + exit(255); + } + } +#ifdef FST_REMOVE_DUPLICATE_VC + offs = vm4ip[0]; - xc->vchg_siz += fstWriterUint32WithVarint32AndLength(xc, &vm4ip[2], xc->tchn_idx - vm4ip[3], buf, len); /* do one fwrite op only */ + 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; i < len; i++) { + if (buf[i] != 'x') + break; + } + + if (i < len) + return; + } else { + return; + } + } + } + + 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; + } +#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); + } } + } } - -void fstWriterEmitTimeChange(void *ctx, uint64_t tim) +void fstWriterEmitValueChange32(fstWriterContext *ctx, + fstHandle handle, + uint32_t bits, + uint32_t val) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; -unsigned int i; -int skip = 0; -if(xc) + char buf[32]; + char *s = buf; + uint32_t i; + for (i = 0; i < bits; ++i) { + *s++ = '0' + ((val >> (bits - i - 1)) & 1); + } + fstWriterEmitValueChange(ctx, handle, buf); +} + +void fstWriterEmitValueChange64(fstWriterContext *ctx, + fstHandle handle, + uint32_t bits, + uint64_t val) +{ + char buf[64]; + char *s = buf; + uint32_t i; + for (i = 0; i < bits; ++i) { + *s++ = '0' + ((val >> (bits - i - 1)) & 1); + } + fstWriterEmitValueChange(ctx, handle, buf); +} + +void fstWriterEmitValueChangeVec32(fstWriterContext *xc, + fstHandle handle, + uint32_t bits, + const uint32_t *val) +{ + if (FST_UNLIKELY(bits <= 32)) { + fstWriterEmitValueChange32(xc, handle, bits, val[0]); + } else if (FST_LIKELY(xc)) { + int bq = bits / 32; + int br = bits & 31; + int i; + int w; + uint32_t v; + unsigned char *s; + if (FST_UNLIKELY(bits > xc->outval_alloc_siz)) { + xc->outval_alloc_siz = bits * 2 + 1; + xc->outval_mem = (unsigned char *)realloc(xc->outval_mem, xc->outval_alloc_siz); + if (FST_UNLIKELY(!xc->outval_mem)) { + fprintf(stderr, + FST_APIMESS + "Could not realloc() in fstWriterEmitValueChangeVec32, exiting.\n"); + exit(255); + } + } + s = xc->outval_mem; { - if(FST_UNLIKELY(xc->is_initial_time)) - { - if(xc->size_limit_locked) /* this resets xc->is_initial_time to one */ - { - return; - } + w = bq; + v = val[w]; + for (i = 0; i < br; ++i) { + *s++ = '0' + ((v >> (br - i - 1)) & 1); + } + } + for (w = bq - 1; w >= 0; --w) { + v = val[w]; + for (i = (32 - 4); i >= 0; i -= 4) { + s[0] = '0' + ((v >> (i + 3)) & 1); + s[1] = '0' + ((v >> (i + 2)) & 1); + s[2] = '0' + ((v >> (i + 1)) & 1); + s[3] = '0' + ((v >> (i + 0)) & 1); + s += 4; + } + } + fstWriterEmitValueChange(xc, handle, xc->outval_mem); + } +} +void fstWriterEmitValueChangeVec64(fstWriterContext *xc, + fstHandle handle, + uint32_t bits, + const uint64_t *val) +{ + if (FST_UNLIKELY(bits <= 64)) { + fstWriterEmitValueChange64(xc, handle, bits, val[0]); + } else if (FST_LIKELY(xc)) { + int bq = bits / 64; + int br = bits & 63; + int i; + int w; + uint32_t v; + unsigned char *s; + if (FST_UNLIKELY(bits > xc->outval_alloc_siz)) { + xc->outval_alloc_siz = bits * 2 + 1; + xc->outval_mem = (unsigned char *)realloc(xc->outval_mem, xc->outval_alloc_siz); + if (FST_UNLIKELY(!xc->outval_mem)) { + fprintf(stderr, + FST_APIMESS + "Could not realloc() in fstWriterEmitValueChangeVec64, exiting.\n"); + exit(255); + } + } + s = xc->outval_mem; + { + w = bq; + v = val[w]; + for (i = 0; i < br; ++i) { + *s++ = '0' + ((v >> (br - i - 1)) & 1); + } + } + for (w = bq - 1; w >= 0; --w) { + v = val[w]; + for (i = (64 - 4); i >= 0; i -= 4) { + s[0] = '0' + ((v >> (i + 3)) & 1); + s[1] = '0' + ((v >> (i + 2)) & 1); + s[2] = '0' + ((v >> (i + 1)) & 1); + s[3] = '0' + ((v >> (i + 0)) & 1); + s += 4; + } + } + fstWriterEmitValueChange(xc, handle, xc->outval_mem); + } +} - if(!xc->valpos_mem) - { - fstWriterCreateMmaps(xc); - } +void fstWriterEmitVariableLengthValueChange(fstWriterContext *xc, + fstHandle handle, + const void *val, + uint32_t len) +{ + const unsigned char *buf = (const unsigned char *)val; - skip = 1; + if (FST_LIKELY((xc) && (handle <= xc->maxhandle))) { + uint32_t fpos; + uint32_t *vm4ip; - 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 (FST_UNLIKELY(!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]); + + /* there is no initial time dump for variable length value changes */ + if (FST_LIKELY(!vm4ip[1])) /* len of zero = variable length */ + { + fpos = xc->vchg_siz; + + if (FST_UNLIKELY((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 = (unsigned char *)realloc(xc->vchg_mem, xc->vchg_alloc_siz); + if (FST_UNLIKELY(!xc->vchg_mem)) { + fprintf(stderr, + FST_APIMESS "Could not realloc() in " + "fstWriterEmitVariableLengthValueChange, exiting.\n"); + exit(255); } + } - if(!skip) - { - xc->tchn_idx++; - } + 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(fstWriterContext *xc, uint64_t tim) +{ + unsigned int i; + int skip = 0; + if (xc) { + if (FST_UNLIKELY(xc->is_initial_time)) { + if (xc->size_limit_locked) /* this resets xc->is_initial_time to one */ + { + return; + } + + if (!xc->valpos_mem) { + fstWriterCreateMmaps(xc); + } + + 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; i < xc->maxhandle; 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 (fstWriterGetFlushContextPendingInternal(xc)) { + 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; - } + } } - -void fstWriterEmitDumpActive(void *ctx, int enable) +void fstWriterEmitDumpActive(fstWriterContext *xc, int enable) { -struct fstWriterContext *xc = (struct fstWriterContext *)ctx; - -if(xc) - { - struct fstBlackoutChain *b = (struct fstBlackoutChain *)calloc(1, sizeof(struct fstBlackoutChain)); + if (xc) { + struct fstBlackoutChain *b = + (struct fstBlackoutChain *)calloc(1, sizeof(struct fstBlackoutChain)); 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; - } + if (xc->blackout_curr) { + xc->blackout_curr->next = b; + xc->blackout_curr = b; + } else { + xc->blackout_head = b; + xc->blackout_curr = b; } + } } - /***********************/ /*** ***/ /*** reader function ***/ @@ -3299,591 +3177,490 @@ 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", - "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 *modtypes[] = {"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" - }; +static const char *attrtypes[] = {"misc", "array", "enum", "class"}; -static const char *arraytypes[] = { - "none", "unpacked", "packed", "sparse" - }; +static const char *arraytypes[] = {"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" - }; - -static const char *packtypes[] = { - "none", "unpacked", "packed", "tagged_packed" - }; +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"}; +static const char *packtypes[] = {"none", "unpacked", "packed", "tagged_packed"}; struct fstCurrHier { -struct fstCurrHier *prev; -void *user_info; -int len; + struct fstCurrHier *prev; + void *user_info; + int len; }; - struct fstReaderContext { -/* common entries */ + /* common entries */ -FILE *f, *fh; + FILE *f, *fh; -uint64_t start_time, end_time; -uint64_t mem_used_by_writer; -uint64_t scope_count; -uint64_t var_count; -fstHandle maxhandle; -uint64_t num_alias; -uint64_t vc_section_count; + uint64_t start_time, end_time; + uint64_t mem_used_by_writer; + uint64_t scope_count; + uint64_t var_count; + 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; + 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 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 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_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]; -int64_t timezero; + char version[FST_HDR_SIM_VERSION_SIZE + 1]; + char date[FST_HDR_DATE_SIZE + 1]; + int64_t timezero; -char *filename, *filename_unpacked; -fst_off_t hier_pos; + char *filename, *filename_unpacked; + fst_off_t hier_pos; -uint32_t num_blackouts; -uint64_t *blackout_times; -unsigned char *blackout_activity; + uint32_t num_blackouts; + uint64_t *blackout_times; + unsigned char *blackout_activity; -uint64_t limit_range_start, limit_range_end; + uint64_t limit_range_start, limit_range_end; -/* entries specific to read value at time functions */ + /* entries specific to read value at time functions */ -unsigned rvat_data_valid : 1; -uint64_t *rvat_time_table; -uint64_t rvat_beg_tim, rvat_end_tim; -unsigned char *rvat_frame_data; -uint64_t rvat_frame_maxhandle; -fst_off_t *rvat_chain_table; -uint32_t *rvat_chain_table_lengths; -uint64_t rvat_vc_maxhandle; -fst_off_t rvat_vc_start; -uint32_t *rvat_sig_offs; -int rvat_packtype; + unsigned rvat_data_valid : 1; + uint64_t *rvat_time_table; + uint64_t rvat_beg_tim, rvat_end_tim; + unsigned char *rvat_frame_data; + uint64_t rvat_frame_maxhandle; + fst_off_t *rvat_chain_table; + uint32_t *rvat_chain_table_lengths; + uint64_t rvat_vc_maxhandle; + fst_off_t rvat_vc_start; + uint32_t *rvat_sig_offs; + int rvat_packtype; -uint32_t rvat_chain_len; -unsigned char *rvat_chain_mem; -fstHandle rvat_chain_facidx; + uint32_t rvat_chain_len; + unsigned char *rvat_chain_mem; + fstHandle rvat_chain_facidx; -uint32_t rvat_chain_pos_tidx; -uint32_t rvat_chain_pos_idx; -uint64_t rvat_chain_pos_time; -unsigned rvat_chain_pos_valid : 1; + uint32_t rvat_chain_pos_tidx; + uint32_t rvat_chain_pos_idx; + uint64_t rvat_chain_pos_time; + unsigned rvat_chain_pos_valid : 1; -/* entries specific to hierarchy traversal */ + /* entries specific to hierarchy traversal */ -struct fstHier hier; -struct fstCurrHier *curr_hier; -fstHandle current_handle; -char *curr_flat_hier_nam; -int flat_hier_alloc_len; -unsigned do_rewind : 1; -char str_scope_nam[FST_ID_NAM_SIZ+1]; -char str_scope_comp[FST_ID_NAM_SIZ+1]; -char *str_scope_attr; + struct fstHier hier; + struct fstCurrHier *curr_hier; + fstHandle current_handle; + char *curr_flat_hier_nam; + int flat_hier_alloc_len; + unsigned do_rewind : 1; + char str_scope_nam[FST_ID_NAM_SIZ + 1]; + char str_scope_comp[FST_ID_NAM_SIZ + 1]; + char *str_scope_attr; -unsigned fseek_failed : 1; + unsigned fseek_failed : 1; -/* self-buffered I/O for writes */ + /* self-buffered I/O for writes */ #ifndef FST_WRITEX_DISABLE -int writex_pos; -int writex_fd; -unsigned char writex_buf[FST_WRITEX_MAX]; + int writex_pos; + int writex_fd; + unsigned char writex_buf[FST_WRITEX_MAX]; #endif -char *f_nam; -char *fh_nam; + char *f_nam; + char *fh_nam; }; - int fstReaderFseeko(struct fstReaderContext *xc, FILE *stream, fst_off_t offset, int whence) { -int rc = fseeko(stream, offset, whence); + int rc = fseeko(stream, offset, whence); -if(rc<0) - { + if (rc < 0) { xc->fseek_failed = 1; #ifdef FST_DEBUG fprintf(stderr, FST_APIMESS "Seek to #%" PRId64 " (whence = %d) failed!\n", offset, whence); perror("Why"); #endif - } + } -return(rc); + return (rc); } - #ifndef FST_WRITEX_DISABLE -static void fstWritex(struct fstReaderContext *xc, void *v, uint32_t len) /* TALOS-2023-1793: change len to unsigned */ +static void fstWritex(struct fstReaderContext *xc, + void *v, + uint32_t len) /* TALOS-2023-1793: change len to unsigned */ { -unsigned char *s = (unsigned char *)v; + 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 - { + if (len) { + if (len < FST_WRITEX_MAX) { + if (xc->writex_pos + len >= FST_WRITEX_MAX) { fstWritex(xc, NULL, 0); - if (write(xc->writex_fd, s, len)) { }; - } + } + + 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; - } + } 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 */ -static void fstReaderDeallocateScopeData(struct fstReaderContext *xc) +static void fstReaderDeallocateScopeData(fstReaderContext *xc) { -struct fstCurrHier *chp; + struct fstCurrHier *chp; -free(xc->curr_flat_hier_nam); xc->curr_flat_hier_nam = NULL; -while(xc->curr_hier) - { + 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; - } + } } - -const char *fstReaderGetCurrentFlatScope(void *ctx) +const char *fstReaderGetCurrentFlatScope(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -if(xc) - { - return(xc->curr_flat_hier_nam ? xc->curr_flat_hier_nam : ""); - } - else - { - return(NULL); - } + if (xc) { + return (xc->curr_flat_hier_nam ? xc->curr_flat_hier_nam : ""); + } else { + return (NULL); + } } - -void *fstReaderGetCurrentScopeUserInfo(void *ctx) +void *fstReaderGetCurrentScopeUserInfo(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -if(xc) - { - return(xc->curr_hier ? xc->curr_hier->user_info : NULL); - } - else - { - return(NULL); - } + if (xc) { + return (xc->curr_hier ? xc->curr_hier->user_info : NULL); + } else { + return (NULL); + } } - -const char *fstReaderPopScope(void *ctx) +const char *fstReaderPopScope(fstReaderContext *xc) { -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) - { - xc->curr_flat_hier_nam[xc->curr_hier->prev->len] = 0; - } - else - { - *xc->curr_flat_hier_nam = 0; - } + 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 (xc->curr_flat_hier_nam ? xc->curr_flat_hier_nam : ""); + } -return(NULL); + return (NULL); } - -void fstReaderResetScope(void *ctx) +void fstReaderResetScope(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; - -if(xc) - { - while(fstReaderPopScope(xc)); /* remove any already-built scoping info */ - } + if (xc) { + while (fstReaderPopScope(xc)) + ; /* remove any already-built scoping info */ + } } - -const char *fstReaderPushScope(void *ctx, const char *nam, void *user_info) +const char *fstReaderPushScope(fstReaderContext *xc, const char *nam, void *user_info) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -if(xc) - { + if (xc) { struct fstCurrHier *ch = (struct fstCurrHier *)malloc(sizeof(struct fstCurrHier)); int chl = xc->curr_hier ? xc->curr_hier->len : 0; int len = chl + 1 + strlen(nam); - if(len >= xc->flat_hier_alloc_len) - { - xc->curr_flat_hier_nam = xc->curr_flat_hier_nam ? (char *)realloc(xc->curr_flat_hier_nam, len+1) : (char *)malloc(len+1); - } + if (len >= xc->flat_hier_alloc_len) { + xc->curr_flat_hier_nam = xc->curr_flat_hier_nam + ? (char *)realloc(xc->curr_flat_hier_nam, len + 1) + : (char *)malloc(len + 1); + } - if(chl) - { - 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); - } + return (xc->curr_flat_hier_nam); + } -return(NULL); + return (NULL); } - -int fstReaderGetCurrentScopeLen(void *ctx) +int fstReaderGetCurrentScopeLen(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; + if (xc && xc->curr_hier) { + return (xc->curr_hier->len); + } -if(xc && xc->curr_hier) - { - return(xc->curr_hier->len); - } - -return(0); + return (0); } - -int fstReaderGetFseekFailed(void *ctx) +int fstReaderGetFseekFailed(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -if(xc) - { - return(xc->fseek_failed != 0); - } + if (xc) { + return (xc->fseek_failed != 0); + } -return(0); + return (0); } - /* * iter mask manipulation util functions */ -int fstReaderGetFacProcessMask(void *ctx, fstHandle facidx) +int fstReaderGetFacProcessMask(fstReaderContext *xc, fstHandle facidx) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; - -if(xc) - { + if (xc) { facidx--; - if(facidxmaxhandle) - { - int process_idx = facidx/8; - int process_bit = facidx&7; + if (facidx < xc->maxhandle) { + int process_idx = facidx / 8; + int process_bit = facidx & 7; - return( (xc->process_mask[process_idx]&(1<process_mask[process_idx] & (1 << process_bit)) != 0); } -return(0); + } + return (0); } - -void fstReaderSetFacProcessMask(void *ctx, fstHandle facidx) +void fstReaderSetFacProcessMask(fstReaderContext *xc, fstHandle facidx) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; - -if(xc) - { + if (xc) { facidx--; - if(facidxmaxhandle) - { - int idx = facidx/8; - int bitpos = facidx&7; + if (facidx < xc->maxhandle) { + int idx = facidx / 8; + int bitpos = facidx & 7; - xc->process_mask[idx] |= (1<process_mask[idx] |= (1 << bitpos); } + } } - -void fstReaderClrFacProcessMask(void *ctx, fstHandle facidx) +void fstReaderClrFacProcessMask(fstReaderContext *xc, fstHandle facidx) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; - -if(xc) - { + if (xc) { facidx--; - if(facidxmaxhandle) - { - int idx = facidx/8; - int bitpos = facidx&7; + if (facidx < xc->maxhandle) { + int idx = facidx / 8; + int bitpos = facidx & 7; - xc->process_mask[idx] &= (~(1<process_mask[idx] &= (~(1 << bitpos)); } + } } - -void fstReaderSetFacProcessMaskAll(void *ctx) +void fstReaderSetFacProcessMaskAll(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; - -if(xc) - { - memset(xc->process_mask, 0xff, (xc->maxhandle+7)/8); - } + if (xc) { + memset(xc->process_mask, 0xff, (xc->maxhandle + 7) / 8); + } } - -void fstReaderClrFacProcessMaskAll(void *ctx) +void fstReaderClrFacProcessMaskAll(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; - -if(xc) - { - memset(xc->process_mask, 0x00, (xc->maxhandle+7)/8); - } + if (xc) { + memset(xc->process_mask, 0x00, (xc->maxhandle + 7) / 8); + } } - /* * various utility read/write functions */ -signed char fstReaderGetTimescale(void *ctx) +signed char fstReaderGetTimescale(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -return(xc ? xc->timescale : 0); + return (xc ? xc->timescale : 0); } - -uint64_t fstReaderGetStartTime(void *ctx) +uint64_t fstReaderGetStartTime(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -return(xc ? xc->start_time : 0); + return (xc ? xc->start_time : 0); } - -uint64_t fstReaderGetEndTime(void *ctx) +uint64_t fstReaderGetEndTime(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -return(xc ? xc->end_time : 0); + return (xc ? xc->end_time : 0); } - -uint64_t fstReaderGetMemoryUsedByWriter(void *ctx) +uint64_t fstReaderGetMemoryUsedByWriter(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -return(xc ? xc->mem_used_by_writer : 0); + return (xc ? xc->mem_used_by_writer : 0); } - -uint64_t fstReaderGetScopeCount(void *ctx) +uint64_t fstReaderGetScopeCount(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -return(xc ? xc->scope_count : 0); + return (xc ? xc->scope_count : 0); } - -uint64_t fstReaderGetVarCount(void *ctx) +uint64_t fstReaderGetVarCount(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -return(xc ? xc->var_count : 0); + return (xc ? xc->var_count : 0); } - -fstHandle fstReaderGetMaxHandle(void *ctx) +fstHandle fstReaderGetMaxHandle(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -return(xc ? xc->maxhandle : 0); + return (xc ? xc->maxhandle : 0); } - -uint64_t fstReaderGetAliasCount(void *ctx) +uint64_t fstReaderGetAliasCount(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -return(xc ? xc->num_alias : 0); + return (xc ? xc->num_alias : 0); } - -uint64_t fstReaderGetValueChangeSectionCount(void *ctx) +uint64_t fstReaderGetValueChangeSectionCount(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -return(xc ? xc->vc_section_count : 0); + return (xc ? xc->vc_section_count : 0); } - -int fstReaderGetDoubleEndianMatchState(void *ctx) +int fstReaderGetDoubleEndianMatchState(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -return(xc ? xc->double_endian_match : 0); + return (xc ? xc->double_endian_match : 0); } - -const char *fstReaderGetVersionString(void *ctx) +const char *fstReaderGetVersionString(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -return(xc ? xc->version : NULL); + return (xc ? xc->version : NULL); } - -const char *fstReaderGetDateString(void *ctx) +const char *fstReaderGetDateString(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -return(xc ? xc->date : NULL); + return (xc ? xc->date : NULL); } - -int fstReaderGetFileType(void *ctx) +int fstReaderGetFileType(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -return(xc ? (int)xc->filetype : (int)FST_FT_VERILOG); + return (xc ? (int)xc->filetype : (int)FST_FT_VERILOG); } - -int64_t fstReaderGetTimezero(void *ctx) +int64_t fstReaderGetTimezero(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -return(xc ? xc->timezero : 0); + return (xc ? xc->timezero : 0); } - -uint32_t fstReaderGetNumberDumpActivityChanges(void *ctx) +uint32_t fstReaderGetNumberDumpActivityChanges(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -return(xc ? xc->num_blackouts : 0); + return (xc ? xc->num_blackouts : 0); } - -uint64_t fstReaderGetDumpActivityChangeTime(void *ctx, uint32_t idx) +uint64_t fstReaderGetDumpActivityChangeTime(fstReaderContext *xc, 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); - } + if (xc && (idx < xc->num_blackouts) && (xc->blackout_times)) { + return (xc->blackout_times[idx]); + } else { + return (0); + } } - -unsigned char fstReaderGetDumpActivityChangeValue(void *ctx, uint32_t idx) +unsigned char fstReaderGetDumpActivityChangeValue(fstReaderContext *xc, 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); - } + if (xc && (idx < xc->num_blackouts) && (xc->blackout_activity)) { + return (xc->blackout_activity[idx]); + } else { + return (0); + } } - -void fstReaderSetLimitTimeRange(void *ctx, uint64_t start_time, uint64_t end_time) +void fstReaderSetLimitTimeRange(fstReaderContext *xc, uint64_t start_time, uint64_t end_time) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; - -if(xc) - { + if (xc) { xc->limit_range_valid = 1; xc->limit_range_start = start_time; xc->limit_range_end = end_time; - } + } } - -void fstReaderSetUnlimitedTimeRange(void *ctx) +void fstReaderSetUnlimitedTimeRange(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; - -if(xc) - { + if (xc) { xc->limit_range_valid = 0; - } + } } - -void fstReaderSetVcdExtensions(void *ctx, int enable) +void fstReaderSetVcdExtensions(fstReaderContext *xc, int enable) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; - -if(xc) - { + if (xc) { xc->use_vcd_extensions = (enable != 0); - } + } } - -void fstReaderIterBlocksSetNativeDoublesOnCallback(void *ctx, int enable) +void fstReaderIterBlocksSetNativeDoublesOnCallback(fstReaderContext *xc, int enable) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -if(xc) - { + if (xc) { xc->native_doubles_for_cb = (enable != 0); - } + } } /* @@ -3891,45 +3668,41 @@ if(xc) */ static void fstVcdID(char *buf, unsigned int value) { -char *pnt = buf; + char *pnt = buf; -/* zero is illegal for a value...it is assumed they start at one */ -while (value) - { + /* zero is illegal for a value...it is assumed they start at one */ + while (value) { value--; *(pnt++) = (char)('!' + value % 94); value = value / 94; - } + } -*pnt = 0; + *pnt = 0; } static int fstVcdIDForFwrite(char *buf, unsigned int value) { -char *pnt = buf; - int len = 0; + char *pnt = buf; + int len = 0; -/* zero is illegal for a value...it is assumed they start at one */ -while (value && len < 14) - { + /* zero is illegal for a value...it is assumed they start at one */ + while (value && len < 14) { value--; - ++len; + ++len; *(pnt++) = (char)('!' + value % 94); value = value / 94; - } + } -return len; + return len; } - static int fstReaderRecreateHierFile(struct fstReaderContext *xc) { -int pass_status = 1; + int pass_status = 1; -if(!xc->fh) - { + if (!xc->fh) { fst_off_t offs_cache = ftello(xc->f); - int fnam_len = strlen(xc->filename) + 6 + 16 + 32 + 1; + int fnam_len = strlen(xc->filename) + 6 + 16 + 32 + 1; char *fnam = (char *)malloc(fnam_len); unsigned char *mem = (unsigned char *)malloc(FST_GZIO_LEN); fst_off_t hl, uclen; @@ -3939,15 +3712,11 @@ if(!xc->fh) 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; - } + 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; + } snprintf(fnam, fnam_len, "%s.hier_%d_%p", xc->filename, getpid(), (void *)xc); fstReaderFseeko(xc, xc->f, xc->hier_pos, SEEK_SET); @@ -3955,650 +3724,713 @@ if(!xc->fh) #ifndef __MINGW32__ 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"); - if(!xc->fh) + 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); - } - } + { + 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); + } + } #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; - } - - fwlen = fstFwrite(mem, len, 1, xc->fh); - if(fwlen != 1) - { - pass_status = 0; - break; - } - } - gzclose(zhandle); + if (gzreadlen != len) { + pass_status = 0; + break; } - else - if(htyp == FST_BL_HIER_LZ4DUO) - { - unsigned char *lz4_cmem = (unsigned char *)malloc(clen); - unsigned char *lz4_ucmem = (unsigned char *)malloc(uclen); - unsigned char *lz4_ucmem2; - uint64_t uclen2; - int skiplen2 = 0; - fstFread(lz4_cmem, clen, 1, xc->f); - - uclen2 = fstGetVarint64(lz4_cmem, &skiplen2); - lz4_ucmem2 = (unsigned char *)malloc(uclen2); - pass_status = (uclen2 == (uint64_t)LZ4_decompress_safe_partial ((char *)lz4_cmem + skiplen2, (char *)lz4_ucmem2, clen - skiplen2, uclen2, uclen2)); - if(pass_status) - { - 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; - } - } - - free(lz4_ucmem2); - free(lz4_ucmem); - free(lz4_cmem); + fwlen = fstFwrite(mem, len, 1, xc->fh); + if (fwlen != 1) { + pass_status = 0; + break; } - else - if(htyp == FST_BL_HIER_LZ4) - { - unsigned char *lz4_cmem = (unsigned char *)malloc(clen); - unsigned char *lz4_ucmem = (unsigned char *)malloc(uclen); + } + gzclose(zhandle); + } else if (htyp == FST_BL_HIER_LZ4DUO) { + unsigned char *lz4_cmem = (unsigned char *)malloc(clen); + unsigned char *lz4_ucmem = (unsigned char *)malloc(uclen); + unsigned char *lz4_ucmem2; + uint64_t uclen2; + int skiplen2 = 0; - 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); - if(fstFwrite(lz4_ucmem, uclen, 1, xc->fh) != 1) - { - pass_status = 0; - } + uclen2 = fstGetVarint64(lz4_cmem, &skiplen2); + lz4_ucmem2 = (unsigned char *)malloc(uclen2); + pass_status = + (uclen2 == (uint64_t)LZ4_decompress_safe_partial((char *)lz4_cmem + skiplen2, + (char *)lz4_ucmem2, + clen - skiplen2, + uclen2, + uclen2)); + if (pass_status) { + pass_status = (uclen == LZ4_decompress_safe_partial((char *)lz4_ucmem2, + (char *)lz4_ucmem, + uclen2, + uclen, + uclen)); - free(lz4_ucmem); - free(lz4_cmem); + if (fstFwrite(lz4_ucmem, uclen, 1, xc->fh) != 1) { + pass_status = 0; } - else /* FST_BL_SKIP */ - { + } + + free(lz4_ucmem2); + free(lz4_ucmem); + free(lz4_cmem); + } else if (htyp == FST_BL_HIER_LZ4) { + unsigned char *lz4_cmem = (unsigned char *)malloc(clen); + unsigned char *lz4_ucmem = (unsigned char *)malloc(uclen); + + fstFread(lz4_cmem, clen, 1, xc->f); + pass_status = (uclen == LZ4_decompress_safe_partial((char *)lz4_cmem, + (char *)lz4_ucmem, + clen, + uclen, + uclen)); + + if (fstFwrite(lz4_ucmem, uclen, 1, xc->fh) != 1) { pass_status = 0; - if(xc->fh) - { - fclose(xc->fh); xc->fh = NULL; /* needed in case .hier file is missing and there are no hier sections */ - } - } + } + + free(lz4_ucmem); + free(lz4_cmem); + } else /* FST_BL_SKIP */ + { + pass_status = 0; + if (xc->fh) { + fclose(xc->fh); + xc->fh = + NULL; /* needed in case .hier file is missing and there are no hier sections */ + } + } free(mem); free(fnam); fstReaderFseeko(xc, xc->f, offs_cache, SEEK_SET); - } + } -return(pass_status); + return (pass_status); } - -int fstReaderIterateHierRewind(void *ctx) +int fstReaderIterateHierRewind(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -int pass_status = 0; + int pass_status = 0; -if(xc) - { + if (xc) { pass_status = 1; - if(!xc->fh) - { - pass_status = fstReaderRecreateHierFile(xc); - } + if (!xc->fh) { + pass_status = fstReaderRecreateHierFile(xc); + } xc->do_rewind = 1; - } + } -return(pass_status); + return (pass_status); } - -struct fstHier *fstReaderIterateHier(void *ctx) +struct fstHier *fstReaderIterateHier(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -int isfeof; -fstHandle alias; -char *pnt; -int ch; + int isfeof; + fstHandle alias; + char *pnt; + int ch; + int unnamed_scope_idx = 0; -if(!xc) return(NULL); + if (!xc) + return (NULL); -if(!xc->fh) - { - if(!fstReaderRecreateHierFile(xc)) - { - return(NULL); - } + if (!xc->fh) { + if (!fstReaderRecreateHierFile(xc)) { + return (NULL); } + } -if(xc->do_rewind) - { + if (xc->do_rewind) { xc->do_rewind = 0; xc->current_handle = 0; fstReaderFseeko(xc, xc->fh, 0, SEEK_SET); clearerr(xc->fh); - } + } -if(!(isfeof=feof(xc->fh))) - { + if (!(isfeof = feof(xc->fh))) { int tag = fgetc(xc->fh); - int cl; - 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; - cl = 0; - while((ch = fgetc(xc->fh))) - { - if(cl < FST_ID_NAM_SIZ) - { - pnt[cl++] = ch; - } - }; /* scopename */ - pnt[cl] = 0; - xc->hier.u.scope.name_length = cl; - - xc->hier.u.scope.component = pnt = xc->str_scope_comp; - cl = 0; - while((ch = fgetc(xc->fh))) - { - if(cl < FST_ID_NAM_SIZ) - { - pnt[cl++] = ch; - } - }; /* scopecomp */ - pnt[cl] = 0; - xc->hier.u.scope.component_length = cl; - 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); - if(!xc->str_scope_attr) - { - xc->str_scope_attr = (char *)calloc(1, FST_ID_NAM_ATTR_SIZ+1); - } - xc->hier.u.attr.name = pnt = xc->str_scope_attr; - cl = 0; - while((ch = fgetc(xc->fh))) - { - if(cl < FST_ID_NAM_ATTR_SIZ) - { - pnt[cl++] = ch; - } - }; /* attrname */ - pnt[cl] = 0; - xc->hier.u.attr.name_length = cl; - - 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_attr, &sidx_skiplen_dummy); - } - } - 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; - cl = 0; - while((ch = fgetc(xc->fh))) - { - if(cl < FST_ID_NAM_SIZ) - { - pnt[cl++] = ch; - } - }; /* varname */ - pnt[cl] = 0; - xc->hier.u.var.name_length = cl; - 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); - - 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; - - default: - isfeof = 1; - break; + int cl; + 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; + cl = 0; + while ((ch = fgetc(xc->fh))) { + if (cl < FST_ID_NAM_SIZ) { + pnt[cl++] = ch; + } + }; /* scopename */ + if (!cl) { + cl = snprintf(pnt, FST_ID_NAM_SIZ, "$unnamed_scope_%d", unnamed_scope_idx++); } - } + pnt[cl] = 0; + xc->hier.u.scope.name_length = cl; -return(!isfeof ? &xc->hier : NULL); + xc->hier.u.scope.component = pnt = xc->str_scope_comp; + cl = 0; + while ((ch = fgetc(xc->fh))) { + if (cl < FST_ID_NAM_SIZ) { + pnt[cl++] = ch; + } + }; /* scopecomp */ + pnt[cl] = 0; + xc->hier.u.scope.component_length = cl; + 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); + if (!xc->str_scope_attr) { + xc->str_scope_attr = (char *)calloc(1, FST_ID_NAM_ATTR_SIZ + 1); + } + xc->hier.u.attr.name = pnt = xc->str_scope_attr; + cl = 0; + while ((ch = fgetc(xc->fh))) { + if (cl < FST_ID_NAM_ATTR_SIZ) { + pnt[cl++] = ch; + } + }; /* attrname */ + pnt[cl] = 0; + xc->hier.u.attr.name_length = cl; + + 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_attr, + &sidx_skiplen_dummy); + } + } + 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; + cl = 0; + while ((ch = fgetc(xc->fh))) { + if (cl < FST_ID_NAM_SIZ) { + pnt[cl++] = ch; + } + }; /* varname */ + pnt[cl] = 0; + xc->hier.u.var.name_length = cl; + 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); + + 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; + + default: + isfeof = 1; + break; + } + } + + return (!isfeof ? &xc->hier : NULL); } - -int fstReaderProcessHier(void *ctx, FILE *fv) +int fstReaderProcessHier(fstReaderContext *xc, FILE *fv) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -char *str; -char *pnt; -int ch, scopetype; -int vartype; -uint32_t len, alias; -/* uint32_t maxvalpos=0; */ -unsigned int num_signal_dyn = 65536; -int attrtype, subtype; -uint64_t attrarg; -fstHandle maxhandle_scanbuild; -int cl; + char *str; + char *pnt; + int ch, scopetype; + int vartype; + uint32_t len, alias; + /* uint32_t maxvalpos=0; */ + unsigned int num_signal_dyn = 65536; + int attrtype, subtype; + uint64_t attrarg; + fstHandle maxhandle_scanbuild; + int cl; + int unnamed_scope_idx = 0; -if(!xc) return(0); + if (!xc) + return (0); -xc->longest_signal_value_len = 32; /* arbitrarily set at 32...this is much longer than an expanded double */ + 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 (!xc->fh) { + if (!fstReaderRecreateHierFile(xc)) { + return (0); } + } -str = (char *)malloc(FST_ID_NAM_ATTR_SIZ+1); + str = (char *)malloc(FST_ID_NAM_ATTR_SIZ + 1); -if(fv) - { + if (fv) { 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); + if (xc->timezero) + fprintf(fv, "$timezero\n\t%" PRId64 "\n$end\n", xc->timezero); - switch(xc->timescale) - { - case 2: time_scale = 100; time_dimension[0] = 0; break; - case 1: time_scale = 10; /* fallthrough */ - case 0: time_dimension[0] = 0; break; + switch (xc->timescale) { + case 2: + time_scale = 100; + time_dimension[0] = 0; + break; + case 1: + time_scale = 10; /* fallthrough */ + case 0: + time_dimension[0] = 0; + break; - case -1: time_scale = 100; time_dimension[0] = 'm'; break; - case -2: time_scale = 10; /* fallthrough */ - case -3: time_dimension[0] = 'm'; break; + case -1: + time_scale = 100; + time_dimension[0] = 'm'; + break; + case -2: + time_scale = 10; /* fallthrough */ + case -3: + time_dimension[0] = 'm'; + break; - case -4: time_scale = 100; time_dimension[0] = 'u'; break; - case -5: time_scale = 10; /* fallthrough */ - case -6: time_dimension[0] = 'u'; break; + case -4: + time_scale = 100; + time_dimension[0] = 'u'; + break; + case -5: + time_scale = 10; /* fallthrough */ + case -6: + time_dimension[0] = 'u'; + break; - case -10: time_scale = 100; time_dimension[0] = 'p'; break; - case -11: time_scale = 10; /* fallthrough */ - case -12: time_dimension[0] = 'p'; break; + case -10: + time_scale = 100; + time_dimension[0] = 'p'; + break; + case -11: + time_scale = 10; /* fallthrough */ + case -12: + time_dimension[0] = 'p'; + break; - case -13: time_scale = 100; time_dimension[0] = 'f'; break; - case -14: time_scale = 10; /* fallthrough */ - case -15: time_dimension[0] = 'f'; break; + case -13: + time_scale = 100; + time_dimension[0] = 'f'; + break; + case -14: + time_scale = 10; /* fallthrough */ + case -15: + time_dimension[0] = 'f'; + break; - case -16: time_scale = 100; time_dimension[0] = 'a'; break; - case -17: time_scale = 10; /* fallthrough */ - case -18: time_dimension[0] = 'a'; break; + case -16: + time_scale = 100; + time_dimension[0] = 'a'; + break; + case -17: + time_scale = 10; /* fallthrough */ + case -18: + time_dimension[0] = 'a'; + break; - case -19: time_scale = 100; time_dimension[0] = 'z'; break; - case -20: time_scale = 10; /* fallthrough */ - case -21: time_dimension[0] = 'z'; break; + case -19: + time_scale = 100; + time_dimension[0] = 'z'; + break; + case -20: + time_scale = 10; /* fallthrough */ + case -21: + time_dimension[0] = 'z'; + break; - case -7: time_scale = 100; time_dimension[0] = 'n'; break; - case -8: time_scale = 10; /* fallthrough */ - case -9: - default: time_dimension[0] = 'n'; break; - } - - if(fv) fprintf(fv, "$timescale\n\t%d%ss\n$end\n", time_scale, time_dimension); + case -7: + time_scale = 100; + time_dimension[0] = 'n'; + break; + case -8: + time_scale = 10; /* fallthrough */ + case -9: + default: + time_dimension[0] = 'n'; + break; } -xc->maxhandle = 0; -xc->num_alias = 0; + if (fv) + fprintf(fv, "$timescale\n\t%d%ss\n$end\n", time_scale, time_dimension); + } -free(xc->signal_lens); -xc->signal_lens = (uint32_t *)malloc(num_signal_dyn*sizeof(uint32_t)); + xc->maxhandle = 0; + xc->num_alias = 0; -free(xc->signal_typs); -xc->signal_typs = (unsigned char *)malloc(num_signal_dyn*sizeof(unsigned char)); + free(xc->signal_lens); + xc->signal_lens = (uint32_t *)malloc(num_signal_dyn * sizeof(uint32_t)); -fstReaderFseeko(xc, xc->fh, 0, SEEK_SET); -while(!feof(xc->fh)) - { + free(xc->signal_typs); + xc->signal_typs = (unsigned char *)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; - cl = 0; - while((ch = fgetc(xc->fh))) - { - if(cl < FST_ID_NAM_ATTR_SIZ) - { - pnt[cl++] = ch; - } - }; /* scopename */ - pnt[cl] = 0; - while(fgetc(xc->fh)) { }; /* scopecomp */ - - 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_GEN_ATTRBEGIN: - attrtype = fgetc(xc->fh); - subtype = fgetc(xc->fh); - pnt = str; - cl = 0; - while((ch = fgetc(xc->fh))) - { - if(cl < FST_ID_NAM_ATTR_SIZ) - { - pnt[cl++] = ch; - } - }; /* attrname */ - pnt[cl] = 0; - - if(!str[0]) { strcpy(str, "\"\""); } - - 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); - - 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_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; - cl = 0; - while((ch = fgetc(xc->fh))) - { - if(cl < FST_ID_NAM_ATTR_SIZ) - { - pnt[cl++] = ch; - } - }; /* varname */ - pnt[cl] = 0; - len = fstReaderVarint32(xc->fh); - alias = fstReaderVarint32(xc->fh); - - if(!alias) - { - if(xc->maxhandle == num_signal_dyn) - { - num_signal_dyn *= 2; - xc->signal_lens = (uint32_t *)realloc(xc->signal_lens, num_signal_dyn*sizeof(uint32_t)); - xc->signal_typs = (unsigned char *)realloc(xc->signal_typs, num_signal_dyn*sizeof(unsigned char)); - } - xc->signal_lens[xc->maxhandle] = len; - xc->signal_typs[xc->maxhandle] = vartype; - - /* 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++; - } - - break; - - default: - break; + 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; + cl = 0; + while ((ch = fgetc(xc->fh))) { + if (cl < FST_ID_NAM_ATTR_SIZ) { + pnt[cl++] = ch; + } + }; /* scopename */ + if (!cl) { + cl = snprintf(pnt, FST_ID_NAM_SIZ, "$unnamed_scope_%d", unnamed_scope_idx++); } + pnt[cl] = 0; + while (fgetc(xc->fh)) { + }; /* scopecomp */ + + 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_GEN_ATTRBEGIN: + attrtype = fgetc(xc->fh); + subtype = fgetc(xc->fh); + pnt = str; + cl = 0; + while ((ch = fgetc(xc->fh))) { + if (cl < FST_ID_NAM_ATTR_SIZ) { + pnt[cl++] = ch; + } + }; /* attrname */ + pnt[cl] = 0; + + if (!str[0]) { + strcpy(str, "\"\""); + } + + 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); + + 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_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; + cl = 0; + while ((ch = fgetc(xc->fh))) { + if (cl < FST_ID_NAM_ATTR_SIZ) { + pnt[cl++] = ch; + } + }; /* varname */ + pnt[cl] = 0; + len = fstReaderVarint32(xc->fh); + alias = fstReaderVarint32(xc->fh); + + if (!alias) { + if (xc->maxhandle == num_signal_dyn) { + num_signal_dyn *= 2; + xc->signal_lens = + (uint32_t *)realloc(xc->signal_lens, num_signal_dyn * sizeof(uint32_t)); + xc->signal_typs = + (unsigned char *)realloc(xc->signal_typs, + num_signal_dyn * sizeof(unsigned char)); + } + xc->signal_lens[xc->maxhandle] = len; + xc->signal_typs[xc->maxhandle] = vartype; + + /* 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++; + } + + break; + + default: + break; } -if(fv) fprintf(fv, "$enddefinitions $end\n"); + } + 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 */ + maxhandle_scanbuild = + xc->maxhandle + ? xc->maxhandle + : 1; /*scan-build warning suppression, in reality we have at least one signal */ -xc->signal_lens = (uint32_t *)realloc(xc->signal_lens, maxhandle_scanbuild*sizeof(uint32_t)); -xc->signal_typs = (unsigned char *)realloc(xc->signal_typs, maxhandle_scanbuild*sizeof(unsigned char)); + xc->signal_lens = (uint32_t *)realloc(xc->signal_lens, maxhandle_scanbuild * sizeof(uint32_t)); + xc->signal_typs = + (unsigned char *)realloc(xc->signal_typs, maxhandle_scanbuild * sizeof(unsigned char)); -free(xc->process_mask); -xc->process_mask = (unsigned char *)calloc(1, (maxhandle_scanbuild+7)/8); + free(xc->process_mask); + xc->process_mask = (unsigned char *)calloc(1, (maxhandle_scanbuild + 7) / 8); -free(xc->temp_signal_value_buf); -xc->temp_signal_value_buf = (unsigned char *)malloc(xc->longest_signal_value_len + 1); + free(xc->temp_signal_value_buf); + xc->temp_signal_value_buf = (unsigned char *)malloc(xc->longest_signal_value_len + 1); -xc->var_count = xc->maxhandle + xc->num_alias; + xc->var_count = xc->maxhandle + xc->num_alias; -free(str); -return(1); + free(str); + return (1); } - /* * reader file open/close functions */ int fstReaderInit(struct fstReaderContext *xc) { -fst_off_t blkpos = 0; -fst_off_t endfile; -uint64_t seclen; -int sectype; -uint64_t vc_section_count_actual = 0; -int hdr_incomplete = 0; -int hdr_seen = 0; -int gzread_pass_status = 1; + fst_off_t blkpos = 0; + fst_off_t endfile; + uint64_t seclen; + int sectype; + uint64_t vc_section_count_actual = 0; + int hdr_incomplete = 0; + int hdr_seen = 0; + int gzread_pass_status = 1; -sectype = fgetc(xc->f); -if(sectype == FST_BL_ZWRAPPER) - { + sectype = fgetc(xc->f); + if (sectype == FST_BL_ZWRAPPER) { FILE *fcomp; fst_off_t offpnt, uclen; char gz_membuf[FST_GZIO_LEN]; @@ -4606,337 +4438,313 @@ if(sectype == FST_BL_ZWRAPPER) int zfd; int flen = strlen(xc->filename); char *hf; - int hf_len; + int hf_len; 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_len = flen + 16 + 32 + 1; + hf_len = flen + 16 + 32 + 1; hf = (char *)calloc(1, hf_len); snprintf(hf, hf_len, "%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 (!fcomp) { + fcomp = tmpfile_open(&xc->f_nam); + free(hf); + hf = NULL; + if (!fcomp) { + tmpfile_close(&fcomp, &xc->f_nam); + return (0); + } + } #if defined(FST_UNBUFFERED_IO) - 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__ xc->filename_unpacked = hf; #else - if(hf) - { - unlink(hf); - free(hf); - } + if (hf) { + unlink(hf); + free(hf); + } #endif fstReaderFseeko(xc, xc->f, FST_ZWRAPPER_HDR_SIZE, SEEK_SET); #if !defined(__MINGW32__) && !defined(_MSC_VER) fflush(xc->f); #else - /* Windows UCRT runtime library reads one byte ahead in the file - even with buffering disabled and does not synchronise the - file position after fseek. */ - _lseek(fileno(xc->f), FST_ZWRAPPER_HDR_SIZE, SEEK_SET); + /* Windows UCRT runtime library reads one byte ahead in the file + even with buffering disabled and does not synchronise the + file position after fseek. */ + _lseek(fileno(xc->f), FST_ZWRAPPER_HDR_SIZE, SEEK_SET); #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; + 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); + if (gzreadlen != this_len) { + gzread_pass_status = 0; + break; } - else - { - close(zfd); + 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) - { + if (gzread_pass_status) { 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) + if (sectype == EOF) { + break; + } + + if ((hdr_incomplete) && (!seclen)) { + break; + } + + if (!hdr_seen && (sectype != FST_BL_HDR)) { + break; + } + + 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); + + hdr_incomplete = (xc->start_time == 0) && (xc->end_time == 0); + + fstFread(&dcheck, 8, 1, xc->f); + /* + * Yosys patch: Fix double endian check for i386 targets built in modern gcc + */ + xc->double_endian_match = (dcheck == (double)FST_DOUBLE_ENDTEST); + if (!xc->double_endian_match) { + union { - break; + 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]; } - - if((hdr_incomplete) && (!seclen)) - { - break; + if (vu.d != FST_DOUBLE_ENDTEST) { + break; /* either corrupt file or wrong architecture (offset +33 also + functions as matchword) */ } + } - if(!hdr_seen && (sectype != FST_BL_HDR)) - { - break; - } + hdr_seen = 1; - blkpos++; - if(sectype == FST_BL_HDR) - { - if(!hdr_seen) - { - int ch; - double dcheck; + 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->start_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); - /* - * Yosys patch: Fix double endian check for i386 targets built in modern gcc - */ - xc->double_endian_match = (dcheck == (double)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; - - 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; - - 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; } - } - - 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 = (unsigned char *)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 */ - - free(xc->process_mask); - xc->process_mask = (unsigned char *)calloc(1, (xc->maxhandle+7)/8); - - if(clen != uclen) - { - unsigned char *cdata = (unsigned char *)malloc(clen); - unsigned long destlen = uclen; - unsigned long sourcelen = clen; - int rc; - - fstFread(cdata, clen, 1, xc->f); - rc = uncompress(ucdata, &destlen, cdata, sourcelen); - - if(rc != Z_OK) - { - fprintf(stderr, FST_APIMESS "fstReaderInit(), geom uncompress rc = %d, exiting.\n", rc); - exit(255); - } - - free(cdata); - } - else - { - fstFread(ucdata, uclen, 1, xc->f); - } - - free(xc->signal_lens); - xc->signal_lens = (uint32_t *)malloc(sizeof(uint32_t) * xc->maxhandle); - free(xc->signal_typs); - xc->signal_typs = (unsigned char *)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; - 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 = (unsigned char *)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; - - xc->num_blackouts = fstReaderVarint32(xc->f); - free(xc->blackout_times); - xc->blackout_times = (uint64_t *)calloc(xc->num_blackouts, sizeof(uint64_t)); - free(xc->blackout_activity); - xc->blackout_activity = (unsigned char *)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; - } - } - - blkpos += seclen; - if(!hdr_seen) break; + if (!vc_section_count_actual) { + xc->start_time = bt; + } } - if(hdr_seen) - { - if(xc->vc_section_count != vc_section_count_actual) - { - xc->vc_section_count = vc_section_count_actual; + 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 = (unsigned char *)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 */ + + free(xc->process_mask); + xc->process_mask = (unsigned char *)calloc(1, (xc->maxhandle + 7) / 8); + + if (clen != uclen) { + unsigned char *cdata = (unsigned char *)malloc(clen); + unsigned long destlen = uclen; + unsigned long sourcelen = clen; + int rc; + + fstFread(cdata, clen, 1, xc->f); + rc = uncompress(ucdata, &destlen, cdata, sourcelen); + + if (rc != Z_OK) { + fprintf(stderr, + FST_APIMESS + "fstReaderInit(), geom uncompress rc = %d, exiting.\n", + rc); + exit(255); } - if(!xc->contains_geom_section) - { - fstReaderProcessHier(xc, NULL); /* recreate signal_lens/signal_typs info */ + free(cdata); + } else { + fstFread(ucdata, uclen, 1, xc->f); + } + + free(xc->signal_lens); + xc->signal_lens = (uint32_t *)malloc(sizeof(uint32_t) * xc->maxhandle); + free(xc->signal_typs); + xc->signal_typs = + (unsigned char *)malloc(sizeof(unsigned char) * xc->maxhandle); + + for (i = 0; i < xc->maxhandle; i++) { + int skiplen; + uint64_t val = fstGetVarint32(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 + */ } + } + + free(xc->temp_signal_value_buf); + xc->temp_signal_value_buf = + (unsigned char *)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; + + xc->num_blackouts = fstReaderVarint32(xc->f); + free(xc->blackout_times); + xc->blackout_times = (uint64_t *)calloc(xc->num_blackouts, sizeof(uint64_t)); + free(xc->blackout_activity); + xc->blackout_activity = + (unsigned char *)calloc(xc->num_blackouts, sizeof(unsigned char)); + + for (i = 0; i < xc->num_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; } -return(hdr_seen); + 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 */ + } + } + } + + return (hdr_seen); } - -void *fstReaderOpenForUtilitiesOnly(void) +fstReaderContext *fstReaderOpenForUtilitiesOnly(void) { -struct fstReaderContext *xc = (struct fstReaderContext *)calloc(1, sizeof(struct fstReaderContext)); + fstReaderContext *xc = (fstReaderContext *)calloc(1, sizeof(fstReaderContext)); -return(xc); + return (xc); } - -void *fstReaderOpen(const char *nam) +fstReaderContext *fstReaderOpen(const char *nam) { -struct fstReaderContext *xc = (struct fstReaderContext *)calloc(1, sizeof(struct fstReaderContext)); + fstReaderContext *xc = (fstReaderContext *)calloc(1, sizeof(fstReaderContext)); -if((!nam)||(!(xc->f=fopen(nam, "rb")))) - { + if ((!nam) || (!(xc->f = fopen(nam, "rb")))) { free(xc); - xc=NULL; - } - else - { + xc = NULL; + } else { int flen = strlen(nam); char *hf = (char *)calloc(1, flen + 6); int rc; #if defined(FST_UNBUFFERED_IO) - 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); @@ -4947,147 +4755,159 @@ 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||(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 if (!rc) { + fstReaderClose(xc); + xc = NULL; } + } -return(xc); + return (xc); } - -static void fstReaderDeallocateRvatData(void *ctx) +static void fstReaderDeallocateRvatData(fstReaderContext *xc) { -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; + 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; xc->rvat_data_valid = 0; - } + } } - -void fstReaderClose(void *ctx) +void fstReaderClose(fstReaderContext *xc) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; - -if(xc) - { + if (xc) { fstReaderDeallocateScopeData(xc); fstReaderDeallocateRvatData(xc); - free(xc->rvat_sig_offs); xc->rvat_sig_offs = NULL; + 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->str_scope_attr); xc->str_scope_attr = 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->str_scope_attr); + xc->str_scope_attr = 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); - } + } } - /* * read processing */ /* normal read which re-interleaves the value change data */ -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 *fv) +int fstReaderIterBlocks(fstReaderContext *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 *fv) { -return(fstReaderIterBlocks2(ctx, value_change_callback, NULL, user_callback_data_pointer, fv)); + return (fstReaderIterBlocks2(ctx, value_change_callback, NULL, user_callback_data_pointer, fv)); } - -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 *fv) +int fstReaderIterBlocks2(fstReaderContext *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 *fv) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; + struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -uint64_t previous_time = UINT64_MAX; -uint64_t *time_table = NULL; -uint64_t tsec_nitems; -unsigned int secnum = 0; -int blocks_skipped = 0; -fst_off_t blkpos = 0; -uint64_t seclen, beg_tim; -uint64_t end_tim; -uint64_t frame_uclen, frame_clen, frame_maxhandle, vc_maxhandle; -fst_off_t vc_start; -fst_off_t indx_pntr, indx_pos; -fst_off_t *chain_table = NULL; -uint32_t *chain_table_lengths = NULL; -unsigned char *chain_cmem; -unsigned char *pnt; -long chain_clen; -fstHandle idx, pidx=0, i; -uint64_t pval; -uint64_t vc_maxhandle_largest = 0; -uint64_t tsec_uclen = 0, tsec_clen = 0; -int sectype; -uint64_t mem_required_for_traversal; -unsigned char *mem_for_traversal = NULL; -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] */ -int dumpvars_state = 0; + uint64_t previous_time = UINT64_MAX; + uint64_t *time_table = NULL; + uint64_t tsec_nitems; + unsigned int secnum = 0; + int blocks_skipped = 0; + fst_off_t blkpos = 0; + uint64_t seclen, beg_tim; + uint64_t end_tim; + uint64_t frame_uclen, frame_clen, frame_maxhandle, vc_maxhandle; + fst_off_t vc_start; + fst_off_t indx_pntr, indx_pos; + fst_off_t *chain_table = NULL; + uint32_t *chain_table_lengths = NULL; + unsigned char *chain_cmem; + unsigned char *pnt; + long chain_clen; + fstHandle idx, pidx = 0, i; + uint64_t pval; + uint64_t vc_maxhandle_largest = 0; + uint64_t tsec_uclen = 0, tsec_clen = 0; + int sectype; + uint64_t mem_required_for_traversal; + unsigned char *mem_for_traversal = NULL; + 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] */ + int dumpvars_state = 0; -if(!xc) return(0); + if (!xc) + return (0); -scatterptr = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t)); -headptr = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t)); -length_remaining = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t)); + scatterptr = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t)); + headptr = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t)); + length_remaining = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t)); -if(fv) - { + if (fv) { #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 */ + 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(;;) - { + for (;;) { uint32_t *tc_head = NULL; - uint32_t tc_head_items = 0; + uint32_t tc_head_items = 0; traversal_mem_offs = 0; fstReaderFseeko(xc, xc->f, blkpos, SEEK_SET); @@ -5095,372 +4915,364 @@ for(;;) 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, FST_APIMESS "<< EOF >>\n"); + fprintf(stderr, FST_APIMESS "<< 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; - } + 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); end_tim = fstReaderUint64(xc->f); - if(xc->limit_range_valid) - { - if(end_tim < xc->limit_range_start) - { - blocks_skipped++; - blkpos += seclen; - continue; - } + if (xc->limit_range_valid) { + if (end_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) + 66; /* add in potential fastlz overhead */ + mem_required_for_traversal = + fstReaderUint64(xc->f) + 66; /* add in potential fastlz overhead */ mem_for_traversal = (unsigned char *)malloc(mem_required_for_traversal); #ifdef FST_DEBUG - fprintf(stderr, FST_APIMESS "sec: %u seclen: %d begtim: %d endtim: %d\n", - secnum, (int)seclen, (int)beg_tim, (int)end_tim); - fprintf(stderr, FST_APIMESS "mem_required_for_traversal: %d\n", (int)mem_required_for_traversal-66); + fprintf(stderr, + FST_APIMESS "sec: %u seclen: %d begtim: %d endtim: %d\n", + secnum, + (int)seclen, + (int)beg_tim, + (int)end_tim); + fprintf(stderr, + FST_APIMESS "mem_required_for_traversal: %d\n", + (int)mem_required_for_traversal - 66); #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; - unsigned int ti; + 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, FST_APIMESS "time section unc: %d, com: %d (%d items)\n", - (int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems); + fprintf(stderr, + FST_APIMESS "time section unc: %d, com: %d (%d items)\n", + (int)tsec_uclen, + (int)tsec_clen, + (int)tsec_nitems); #endif - if(tsec_clen > seclen) break; /* corrupted tsec_clen: by definition it can't be larger than size of section */ - ucdata = (unsigned char *)malloc(tsec_uclen); - if(!ucdata) break; /* malloc fail as tsec_uclen out of range from corrupted file */ - destlen = tsec_uclen; - sourcelen = tsec_clen; + if (tsec_clen > seclen) + break; /* corrupted tsec_clen: by definition it can't be larger than size of section + */ + ucdata = (unsigned char *)malloc(tsec_uclen); + if (!ucdata) + break; /* malloc fail as tsec_uclen out of range from corrupted file */ + destlen = tsec_uclen; + sourcelen = tsec_clen; - fstReaderFseeko(xc, xc->f, -24 - ((fst_off_t)tsec_clen), SEEK_CUR); + fstReaderFseeko(xc, xc->f, -24 - ((fst_off_t)tsec_clen), SEEK_CUR); - if(tsec_uclen != tsec_clen) - { + if (tsec_uclen != tsec_clen) { cdata = (unsigned char *)malloc(tsec_clen); fstFread(cdata, tsec_clen, 1, xc->f); rc = uncompress(ucdata, &destlen, cdata, sourcelen); - if(rc != Z_OK) - { - fprintf(stderr, FST_APIMESS "fstReaderIterBlocks2(), tsec uncompress rc = %d, exiting.\n", rc); - exit(255); - } + if (rc != Z_OK) { + fprintf(stderr, + FST_APIMESS + "fstReaderIterBlocks2(), tsec uncompress rc = %d, exiting.\n", + rc); + exit(255); + } free(cdata); - } - else - { + } else { fstFread(ucdata, tsec_uclen, 1, xc->f); + } + + free(time_table); + + if (sizeof(size_t) < sizeof(uint64_t)) { + /* TALOS-2023-1792 for 32b overflow */ + uint64_t chk_64 = tsec_nitems * sizeof(uint64_t); + size_t chk_32 = ((size_t)tsec_nitems) * sizeof(uint64_t); + if (chk_64 != chk_32) + chk_report_abort("TALOS-2023-1792"); + } else { + uint64_t chk_64 = tsec_nitems * sizeof(uint64_t); + if ((chk_64 / sizeof(uint64_t)) != tsec_nitems) { + chk_report_abort("TALOS-2023-1792"); } - - free(time_table); - - if(sizeof(size_t) < sizeof(uint64_t)) - { - /* TALOS-2023-1792 for 32b overflow */ - uint64_t chk_64 = tsec_nitems * sizeof(uint64_t); - size_t chk_32 = ((size_t)tsec_nitems) * sizeof(uint64_t); - if(chk_64 != chk_32) chk_report_abort("TALOS-2023-1792"); - } - else - { - uint64_t chk_64 = tsec_nitems * sizeof(uint64_t); - if((chk_64/sizeof(uint64_t)) != tsec_nitems) - { - chk_report_abort("TALOS-2023-1792"); - } - } - time_table = (uint64_t *)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); - if(secnum == 0) - { - if((beg_tim != time_table[0]) || (blocks_skipped)) - { - unsigned char *mu = (unsigned char *)malloc(frame_uclen); - uint32_t sig_offs = 0; + if (secnum == 0) { + if ((beg_tim != time_table[0]) || (blocks_skipped)) { + unsigned char *mu = (unsigned char *)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) - { - if(dumpvars_state == 1) { wx_len = snprintf(wx_buf, 32, "$end\n"); fstWritex(xc, wx_buf, wx_len); dumpvars_state = 2; } - wx_len = snprintf(wx_buf, 32, "#%" PRIu64 "\n", beg_tim); - fstWritex(xc, wx_buf, wx_len); - if(!dumpvars_state) { wx_len = snprintf(wx_buf, 32, "$dumpvars\n"); fstWritex(xc, wx_buf, wx_len); dumpvars_state = 1; } - } - if((xc->num_blackouts)&&(cur_blackout != xc->num_blackouts)) - { - if(beg_tim == xc->blackout_times[cur_blackout]) - { - wx_len = snprintf(wx_buf, 32, "$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 = (unsigned char *)malloc(frame_clen); - int rc; - - 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) - { - fprintf(stderr, FST_APIMESS "fstReaderIterBlocks2(), frame uncompress rc: %d, exiting.\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]; - - 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) - { - if(xc->signal_lens[idx] > xc->longest_signal_value_len) - { - chk_report_abort("TALOS-2023-1797"); - } - 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); - if((sig_offs + xc->signal_lens[idx]) > frame_uclen) - { - chk_report_abort("TALOS-2023-1793"); - } - 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; - - 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; - - for(j=0;j<8;j++) - { - clone_d[j] = srcdata[7-j]; - } - } - snprintf((char *)xc->temp_signal_value_buf, xc->longest_signal_value_len + 1, "%.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; - - for(j=0;j<8;j++) - { - clone_d[j] = srcdata[7-j]; - } - } - - fstVcdID(vcdid_buf, idx+1); - wx_len = snprintf(wx_buf, 64, "r%.16g %s\n", d, vcdid_buf); - fstWritex(xc, wx_buf, wx_len); - } - } - } - } - } - - sig_offs += xc->signal_lens[idx]; - } - - free(mu); - fstReaderFseeko(xc, xc->f, -((fst_off_t)frame_clen), SEEK_CUR); + if (beg_tim) { + if (dumpvars_state == 1) { + wx_len = snprintf(wx_buf, 32, "$end\n"); + fstWritex(xc, wx_buf, wx_len); + dumpvars_state = 2; } + wx_len = snprintf(wx_buf, 32, "#%" PRIu64 "\n", beg_tim); + fstWritex(xc, wx_buf, wx_len); + if (!dumpvars_state) { + wx_len = snprintf(wx_buf, 32, "$dumpvars\n"); + fstWritex(xc, wx_buf, wx_len); + dumpvars_state = 1; + } + } + if ((xc->num_blackouts) && (cur_blackout != xc->num_blackouts)) { + if (beg_tim == xc->blackout_times[cur_blackout]) { + wx_len = + snprintf(wx_buf, + 32, + "$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 = (unsigned char *)malloc(frame_clen); + int rc; + + 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) { + fprintf(stderr, + FST_APIMESS + "fstReaderIterBlocks2(), frame uncompress rc: %d, exiting.\n", + rc); + exit(255); + } + free(mc); + } + + for (idx = 0; idx < frame_maxhandle; idx++) { + int process_idx = idx / 8; + int process_bit = idx & 7; + + if (xc->process_mask[process_idx] & (1 << process_bit)) { + if (xc->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) { + if (xc->signal_lens[idx] > xc->longest_signal_value_len) { + chk_report_abort("TALOS-2023-1797"); + } + 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); + if ((sig_offs + xc->signal_lens[idx]) > frame_uclen) { + chk_report_abort("TALOS-2023-1793"); + } + 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; + + 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; + + for (j = 0; j < 8; j++) { + clone_d[j] = srcdata[7 - j]; + } + } + snprintf((char *)xc->temp_signal_value_buf, + xc->longest_signal_value_len + 1, + "%.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; + + for (j = 0; j < 8; j++) { + clone_d[j] = srcdata[7 - j]; + } + } + + fstVcdID(vcdid_buf, idx + 1); + wx_len = snprintf(wx_buf, 64, "r%.16g %s\n", d, vcdid_buf); + fstWritex(xc, wx_buf, wx_len); + } + } + } + } + } + + sig_offs += xc->signal_lens[idx]; + } + + free(mu); + fstReaderFseeko(xc, xc->f, -((fst_off_t)frame_clen), SEEK_CUR); + } + } + fstReaderFseeko(xc, xc->f, (fst_off_t)frame_clen, SEEK_CUR); /* skip past compressed data */ vc_maxhandle = fstReaderVarint64(xc->f); - vc_start = ftello(xc->f); /* points to '!' character */ + vc_start = ftello(xc->f); /* points to '!' character */ packtype = fgetc(xc->f); #ifdef FST_DEBUG - fprintf(stderr, FST_APIMESS "frame_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", - (int)frame_uclen, (int)frame_clen, (int)frame_maxhandle); - fprintf(stderr, FST_APIMESS "vc_maxhandle: %d, packtype: %c\n", (int)vc_maxhandle, packtype); + fprintf(stderr, + FST_APIMESS "frame_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", + (int)frame_uclen, + (int)frame_clen, + (int)frame_maxhandle); + fprintf(stderr, + FST_APIMESS "vc_maxhandle: %d, packtype: %c\n", + (int)vc_maxhandle, + packtype); #endif - indx_pntr = blkpos + seclen - 24 -tsec_clen -8; + 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; @@ -5468,168 +5280,151 @@ for(;;) fprintf(stderr, FST_APIMESS "indx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen); #endif chain_cmem = (unsigned char *)malloc(chain_clen); - if(!chain_cmem) goto block_err; + 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; + vc_maxhandle_largest = vc_maxhandle; - if(!(vc_maxhandle+1)) - { - chk_report_abort("TALOS-2023-1798"); - } + if (!(vc_maxhandle + 1)) { + chk_report_abort("TALOS-2023-1798"); + } - if(sizeof(size_t) < sizeof(uint64_t)) - { - /* TALOS-2023-1798 for 32b overflow */ - uint64_t chk_64 = (vc_maxhandle+1) * sizeof(fst_off_t); - size_t chk_32 = ((size_t)(vc_maxhandle+1)) * sizeof(fst_off_t); - if(chk_64 != chk_32) chk_report_abort("TALOS-2023-1798"); - } - else - { - uint64_t chk_64 = (vc_maxhandle+1) * sizeof(fst_off_t); - if((chk_64/sizeof(fst_off_t)) != (vc_maxhandle+1)) - { - chk_report_abort("TALOS-2023-1798"); - } - } - chain_table = (fst_off_t *)calloc((vc_maxhandle+1), sizeof(fst_off_t)); - - if(sizeof(size_t) < sizeof(uint64_t)) - { - /* TALOS-2023-1798 for 32b overflow */ - uint64_t chk_64 = (vc_maxhandle+1) * sizeof(uint32_t); - size_t chk_32 = ((size_t)(vc_maxhandle+1)) * sizeof(uint32_t); - if(chk_64 != chk_32) chk_report_abort("TALOS-2023-1798"); - } - else - { - uint64_t chk_64 = (vc_maxhandle+1) * sizeof(uint32_t); - if((chk_64/sizeof(uint32_t)) != (vc_maxhandle+1)) - { - chk_report_abort("TALOS-2023-1798"); - } - } - chain_table_lengths = (uint32_t *)calloc((vc_maxhandle+1), sizeof(uint32_t)); + if (sizeof(size_t) < sizeof(uint64_t)) { + /* TALOS-2023-1798 for 32b overflow */ + uint64_t chk_64 = (vc_maxhandle + 1) * sizeof(fst_off_t); + size_t chk_32 = ((size_t)(vc_maxhandle + 1)) * sizeof(fst_off_t); + if (chk_64 != chk_32) + chk_report_abort("TALOS-2023-1798"); + } else { + uint64_t chk_64 = (vc_maxhandle + 1) * sizeof(fst_off_t); + if ((chk_64 / sizeof(fst_off_t)) != (vc_maxhandle + 1)) { + chk_report_abort("TALOS-2023-1798"); } + } + chain_table = (fst_off_t *)calloc((vc_maxhandle + 1), sizeof(fst_off_t)); - if(!chain_table || !chain_table_lengths) goto block_err; + if (sizeof(size_t) < sizeof(uint64_t)) { + /* TALOS-2023-1798 for 32b overflow */ + uint64_t chk_64 = (vc_maxhandle + 1) * sizeof(uint32_t); + size_t chk_32 = ((size_t)(vc_maxhandle + 1)) * sizeof(uint32_t); + if (chk_64 != chk_32) + chk_report_abort("TALOS-2023-1798"); + } else { + uint64_t chk_64 = (vc_maxhandle + 1) * sizeof(uint32_t); + if ((chk_64 / sizeof(uint32_t)) != (vc_maxhandle + 1)) { + chk_report_abort("TALOS-2023-1798"); + } + } + chain_table_lengths = (uint32_t *)calloc((vc_maxhandle + 1), sizeof(uint32_t)); + } + + if (!chain_table || !chain_table_lengths) + goto block_err; 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); - fstHandle loopcnt = val >> 1; - if((idx+loopcnt-1) > vc_maxhandle) /* TALOS-2023-1789 */ - { - chk_report_abort("TALOS-2023-1789"); - } + fstHandle loopcnt = val >> 1; + if ((idx + loopcnt - 1) > vc_maxhandle) /* TALOS-2023-1789 */ + { + chk_report_abort("TALOS-2023-1789"); + } - for(i=0;i> 1); - if(idx) { chain_table_lengths[pidx] = pval - chain_table[pidx]; } - pidx = idx++; - } - else - { - fstHandle loopcnt = val >> 1; + pnt += skiplen; + } while (pnt != (chain_cmem + chain_clen)); + } else { + do { + int skiplen; + uint64_t val = fstGetVarint32(pnt, &skiplen); - if((idx+loopcnt-1) > vc_maxhandle) /* TALOS-2023-1789 */ - { - chk_report_abort("TALOS-2023-1789"); - } + 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 { + fstHandle loopcnt = val >> 1; - for(i=0;i vc_maxhandle) /* TALOS-2023-1789 */ + { + chk_report_abort("TALOS-2023-1789"); + } - pnt += skiplen; - } while (pnt != (chain_cmem + chain_clen)); + for (i = 0; i < loopcnt; i++) { + chain_table[idx++] = 0; + } } + pnt += skiplen; + } while (pnt != (chain_cmem + chain_clen)); + } + chain_table[idx] = indx_pos - vc_start; chain_table_lengths[pidx] = chain_table[idx] - chain_table[pidx]; - for(i=0;i xc->maxhandle) idx = xc->maxhandle; - for(i=0;i xc->maxhandle) + idx = xc->maxhandle; + for (i = 0; i < idx; i++) { + if (chain_table[i]) { + int process_idx = i / 8; + int process_bit = i & 7; - if(xc->process_mask[process_idx]&(1<process_mask[process_idx] & (1 << process_bit)) { + int rc = Z_OK; + 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) - { - 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(traversal_mem_offs >= mem_required_for_traversal) - { - chk_report_abort("TALOS-2023-1785"); - } - - if(mc_mem_len < chain_table_lengths[i]) - { - free(mc_mem); - mc_mem = (unsigned char *)malloc(mc_mem_len = chain_table_lengths[i]); - } - mc = mc_mem; - - fstFread(mc, chain_table_lengths[i], 1, xc->f); - - 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;j= mem_required_for_traversal) - { - chk_report_abort("TALOS-2023-1785"); - } - - fstFread(mu, destlen, 1, xc->f); - /* 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(tdelta >= tc_head_items) - { - chk_report_abort("TALOS-2023-1791"); - } - - scatterptr[i] = tc_head[tdelta]; - tc_head[tdelta] = i+1; - } + if (traversal_mem_offs >= mem_required_for_traversal) { + chk_report_abort("TALOS-2023-1785"); } + + if (mc_mem_len < chain_table_lengths[i]) { + free(mc_mem); + mc_mem = (unsigned char *)malloc(mc_mem_len = chain_table_lengths[i]); + } + mc = mc_mem; + + fstFread(mc, chain_table_lengths[i], 1, xc->f); + + 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;j= mem_required_for_traversal) { + chk_report_abort("TALOS-2023-1785"); + } + + fstFread(mu, destlen, 1, xc->f); + /* 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 (tdelta >= tc_head_items) { + chk_report_abort("TALOS-2023-1791"); + } + + 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; + } + } - if(dumpvars_state == 1) { wx_len = snprintf(wx_buf, 32, "$end\n"); fstWritex(xc, wx_buf, wx_len); dumpvars_state = 2; } - wx_len = snprintf(wx_buf, 32, "#%" PRIu64 "\n", time_table[i]); - fstWritex(xc, wx_buf, wx_len); - if(!dumpvars_state) { wx_len = snprintf(wx_buf, 32, "$dumpvars\n"); fstWritex(xc, wx_buf, wx_len); dumpvars_state = 1; } + if (dumpvars_state == 1) { + wx_len = snprintf(wx_buf, 32, "$end\n"); + fstWritex(xc, wx_buf, wx_len); + dumpvars_state = 2; + } + wx_len = snprintf(wx_buf, 32, "#%" PRIu64 "\n", time_table[i]); + fstWritex(xc, wx_buf, wx_len); + if (!dumpvars_state) { + wx_len = snprintf(wx_buf, 32, "$dumpvars\n"); + fstWritex(xc, wx_buf, wx_len); + dumpvars_state = 1; + } - if((xc->num_blackouts)&&(cur_blackout != xc->num_blackouts)) - { - if(time_table[i] == xc->blackout_times[cur_blackout]) - { - wx_len = snprintf(wx_buf, 32, "$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 = + snprintf(wx_buf, + 32, + "$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); + + 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)]; } - while(tc_head[i]) - { - idx = tc_head[i] - 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; + + 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 ((tdelta + i) >= tc_head_items) { + chk_report_abort("TALOS-2023-1791"); + } + + 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; - 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 (!(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(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] = 's'; + fstWritex(xc, vcd_id, 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; - - 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((tdelta+i) >= tc_head_items) - { - chk_report_abort("TALOS-2023-1791"); - } - - scatterptr[idx] = tc_head[i+tdelta]; - tc_head[i+tdelta] = idx+1; - } + vcdid_len = fstVcdIDForFwrite(vcd_id + 1, idx + 1); + { + if (sizeof(size_t) < sizeof(uint64_t)) { + /* TALOS-2023-1790 for 32b overflow */ + uint64_t chk_64 = len * 4 + 1; + size_t chk_32 = len * 4 + 1; + if (chk_64 != chk_32) + chk_report_abort("TALOS-2023-1790"); } - 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; + unsigned char *vesc = (unsigned char *)malloc(len * 4 + 1); + int vlen = fstUtilityBinToEsc(vesc, vdata, len); + fstWritex(xc, vesc, vlen); + free(vesc); + } - 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); - - vcdid_len = fstVcdIDForFwrite(vcd_id+1, idx+1); - { - if(sizeof(size_t) < sizeof(uint64_t)) - { - /* TALOS-2023-1790 for 32b overflow */ - uint64_t chk_64 = len*4 + 1; - size_t chk_32 = len*4 + 1; - if(chk_64 != chk_32) chk_report_abort("TALOS-2023-1790"); - } - - unsigned char *vesc = (unsigned char *)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); - } - } - } - - skiplen += len; - headptr[idx] += skiplen; - length_remaining[idx] -= skiplen; - - tc_head[i] = scatterptr[idx]; - scatterptr[idx] = 0; - - if(length_remaining[idx]) - { - vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]); - tdelta = vli >> 1; - - if((tdelta+i) >= tc_head_items) - { - chk_report_abort("TALOS-2023-1791"); - } - - 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; - - if(xc->signal_typs[idx] != FST_VT_VCD_REAL) - { - if(len > xc->longest_signal_value_len) - { - chk_report_abort("TALOS-2023-1797"); - } - - 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; - - 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); - } - } - - 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'; - uint64_t mem_required_for_traversal_chk = vdata - mem_for_traversal + len; - - fstWritex(xc, &ch_bp, 1); - if(mem_required_for_traversal_chk > mem_required_for_traversal) - { - chk_report_abort("TALOS-2023-1793"); - } - 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; - - 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; - } - - 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; - - for(j=0;j<8;j++) - { - clone_d[j] = srcdata[7-j]; - } - } - snprintf((char *)xc->temp_signal_value_buf, xc->longest_signal_value_len + 1, "%.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; - - for(j=0;j<8;j++) - { - clone_d[j] = srcdata[7-j]; - } - } - - wx_len = snprintf(wx_buf, 32, "r%.16g", d); - if (wx_len > 32 || wx_len < 0) wx_len = 32; - 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); - } - - skiplen += len; - headptr[idx] += skiplen; - length_remaining[idx] -= skiplen; - - tc_head[i] = scatterptr[idx]; - scatterptr[idx] = 0; - - if(length_remaining[idx]) - { - vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]); - tdelta = vli >> 1; - - if((tdelta+i) >= tc_head_items) - { - chk_report_abort("TALOS-2023-1791"); - } - - scatterptr[idx] = tc_head[i+tdelta]; - tc_head[i+tdelta] = idx+1; - } + vcd_id[0] = ' '; + vcd_id[vcdid_len + 1] = '\n'; + fstWritex(xc, vcd_id, vcdid_len + 2); } + } } - } -block_err: + skiplen += len; + headptr[idx] += skiplen; + length_remaining[idx] -= skiplen; + + tc_head[i] = scatterptr[idx]; + scatterptr[idx] = 0; + + if (length_remaining[idx]) { + vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]); + tdelta = vli >> 1; + + if ((tdelta + i) >= tc_head_items) { + chk_report_abort("TALOS-2023-1791"); + } + + 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; + + if (xc->signal_typs[idx] != FST_VT_VCD_REAL) { + if (len > xc->longest_signal_value_len) { + chk_report_abort("TALOS-2023-1797"); + } + + if (!(vli & 1)) { + int byte = 0; + int bit; + unsigned int j; + + for (j = 0; j < len; j++) { + unsigned char ch; + byte = j / 8; + bit = 7 - (j & 7); + ch = ((vdata[byte] >> 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'; + + 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'; + uint64_t mem_required_for_traversal_chk = + vdata - mem_for_traversal + len; + + fstWritex(xc, &ch_bp, 1); + if (mem_required_for_traversal_chk > + mem_required_for_traversal) { + chk_report_abort("TALOS-2023-1793"); + } + 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; + + 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; + } + + 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; + + for (j = 0; j < 8; j++) { + clone_d[j] = srcdata[7 - j]; + } + } + snprintf((char *)xc->temp_signal_value_buf, + xc->longest_signal_value_len + 1, + "%.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; + + for (j = 0; j < 8; j++) { + clone_d[j] = srcdata[7 - j]; + } + } + + wx_len = snprintf(wx_buf, 32, "r%.16g", d); + if (wx_len > 32 || wx_len < 0) wx_len = 32; + 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); + } + + skiplen += len; + headptr[idx] += skiplen; + length_remaining[idx] -= skiplen; + + tc_head[i] = scatterptr[idx]; + scatterptr[idx] = 0; + + if (length_remaining[idx]) { + vli = fstGetVarint32NoSkip(mem_for_traversal + headptr[idx]); + tdelta = vli >> 1; + + if ((tdelta + i) >= tc_head_items) { + chk_report_abort("TALOS-2023-1791"); + } + + 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(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 */ + 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 (mem_for_traversal) + free(mem_for_traversal); /* scan-build */ + free(length_remaining); + free(headptr); + free(scatterptr); -if(chain_table) free(chain_table); -if(chain_table_lengths) free(chain_table_lengths); + if (chain_table) + free(chain_table); + if (chain_table_lengths) + free(chain_table_lengths); -free(time_table); + free(time_table); #ifndef FST_WRITEX_DISABLE -if(fv) - { + if (fv) { fstWritex(xc, NULL, 0); - } + } #endif -return(1); + return (1); } - /* rvat functions */ -static char *fstExtractRvatDataFromFrame(struct fstReaderContext *xc, fstHandle facidx, char *buf) +static char *fstExtractRvatDataFromFrame(fstReaderContext *xc, fstHandle facidx, char *buf) { -if(facidx >= xc->rvat_frame_maxhandle) - { - return(NULL); - } + if (facidx >= xc->rvat_frame_maxhandle) { + return (NULL); + } -if(xc->signal_lens[facidx] == 1) - { + 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 { + 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; + + for (j = 0; j < 8; j++) { + clone_d[j] = srcdata[7 - j]; } - 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; - - for(j=0;j<8;j++) - { - clone_d[j] = srcdata[7-j]; - } - } - - snprintf((char *)buf, 32, "%.16g", d); /* this will write 18 bytes */ - } + snprintf((char *)buf, 32, "%.16g", d); /* this will write 18 bytes */ } + } -return(buf); + return (buf); } - -char *fstReaderGetValueFromHandleAtTime(void *ctx, uint64_t tim, fstHandle facidx, char *buf) +char *fstReaderGetValueFromHandleAtTime(fstReaderContext *xc, + uint64_t tim, + fstHandle facidx, + char *buf) { -struct fstReaderContext *xc = (struct fstReaderContext *)ctx; -fst_off_t blkpos = 0, prev_blkpos; -uint64_t beg_tim, end_tim, beg_tim2, end_tim2; -int sectype; + fst_off_t blkpos = 0, prev_blkpos; + uint64_t beg_tim, end_tim, beg_tim2, end_tim2; + int sectype; #ifdef FST_DEBUG -unsigned int secnum = 0; + unsigned int secnum = 0; #endif -uint64_t seclen; -uint64_t tsec_uclen = 0, tsec_clen = 0; -uint64_t tsec_nitems; -uint64_t frame_uclen, frame_clen; + uint64_t seclen; + uint64_t tsec_uclen = 0, tsec_clen = 0; + uint64_t tsec_nitems; + uint64_t frame_uclen, frame_clen; #ifdef FST_DEBUG -uint64_t mem_required_for_traversal; + uint64_t mem_required_for_traversal; #endif -fst_off_t indx_pntr, indx_pos; -long chain_clen; -unsigned char *chain_cmem; -unsigned char *pnt; -fstHandle idx, pidx=0, i; -uint64_t pval; + fst_off_t indx_pntr, indx_pos; + long chain_clen; + unsigned char *chain_cmem; + unsigned char *pnt; + fstHandle idx, pidx = 0, i; + uint64_t pval; -if((!xc) || (!facidx) || (facidx > xc->maxhandle) || (!buf) || (!xc->signal_lens[facidx-1])) - { - return(NULL); - } + if ((!xc) || (!facidx) || (facidx > xc->maxhandle) || (!buf) || + (!xc->signal_lens[facidx - 1])) { + return (NULL); + } -if(!xc->rvat_sig_offs) - { + if (!xc->rvat_sig_offs) { uint32_t cur_offs = 0; xc->rvat_sig_offs = (uint32_t *)calloc(xc->maxhandle, sizeof(uint32_t)); - for(i=0;imaxhandle;i++) - { - xc->rvat_sig_offs[i] = cur_offs; - cur_offs += xc->signal_lens[i]; - } + for (i = 0; i < xc->maxhandle; 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_data_valid) { + if ((xc->rvat_beg_tim <= tim) && (tim <= xc->rvat_end_tim)) { + goto process_value; + } fstReaderDeallocateRvatData(xc); - } + } -xc->rvat_chain_pos_valid = 0; + xc->rvat_chain_pos_valid = 0; -for(;;) - { + for (;;) { fstReaderFseeko(xc, xc->f, (prev_blkpos = blkpos), SEEK_SET); 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; - } + 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); - if((beg_tim <= tim) && (tim <= end_tim)) - { - if((tim == end_tim) && (tim != xc->end_time)) - { - fst_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)) { + fst_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; #ifdef FST_DEBUG secnum++; #endif - } + } -xc->rvat_beg_tim = beg_tim; -xc->rvat_end_tim = end_tim; + 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); #ifdef FST_DEBUG -fprintf(stderr, FST_APIMESS "rvat sec: %u seclen: %d begtim: %d endtim: %d\n", - secnum, (int)seclen, (int)beg_tim, (int)end_tim); -fprintf(stderr, FST_APIMESS "mem_required_for_traversal: %d\n", (int)mem_required_for_traversal); + fprintf(stderr, + FST_APIMESS "rvat sec: %u seclen: %d begtim: %d endtim: %d\n", + secnum, + (int)seclen, + (int)beg_tim, + (int)end_tim); + fprintf(stderr, + FST_APIMESS "mem_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; -unsigned 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; -fstReaderFseeko(xc, xc->f, blkpos + seclen - 24, SEEK_SET); -tsec_uclen = fstReaderUint64(xc->f); -tsec_clen = fstReaderUint64(xc->f); -tsec_nitems = fstReaderUint64(xc->f); + fstReaderFseeko(xc, xc->f, blkpos + seclen - 24, SEEK_SET); + tsec_uclen = fstReaderUint64(xc->f); + tsec_clen = fstReaderUint64(xc->f); + tsec_nitems = fstReaderUint64(xc->f); #ifdef FST_DEBUG -fprintf(stderr, FST_APIMESS "time section unc: %d, com: %d (%d items)\n", - (int)tsec_uclen, (int)tsec_clen, (int)tsec_nitems); + fprintf(stderr, + FST_APIMESS "time section unc: %d, com: %d (%d items)\n", + (int)tsec_uclen, + (int)tsec_clen, + (int)tsec_nitems); #endif -ucdata = (unsigned char *)malloc(tsec_uclen); -destlen = tsec_uclen; -sourcelen = tsec_clen; + ucdata = (unsigned char *)malloc(tsec_uclen); + destlen = tsec_uclen; + sourcelen = tsec_clen; -fstReaderFseeko(xc, xc->f, -24 - ((fst_off_t)tsec_clen), SEEK_CUR); -if(tsec_uclen != tsec_clen) - { - cdata = (unsigned char *)malloc(tsec_clen); - fstFread(cdata, tsec_clen, 1, xc->f); + fstReaderFseeko(xc, xc->f, -24 - ((fst_off_t)tsec_clen), SEEK_CUR); + if (tsec_uclen != tsec_clen) { + cdata = (unsigned char *)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) - { - fprintf(stderr, FST_APIMESS "fstReaderGetValueFromHandleAtTime(), tsec uncompress rc = %d, exiting.\n", rc); + if (rc != Z_OK) { + fprintf(stderr, + FST_APIMESS + "fstReaderGetValueFromHandleAtTime(), tsec uncompress rc = %d, exiting.\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 = (uint64_t *)calloc(tsec_nitems, sizeof(uint64_t)); -tpnt = ucdata; -tpval = 0; -for(ti=0;tirvat_time_table[ti] = tpval + val; - tpnt += skiplen; + xc->rvat_time_table = (uint64_t *)calloc(tsec_nitems, sizeof(uint64_t)); + tpnt = ucdata; + tpval = 0; + for (ti = 0; ti < tsec_nitems; ti++) { + int skiplen; + uint64_t val = fstGetVarint64(tpnt, &skiplen); + tpval = xc->rvat_time_table[ti] = tpval + val; + tpnt += skiplen; } -free(ucdata); -} + free(ucdata); + } -fstReaderFseeko(xc, xc->f, blkpos+32, SEEK_SET); + fstReaderFseeko(xc, xc->f, blkpos + 32, SEEK_SET); -frame_uclen = fstReaderVarint64(xc->f); -frame_clen = fstReaderVarint64(xc->f); -xc->rvat_frame_maxhandle = fstReaderVarint64(xc->f); -xc->rvat_frame_data = (unsigned char *)malloc(frame_uclen); + frame_uclen = fstReaderVarint64(xc->f); + frame_clen = fstReaderVarint64(xc->f); + xc->rvat_frame_maxhandle = fstReaderVarint64(xc->f); + xc->rvat_frame_data = (unsigned char *)malloc(frame_uclen); -if(frame_uclen == frame_clen) - { + if (frame_uclen == frame_clen) { fstFread(xc->rvat_frame_data, frame_uclen, 1, xc->f); - } - else - { + } else { unsigned char *mc = (unsigned char *)malloc(frame_clen); int rc; @@ -6392,321 +6150,293 @@ if(frame_uclen == frame_clen) fstFread(mc, sourcelen, 1, xc->f); rc = uncompress(xc->rvat_frame_data, &destlen, mc, sourcelen); - if(rc != Z_OK) - { - fprintf(stderr, FST_APIMESS "fstReaderGetValueFromHandleAtTime(), frame decompress rc: %d, exiting.\n", rc); - exit(255); - } - free(mc); + if (rc != Z_OK) { + fprintf(stderr, + FST_APIMESS + "fstReaderGetValueFromHandleAtTime(), frame decompress rc: %d, exiting.\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_packtype = fgetc(xc->f); + xc->rvat_vc_maxhandle = fstReaderVarint64(xc->f); + xc->rvat_vc_start = ftello(xc->f); /* points to '!' character */ + xc->rvat_packtype = fgetc(xc->f); #ifdef FST_DEBUG -fprintf(stderr, FST_APIMESS "frame_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", - (int)frame_uclen, (int)frame_clen, (int)xc->rvat_frame_maxhandle); -fprintf(stderr, FST_APIMESS "vc_maxhandle: %d\n", (int)xc->rvat_vc_maxhandle); + fprintf(stderr, + FST_APIMESS "frame_uclen: %d, frame_clen: %d, frame_maxhandle: %d\n", + (int)frame_uclen, + (int)frame_clen, + (int)xc->rvat_frame_maxhandle); + fprintf(stderr, FST_APIMESS "vc_maxhandle: %d\n", (int)xc->rvat_vc_maxhandle); #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, FST_APIMESS "indx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen); + fprintf(stderr, FST_APIMESS "indx_pos: %d (%d bytes)\n", (int)indx_pos, (int)chain_clen); #endif -chain_cmem = (unsigned char *)malloc(chain_clen); -fstReaderFseeko(xc, xc->f, indx_pos, SEEK_SET); -fstFread(chain_cmem, chain_clen, 1, xc->f); + chain_cmem = (unsigned char *)malloc(chain_clen); + fstReaderFseeko(xc, xc->f, indx_pos, SEEK_SET); + fstFread(chain_cmem, chain_clen, 1, xc->f); -xc->rvat_chain_table = (fst_off_t *)calloc((xc->rvat_vc_maxhandle+1), sizeof(fst_off_t)); -xc->rvat_chain_table_lengths = (uint32_t *)calloc((xc->rvat_vc_maxhandle+1), sizeof(uint32_t)); + xc->rvat_chain_table = (fst_off_t *)calloc((xc->rvat_vc_maxhandle + 1), sizeof(fst_off_t)); + xc->rvat_chain_table_lengths = + (uint32_t *)calloc((xc->rvat_vc_maxhandle + 1), sizeof(uint32_t)); -pnt = chain_cmem; -idx = 0; -pval = 0; + pnt = chain_cmem; + idx = 0; + pval = 0; -if(sectype == FST_BL_VCDATA_DYN_ALIAS2) - { + 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 = xc->rvat_chain_table[idx] = pval + shval; - if(idx) { xc->rvat_chain_table_lengths[pidx] = pval - xc->rvat_chain_table[pidx]; } - pidx = idx++; - } - else if(shval < 0) - { - xc->rvat_chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */ - xc->rvat_chain_table_lengths[idx] = prev_alias = shval; /* because during this loop iter would give stale data! */ - idx++; - } - else - { - xc->rvat_chain_table[idx] = 0; /* need to explicitly zero as calloc above might not run */ - xc->rvat_chain_table_lengths[idx] = prev_alias; /* because during this loop iter would give stale data! */ - idx++; - } - } - else - { - uint64_t val = fstGetVarint32(pnt, &skiplen); - - fstHandle loopcnt = val >> 1; - for(i=0;irvat_chain_table[idx++] = 0; - } - } - - pnt += skiplen; - } while (pnt != (chain_cmem + chain_clen)); - } - else - { - do - { - int skiplen; - uint64_t val = fstGetVarint32(pnt, &skiplen); - - if(!val) - { - 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 - { - fstHandle loopcnt = val >> 1; - for(i=0;irvat_chain_table[idx++] = 0; - } - } - - 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])) - { - 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]; - } + if (*pnt & 0x01) { + int64_t shval = fstGetSVarint64(pnt, &skiplen) >> 1; + if (shval > 0) { + pval = xc->rvat_chain_table[idx] = pval + shval; + if (idx) { + xc->rvat_chain_table_lengths[pidx] = pval - xc->rvat_chain_table[pidx]; + } + pidx = idx++; + } else if (shval < 0) { + xc->rvat_chain_table[idx] = + 0; /* need to explicitly zero as calloc above might not run */ + xc->rvat_chain_table_lengths[idx] = prev_alias = + shval; /* because during this loop iter would give stale data! */ + idx++; + } else { + xc->rvat_chain_table[idx] = + 0; /* need to explicitly zero as calloc above might not run */ + xc->rvat_chain_table_lengths[idx] = + prev_alias; /* because during this loop iter would give stale data! */ + idx++; } + } else { + uint64_t val = fstGetVarint32(pnt, &skiplen); + + fstHandle loopcnt = val >> 1; + for (i = 0; i < loopcnt; i++) { + xc->rvat_chain_table[idx++] = 0; + } + } + + pnt += skiplen; + } while (pnt != (chain_cmem + chain_clen)); + } else { + do { + int skiplen; + uint64_t val = fstGetVarint32(pnt, &skiplen); + + if (!val) { + 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 { + fstHandle loopcnt = val >> 1; + for (i = 0; i < loopcnt; i++) { + xc->rvat_chain_table[idx++] = 0; + } + } + + 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; i < idx; i++) { + int32_t v32 = xc->rvat_chain_table_lengths[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]; + } } + } #ifdef FST_DEBUG -fprintf(stderr, FST_APIMESS "decompressed chain idx len: %" PRIu32 "\n", idx); + fprintf(stderr, FST_APIMESS "decompressed chain idx len: %" PRIu32 "\n", idx); #endif -xc->rvat_data_valid = 1; + 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) - { - return(NULL); + if (facidx > xc->rvat_vc_maxhandle) { + 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)); + } + + if (facidx != xc->rvat_chain_facidx) { + if (xc->rvat_chain_mem) { + free(xc->rvat_chain_mem); + xc->rvat_chain_mem = NULL; + + xc->rvat_chain_pos_valid = 0; } + } -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)); - } - -if(facidx != xc->rvat_chain_facidx) - { - if(xc->rvat_chain_mem) - { - free(xc->rvat_chain_mem); - xc->rvat_chain_mem = NULL; - - xc->rvat_chain_pos_valid = 0; - } - } - -if(!xc->rvat_chain_mem) - { + 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 = (unsigned char *)malloc(xc->rvat_chain_len); - unsigned char *mc = (unsigned char *)malloc(xc->rvat_chain_table_lengths[facidx]); - unsigned long destlen = xc->rvat_chain_len; - unsigned long sourcelen = xc->rvat_chain_table_lengths[facidx]; - int rc = Z_OK; + if (xc->rvat_chain_len) { + unsigned char *mu = (unsigned char *)malloc(xc->rvat_chain_len); + unsigned char *mc = (unsigned char *)malloc(xc->rvat_chain_table_lengths[facidx]); + unsigned long destlen = xc->rvat_chain_len; + unsigned long sourcelen = xc->rvat_chain_table_lengths[facidx]; + int rc = Z_OK; - fstFread(mc, xc->rvat_chain_table_lengths[facidx], 1, xc->f); + fstFread(mc, xc->rvat_chain_table_lengths[facidx], 1, xc->f); - switch(xc->rvat_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; - } + switch (xc->rvat_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; + } - free(mc); + free(mc); - if(rc != Z_OK) - { - fprintf(stderr, FST_APIMESS "fstReaderGetValueFromHandleAtTime(), rvat decompress clen: %d (rc=%d), exiting.\n", (int)xc->rvat_chain_len, rc); - exit(255); - } + if (rc != Z_OK) { + fprintf(stderr, + FST_APIMESS "fstReaderGetValueFromHandleAtTime(), rvat decompress clen: %d " + "(rc=%d), exiting.\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 = (unsigned char *)malloc(xc->rvat_chain_len = destlen); - fstFread(mu, destlen, 1, xc->f); - /* data to process is for(j=0;jrvat_chain_mem = mu; - } + /* data to process is for(j=0;jrvat_chain_mem = mu; + } else { + int destlen = xc->rvat_chain_table_lengths[facidx] - skiplen; + unsigned char *mu = (unsigned char *)malloc(xc->rvat_chain_len = destlen); + fstFread(mu, destlen, 1, xc->f); + /* data to process is for(j=0;jrvat_chain_mem = mu; + } xc->rvat_chain_facidx = facidx; + } + + /* process value chain here */ + + { + uint32_t tidx = 0, ptidx = 0; + uint32_t tdelta; + int skiplen; + 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; } -/* process value chain here */ - -{ -uint32_t tidx = 0, ptidx = 0; -uint32_t tdelta; -int skiplen; -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) - { + if (xc->signal_lens[facidx] == 1) { + while (i < xc->rvat_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 */ + if (xc->rvat_time_table[tidx + tdelta] <= tim) { + iprev = i; + pvli = vli; + ptidx = tidx; + /* pskip = skiplen; */ /* scan-build */ - tidx += tdelta; - i+=skiplen; - } - else - { - break; - } + tidx += tdelta; + i += skiplen; + } else { + break; } - if(iprev != xc->rvat_chain_len) - { + } + 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)]; - } + 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) - { + return (buf); + } else { + return (fstExtractRvatDataFromFrame(xc, facidx, buf)); + } + } else { + while (i < xc->rvat_chain_len) { uint32_t vli = fstGetVarint32(xc->rvat_chain_mem + i, &skiplen); tdelta = vli >> 1; - if(xc->rvat_time_table[tidx + tdelta] <= tim) - { - iprev = i; - pvli = vli; - ptidx = tidx; - pskip = skiplen; + if (xc->rvat_time_table[tidx + tdelta] <= tim) { + iprev = i; + pvli = vli; + ptidx = tidx; + pskip = skiplen; - tidx += tdelta; - i+=skiplen; + tidx += tdelta; + i += skiplen; - if(!(pvli & 1)) - { - i+=((xc->signal_lens[facidx]+7)/8); - } - else - { - i+=xc->signal_lens[facidx]; - } - } - else - { - break; - } + if (!(pvli & 1)) { + i += ((xc->signal_lens[facidx] + 7) / 8); + } else { + i += xc->signal_lens[facidx]; + } + } else { + break; } + } - if(iprev != xc->rvat_chain_len) - { + if (iprev != xc->rvat_chain_len) { unsigned char *vdata = xc->rvat_chain_mem + iprev + pskip; xc->rvat_chain_pos_tidx = ptidx; @@ -6714,93 +6444,72 @@ if(xc->signal_lens[facidx] == 1) xc->rvat_chain_pos_time = tim; xc->rvat_chain_pos_valid = 1; - if(xc->signal_typs[facidx] != FST_VT_VCD_REAL) - { - if(!(pvli & 1)) - { - int byte = 0; - int bit; - unsigned int j; + if (xc->signal_typs[facidx] != FST_VT_VCD_REAL) { + if (!(pvli & 1)) { + int byte = 0; + int bit; + unsigned int j; - 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; - - return(buf); - } - else - { - memcpy(buf, vdata, xc->signal_lens[facidx]); - buf[xc->signal_lens[facidx]] = 0; - return(buf); - } + for (j = 0; j < xc->signal_lens[facidx]; j++) { + unsigned char ch; + byte = j / 8; + bit = 7 - (j & 7); + ch = ((vdata[byte] >> bit) & 1) | '0'; + buf[j] = ch; } - else - { - double d; - unsigned char *clone_d = (unsigned char *)&d; - unsigned char bufd[8]; - unsigned char *srcdata; + buf[j] = 0; - if(!(pvli & 1)) /* very rare case, but possible */ - { - int bit; - 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++) - { - unsigned char ch; - bit = 7 - (j & 7); - ch = ((vdata[0] >> bit) & 1) | '0'; - bufd[j] = ch; - } + if (!(pvli & 1)) /* very rare case, but possible */ + { + int bit; + int j; - 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]; - } - } - - snprintf(buf, 32, "r%.16g", d); /* this will write 19 bytes */ - return(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]; + } + } + + snprintf(buf, 32, "r%.16g", d); /* this will write 19 bytes */ + return (buf); } - else - { - return(fstExtractRvatDataFromFrame(xc, facidx, buf)); - } + } else { + return (fstExtractRvatDataFromFrame(xc, facidx, buf)); + } } + } + + /* return(NULL); */ } -/* return(NULL); */ -} - - - -/**********************************************************************/ -#ifndef _WAVE_HAVE_JUDY - /***********************/ /*** ***/ /*** jenkins hash ***/ @@ -6833,18 +6542,36 @@ mix() was built out of 36 single-cycle latency instructions in a to choose from. I only looked at a billion or so. -------------------------------------------------------------------- */ -#define mix(a,b,c) \ -{ \ - a -= b; a -= c; a ^= (c>>13); \ - b -= c; b -= a; b ^= (a<<8); \ - c -= a; c -= b; c ^= (b>>13); \ - a -= b; a -= c; a ^= (c>>12); \ - b -= c; b -= a; b ^= (a<<16); \ - c -= a; c -= b; c ^= (b>>5); \ - a -= b; a -= c; a ^= (c>>3); \ - b -= c; b -= a; b ^= (a<<10); \ - c -= a; c -= b; c ^= (b>>15); \ -} +#define mix(a, b, c) \ + { \ + a -= b; \ + a -= c; \ + a ^= (c >> 13); \ + b -= c; \ + b -= a; \ + b ^= (a << 8); \ + c -= a; \ + c -= b; \ + c ^= (b >> 13); \ + a -= b; \ + a -= c; \ + a ^= (c >> 12); \ + b -= c; \ + b -= a; \ + b ^= (a << 16); \ + c -= a; \ + c -= b; \ + c ^= (b >> 5); \ + a -= b; \ + a -= c; \ + a ^= (c >> 3); \ + b -= c; \ + b -= a; \ + b ^= (a << 10); \ + c -= a; \ + c -= b; \ + c ^= (b >> 15); \ + } /* -------------------------------------------------------------------- @@ -6876,44 +6603,55 @@ acceptable. Do NOT use for cryptographic purposes. static uint32_t j_hash(const uint8_t *k, uint32_t length, uint32_t initval) { - uint32_t a,b,c,len; + uint32_t a, b, c, len; - /* Set up the internal state */ - len = length; - a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */ - c = initval; /* the previous hash value */ + /* Set up the internal state */ + len = length; + a = b = 0x9e3779b9; /* the golden ratio; an arbitrary value */ + c = initval; /* the previous hash value */ - /*---------------------------------------- handle most of the key */ - while (len >= 12) - { - a += (k[0] +((uint32_t)k[1]<<8) +((uint32_t)k[2]<<16) +((uint32_t)k[3]<<24)); - b += (k[4] +((uint32_t)k[5]<<8) +((uint32_t)k[6]<<16) +((uint32_t)k[7]<<24)); - c += (k[8] +((uint32_t)k[9]<<8) +((uint32_t)k[10]<<16)+((uint32_t)k[11]<<24)); - mix(a,b,c); - k += 12; len -= 12; - } + /*---------------------------------------- handle most of the key */ + while (len >= 12) { + a += (k[0] + ((uint32_t)k[1] << 8) + ((uint32_t)k[2] << 16) + ((uint32_t)k[3] << 24)); + b += (k[4] + ((uint32_t)k[5] << 8) + ((uint32_t)k[6] << 16) + ((uint32_t)k[7] << 24)); + c += (k[8] + ((uint32_t)k[9] << 8) + ((uint32_t)k[10] << 16) + ((uint32_t)k[11] << 24)); + mix(a, b, c); + k += 12; + len -= 12; + } - /*------------------------------------- handle the last 11 bytes */ - c += length; - switch(len) /* all the case statements fall through */ - { - case 11: c+=((uint32_t)k[10]<<24); /* fallthrough */ - case 10: c+=((uint32_t)k[9]<<16); /* fallthrough */ - case 9 : c+=((uint32_t)k[8]<<8); /* fallthrough */ - /* the first byte of c is reserved for the length */ - case 8 : b+=((uint32_t)k[7]<<24); /* fallthrough */ - case 7 : b+=((uint32_t)k[6]<<16); /* fallthrough */ - case 6 : b+=((uint32_t)k[5]<<8); /* fallthrough */ - case 5 : b+=k[4]; /* fallthrough */ - case 4 : a+=((uint32_t)k[3]<<24); /* fallthrough */ - case 3 : a+=((uint32_t)k[2]<<16); /* fallthrough */ - case 2 : a+=((uint32_t)k[1]<<8); /* fallthrough */ - case 1 : a+=k[0]; - /* case 0: nothing left to add */ - } - mix(a,b,c); - /*-------------------------------------------- report the result */ - return(c); + /*------------------------------------- handle the last 11 bytes */ + c += length; + switch (len) /* all the case statements fall through */ + { + case 11: + c += ((uint32_t)k[10] << 24); /* fallthrough */ + case 10: + c += ((uint32_t)k[9] << 16); /* fallthrough */ + case 9: + c += ((uint32_t)k[8] << 8); /* fallthrough */ + /* the first byte of c is reserved for the length */ + case 8: + b += ((uint32_t)k[7] << 24); /* fallthrough */ + case 7: + b += ((uint32_t)k[6] << 16); /* fallthrough */ + case 6: + b += ((uint32_t)k[5] << 8); /* fallthrough */ + case 5: + b += k[4]; /* fallthrough */ + case 4: + a += ((uint32_t)k[3] << 24); /* fallthrough */ + case 3: + a += ((uint32_t)k[2] << 16); /* fallthrough */ + case 2: + a += ((uint32_t)k[1] << 8); /* fallthrough */ + case 1: + a += k[0]; + /* case 0: nothing left to add */ + } + mix(a, b, c); + /*-------------------------------------------- report the result */ + return (c); } /********************************************************************/ @@ -6926,83 +6664,74 @@ static uint32_t j_hash(const uint8_t *k, uint32_t length, uint32_t initval) struct collchain_t { -struct collchain_t *next; -void *payload; -uint32_t fullhash, length; -unsigned char mem[1]; + struct collchain_t *next; + void *payload; + uint32_t fullhash, length; + unsigned char mem[1]; }; - void **JenkinsIns(void *base_i, const unsigned char *mem, uint32_t length, uint32_t hashmask) { -struct collchain_t ***base = (struct collchain_t ***)base_i; -uint32_t hf, h; -struct collchain_t **ar; -struct collchain_t *chain, *pchain; + struct collchain_t ***base = (struct collchain_t ***)base_i; + uint32_t hf, h; + struct collchain_t **ar; + struct collchain_t *chain, *pchain; -if(!*base) - { + if (!*base) { *base = (struct collchain_t **)calloc(1, (hashmask + 1) * sizeof(void *)); - } -ar = *base; + } + 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)); - } + 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)); + } pchain = chain; chain = chain->next; - } + } -chain = (struct collchain_t *)calloc(1, sizeof(struct collchain_t) + length - 1); -memcpy(chain->mem, mem, length); -chain->fullhash = hf; -chain->length = length; -chain->next = ar[h]; -ar[h] = chain; -return(&(chain->payload)); + chain = (struct collchain_t *)calloc(1, sizeof(struct collchain_t) + length - 1); + memcpy(chain->mem, mem, length); + chain->fullhash = hf; + chain->length = length; + chain->next = ar[h]; + ar[h] = chain; + return (&(chain->payload)); } - void JenkinsFree(void *base_i, uint32_t hashmask) { -struct collchain_t ***base = (struct collchain_t ***)base_i; -uint32_t h; -struct collchain_t **ar; -struct collchain_t *chain, *chain_next; + struct collchain_t ***base = (struct collchain_t ***)base_i; + uint32_t h; + struct collchain_t **ar; + struct collchain_t *chain, *chain_next; -if(base && *base) - { + 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; - } - } + for (h = 0; h <= hashmask; h++) { + chain = ar[h]; + while (chain) { + chain_next = chain->next; + free(chain); + chain = chain_next; + } + } free(*base); *base = NULL; - } + } } -#endif - /**********************************************************************/ /************************/ @@ -7013,212 +6742,266 @@ if(base && *base) int fstUtilityBinToEscConvertedLen(const unsigned char *s, int len) { -const unsigned char *src = s; -int dlen = 0; -int i; + const unsigned char *src = s; + int dlen = 0; + int i; -for(i=0;i ' ') && (src[i] <= '~')) /* no white spaces in output */ { - case '\a': /* fallthrough */ - case '\b': /* fallthrough */ - case '\f': /* fallthrough */ - case '\n': /* fallthrough */ - case '\r': /* fallthrough */ - case '\t': /* fallthrough */ - case '\v': /* fallthrough */ - case '\'': /* fallthrough */ - case '\"': /* fallthrough */ - case '\\': /* fallthrough */ - case '\?': dlen += 2; break; - default: if((src[i] > ' ') && (src[i] <= '~')) /* no white spaces in output */ - { - dlen++; - } - else - { - dlen += 4; - } - break; + dlen++; + } else { + dlen += 4; } + break; } + } -return(dlen); + return (dlen); } - int fstUtilityBinToEsc(unsigned char *d, const unsigned char *s, int len) { -const unsigned char *src = s; -unsigned char *dst = d; -unsigned char val; -int i; + const unsigned char *src = s; + unsigned char *dst = d; + unsigned char val; + int i; -for(i=0;i ' ') && (src[i] <= '~')) /* no white spaces in output */ { - 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; + *(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); + return (dst - d); } - /* * this overwrites the original string if the destination pointer is NULL */ int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len) { -unsigned char *src = s; -unsigned char *dst = (!d) ? s : (s = d); -unsigned char val[3]; -int i; + unsigned char *src = s; + unsigned char *dst = (!d) ? s : (s = d); + 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); + return (dst - s); } - struct fstETab *fstUtilityExtractEnumTableFromString(const char *s) { -struct fstETab *et = NULL; -int num_spaces = 0; -int i; -int newlen; + struct fstETab *et = NULL; + int num_spaces = 0; + int i; + int newlen; -if(s) - { - const char *csp = strchr(s, ' '); - int cnt = atoi(csp+1); + if (s) { + const char *csp = strchr(s, ' '); + int cnt = atoi(csp + 1); - for(;;) - { - csp = strchr(csp+1, ' '); - if(csp) { num_spaces++; } else { break; } - } + for (;;) { + csp = strchr(csp + 1, ' '); + if (csp) { + num_spaces++; + } else { + break; + } + } - if(num_spaces == (2*cnt)) - { - char *sp, *sp2; + if (num_spaces == (2 * cnt)) { + char *sp, *sp2; - et = (struct fstETab*)calloc(1, sizeof(struct fstETab)); - et->elem_count = cnt; - et->name = strdup(s); - et->literal_arr = (char**)calloc(cnt, sizeof(char *)); - et->val_arr = (char**)calloc(cnt, sizeof(char *)); + et = (struct fstETab *)calloc(1, sizeof(struct fstETab)); + et->elem_count = cnt; + et->name = strdup(s); + et->literal_arr = (char **)calloc(cnt, sizeof(char *)); + et->val_arr = (char **)calloc(cnt, sizeof(char *)); - sp = strchr(et->name, ' '); - *sp = 0; + sp = strchr(et->name, ' '); + *sp = 0; - sp = strchr(sp+1, ' '); + sp = strchr(sp + 1, ' '); - for(i=0;iliteral_arr[i] = sp+1; - sp = sp2; + for (i = 0; i < cnt; i++) { + sp2 = strchr(sp + 1, ' '); + *(char *)sp2 = 0; + et->literal_arr[i] = sp + 1; + sp = sp2; - newlen = fstUtilityEscToBin(NULL, (unsigned char*)et->literal_arr[i], strlen(et->literal_arr[i])); - et->literal_arr[i][newlen] = 0; - } + newlen = fstUtilityEscToBin(NULL, + (unsigned char *)et->literal_arr[i], + strlen(et->literal_arr[i])); + et->literal_arr[i][newlen] = 0; + } - for(i=0;ival_arr[i] = sp+1; - sp = sp2; + for (i = 0; i < cnt; i++) { + sp2 = strchr(sp + 1, ' '); + if (sp2) { + *sp2 = 0; + } + et->val_arr[i] = sp + 1; + sp = sp2; - newlen = fstUtilityEscToBin(NULL, (unsigned char*)et->val_arr[i], strlen(et->val_arr[i])); - et->val_arr[i][newlen] = 0; - } - } - } + newlen = fstUtilityEscToBin(NULL, + (unsigned char *)et->val_arr[i], + strlen(et->val_arr[i])); + et->val_arr[i][newlen] = 0; + } + } + } -return(et); + return (et); } - void fstUtilityFreeEnumTable(struct fstETab *etab) { -if(etab) - { - free(etab->literal_arr); - free(etab->val_arr); - free(etab->name); - free(etab); - } + if (etab) { + free(etab->literal_arr); + free(etab->val_arr); + free(etab->name); + free(etab); + } } diff --git a/libs/fst/fstapi.h b/libs/fst/fstapi.h index ba58c2017..cace48951 100644 --- a/libs/fst/fstapi.h +++ b/libs/fst/fstapi.h @@ -26,7 +26,8 @@ #define FST_API_H #ifdef __cplusplus -extern "C" { +extern "C" +{ #endif #include @@ -35,430 +36,510 @@ extern "C" { #include #include #if defined(_MSC_VER) - #include "libs/zlib/zlib.h" - #include "fst_win_unistd.h" +#include "libs/zlib/zlib.h" +#include "fst_win_unistd.h" #else - #include - #include +#include +#include #endif #include -#define FST_RDLOAD "FSTLOAD | " - typedef uint32_t fstHandle; typedef uint32_t fstEnumHandle; -enum fstWriterPackType { - FST_WR_PT_ZLIB = 0, - FST_WR_PT_FASTLZ = 1, - FST_WR_PT_LZ4 = 2 +enum fstWriterPackType +{ + FST_WR_PT_ZLIB = 0, + FST_WR_PT_FASTLZ = 1, + FST_WR_PT_LZ4 = 2 }; -enum fstFileType { - FST_FT_MIN = 0, +enum fstFileType +{ + FST_FT_MIN = 0, - FST_FT_VERILOG = 0, - FST_FT_VHDL = 1, - FST_FT_VERILOG_VHDL = 2, + FST_FT_VERILOG = 0, + FST_FT_VHDL = 1, + FST_FT_VERILOG_VHDL = 2, - FST_FT_MAX = 2 + FST_FT_MAX = 2 }; -enum fstBlockType { - FST_BL_HDR = 0, - FST_BL_VCDATA = 1, - FST_BL_BLACKOUT = 2, - 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, +enum fstBlockType +{ + FST_BL_HDR = 0, + FST_BL_VCDATA = 1, + FST_BL_BLACKOUT = 2, + 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 */ + FST_BL_ZWRAPPER = 254, /* indicates that whole trace is gz wrapped */ + FST_BL_SKIP = 255 /* used while block is being written */ }; -enum fstScopeType { - FST_ST_MIN = 0, +enum fstScopeType +{ + FST_ST_MIN = 0, - FST_ST_VCD_MODULE = 0, - FST_ST_VCD_TASK = 1, - FST_ST_VCD_FUNCTION = 2, - FST_ST_VCD_BEGIN = 3, - FST_ST_VCD_FORK = 4, - FST_ST_VCD_GENERATE = 5, - FST_ST_VCD_STRUCT = 6, - FST_ST_VCD_UNION = 7, - FST_ST_VCD_CLASS = 8, - FST_ST_VCD_INTERFACE = 9, - FST_ST_VCD_PACKAGE = 10, - FST_ST_VCD_PROGRAM = 11, + FST_ST_VCD_MODULE = 0, + FST_ST_VCD_TASK = 1, + FST_ST_VCD_FUNCTION = 2, + FST_ST_VCD_BEGIN = 3, + FST_ST_VCD_FORK = 4, + FST_ST_VCD_GENERATE = 5, + FST_ST_VCD_STRUCT = 6, + FST_ST_VCD_UNION = 7, + FST_ST_VCD_CLASS = 8, + FST_ST_VCD_INTERFACE = 9, + FST_ST_VCD_PACKAGE = 10, + FST_ST_VCD_PROGRAM = 11, - FST_ST_VHDL_ARCHITECTURE = 12, - FST_ST_VHDL_PROCEDURE = 13, - FST_ST_VHDL_FUNCTION = 14, - FST_ST_VHDL_RECORD = 15, - FST_ST_VHDL_PROCESS = 16, - FST_ST_VHDL_BLOCK = 17, - FST_ST_VHDL_FOR_GENERATE = 18, - FST_ST_VHDL_IF_GENERATE = 19, - FST_ST_VHDL_GENERATE = 20, - FST_ST_VHDL_PACKAGE = 21, + FST_ST_VHDL_ARCHITECTURE = 12, + FST_ST_VHDL_PROCEDURE = 13, + FST_ST_VHDL_FUNCTION = 14, + FST_ST_VHDL_RECORD = 15, + FST_ST_VHDL_PROCESS = 16, + FST_ST_VHDL_BLOCK = 17, + FST_ST_VHDL_FOR_GENERATE = 18, + FST_ST_VHDL_IF_GENERATE = 19, + FST_ST_VHDL_GENERATE = 20, + FST_ST_VHDL_PACKAGE = 21, - FST_ST_MAX = 21, + FST_ST_MAX = 21, - FST_ST_GEN_ATTRBEGIN = 252, - FST_ST_GEN_ATTREND = 253, + FST_ST_GEN_ATTRBEGIN = 252, + FST_ST_GEN_ATTREND = 253, - FST_ST_VCD_SCOPE = 254, - FST_ST_VCD_UPSCOPE = 255 + FST_ST_VCD_SCOPE = 254, + FST_ST_VCD_UPSCOPE = 255 }; -enum fstVarType { - FST_VT_MIN = 0, /* start of vartypes */ +enum fstVarType +{ + FST_VT_MIN = 0, /* start of vartypes */ - FST_VT_VCD_EVENT = 0, - FST_VT_VCD_INTEGER = 1, - FST_VT_VCD_PARAMETER = 2, - FST_VT_VCD_REAL = 3, - FST_VT_VCD_REAL_PARAMETER = 4, - FST_VT_VCD_REG = 5, - FST_VT_VCD_SUPPLY0 = 6, - FST_VT_VCD_SUPPLY1 = 7, - FST_VT_VCD_TIME = 8, - FST_VT_VCD_TRI = 9, - FST_VT_VCD_TRIAND = 10, - FST_VT_VCD_TRIOR = 11, - FST_VT_VCD_TRIREG = 12, - FST_VT_VCD_TRI0 = 13, - FST_VT_VCD_TRI1 = 14, - FST_VT_VCD_WAND = 15, - 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_REALTIME = 20, + FST_VT_VCD_EVENT = 0, + FST_VT_VCD_INTEGER = 1, + FST_VT_VCD_PARAMETER = 2, + FST_VT_VCD_REAL = 3, + FST_VT_VCD_REAL_PARAMETER = 4, + FST_VT_VCD_REG = 5, + FST_VT_VCD_SUPPLY0 = 6, + FST_VT_VCD_SUPPLY1 = 7, + FST_VT_VCD_TIME = 8, + FST_VT_VCD_TRI = 9, + FST_VT_VCD_TRIAND = 10, + FST_VT_VCD_TRIOR = 11, + FST_VT_VCD_TRIREG = 12, + FST_VT_VCD_TRI0 = 13, + FST_VT_VCD_TRI1 = 14, + FST_VT_VCD_WAND = 15, + 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_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_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_MAX = 29 /* end of vartypes */ + FST_VT_MAX = 29 /* end of vartypes */ }; -enum fstVarDir { - FST_VD_MIN = 0, +enum fstVarDir +{ + FST_VD_MIN = 0, - FST_VD_IMPLICIT = 0, - FST_VD_INPUT = 1, - FST_VD_OUTPUT = 2, - FST_VD_INOUT = 3, - FST_VD_BUFFER = 4, - FST_VD_LINKAGE = 5, + FST_VD_IMPLICIT = 0, + FST_VD_INPUT = 1, + FST_VD_OUTPUT = 2, + FST_VD_INOUT = 3, + FST_VD_BUFFER = 4, + FST_VD_LINKAGE = 5, - FST_VD_MAX = 5 + FST_VD_MAX = 5 }; -enum fstHierType { - FST_HT_MIN = 0, +enum fstHierType +{ + FST_HT_MIN = 0, - FST_HT_SCOPE = 0, - FST_HT_UPSCOPE = 1, - FST_HT_VAR = 2, - FST_HT_ATTRBEGIN = 3, - FST_HT_ATTREND = 4, + FST_HT_SCOPE = 0, + FST_HT_UPSCOPE = 1, + FST_HT_VAR = 2, + FST_HT_ATTRBEGIN = 3, + FST_HT_ATTREND = 4, - /* FST_HT_TREEBEGIN and FST_HT_TREEEND are not yet used by FST but are currently used when fstHier bridges other formats */ - FST_HT_TREEBEGIN = 5, - FST_HT_TREEEND = 6, + /* FST_HT_TREEBEGIN and FST_HT_TREEEND are not yet used by FST but are currently used when + fstHier bridges other formats */ + FST_HT_TREEBEGIN = 5, + FST_HT_TREEEND = 6, - FST_HT_MAX = 6 + FST_HT_MAX = 6 }; -enum fstAttrType { - FST_AT_MIN = 0, +enum fstAttrType +{ + FST_AT_MIN = 0, - 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, + 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, - FST_AT_MAX = 3 + FST_AT_MAX = 3 }; -enum fstMiscType { - FST_MT_MIN = 0, +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_PATHNAME = 3, /* reserved for fstWriterSetSourceStem() string -> number management */ - FST_MT_SOURCESTEM = 4, /* use fstWriterSetSourceStem() to emit */ - FST_MT_SOURCEISTEM = 5, /* use fstWriterSetSourceInstantiationStem() to emit */ - FST_MT_VALUELIST = 6, /* use fstWriterSetValueList() to emit, followed by fstWriterCreateVar*() */ - FST_MT_ENUMTABLE = 7, /* use fstWriterCreateEnumTable() and fstWriterEmitEnumTableRef() to emit */ - FST_MT_UNKNOWN = 8, + 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 */ + FST_MT_VALUELIST = + 6, /* use fstWriterSetValueList() to emit, followed by fstWriterCreateVar*() */ + FST_MT_ENUMTABLE = + 7, /* use fstWriterCreateEnumTable() and fstWriterEmitEnumTableRef() to emit */ + FST_MT_UNKNOWN = 8, - FST_MT_MAX = 8 + FST_MT_MAX = 8 }; -enum fstArrayType { - FST_AR_MIN = 0, +enum fstArrayType +{ + FST_AR_MIN = 0, - FST_AR_NONE = 0, - FST_AR_UNPACKED = 1, - FST_AR_PACKED = 2, - FST_AR_SPARSE = 3, + FST_AR_NONE = 0, + FST_AR_UNPACKED = 1, + FST_AR_PACKED = 2, + FST_AR_SPARSE = 3, - FST_AR_MAX = 3 + FST_AR_MAX = 3 }; -enum fstEnumValueType { - FST_EV_SV_INTEGER = 0, - FST_EV_SV_BIT = 1, - FST_EV_SV_LOGIC = 2, - FST_EV_SV_INT = 3, - FST_EV_SV_SHORTINT = 4, - FST_EV_SV_LONGINT = 5, - FST_EV_SV_BYTE = 6, - FST_EV_SV_UNSIGNED_INTEGER = 7, - FST_EV_SV_UNSIGNED_BIT = 8, - FST_EV_SV_UNSIGNED_LOGIC = 9, - FST_EV_SV_UNSIGNED_INT = 10, +enum fstEnumValueType +{ + FST_EV_SV_INTEGER = 0, + FST_EV_SV_BIT = 1, + FST_EV_SV_LOGIC = 2, + FST_EV_SV_INT = 3, + FST_EV_SV_SHORTINT = 4, + FST_EV_SV_LONGINT = 5, + FST_EV_SV_BYTE = 6, + FST_EV_SV_UNSIGNED_INTEGER = 7, + FST_EV_SV_UNSIGNED_BIT = 8, + FST_EV_SV_UNSIGNED_LOGIC = 9, + FST_EV_SV_UNSIGNED_INT = 10, FST_EV_SV_UNSIGNED_SHORTINT = 11, - FST_EV_SV_UNSIGNED_LONGINT = 12, - FST_EV_SV_UNSIGNED_BYTE = 13, + FST_EV_SV_UNSIGNED_LONGINT = 12, + FST_EV_SV_UNSIGNED_BYTE = 13, - FST_EV_REG = 14, - FST_EV_TIME = 15, + FST_EV_REG = 14, + FST_EV_TIME = 15, - FST_EV_MAX = 15 + FST_EV_MAX = 15 }; -enum fstPackType { - FST_PT_NONE = 0, - FST_PT_UNPACKED = 1, - FST_PT_PACKED = 2, +enum fstPackType +{ + FST_PT_NONE = 0, + FST_PT_UNPACKED = 1, + FST_PT_PACKED = 2, FST_PT_TAGGED_PACKED = 3, - FST_PT_MAX = 3 + FST_PT_MAX = 3 }; -enum fstSupplementalVarType { - FST_SVT_MIN = 0, +enum fstSupplementalVarType +{ + FST_SVT_MIN = 0, - FST_SVT_NONE = 0, + FST_SVT_NONE = 0, - FST_SVT_VHDL_SIGNAL = 1, - FST_SVT_VHDL_VARIABLE = 2, - FST_SVT_VHDL_CONSTANT = 3, - FST_SVT_VHDL_FILE = 4, - FST_SVT_VHDL_MEMORY = 5, + FST_SVT_VHDL_SIGNAL = 1, + FST_SVT_VHDL_VARIABLE = 2, + FST_SVT_VHDL_CONSTANT = 3, + FST_SVT_VHDL_FILE = 4, + FST_SVT_VHDL_MEMORY = 5, - FST_SVT_MAX = 5 + FST_SVT_MAX = 5 }; -enum fstSupplementalDataType { - FST_SDT_MIN = 0, +enum fstSupplementalDataType +{ + FST_SDT_MIN = 0, - FST_SDT_NONE = 0, + FST_SDT_NONE = 0, - FST_SDT_VHDL_BOOLEAN = 1, - FST_SDT_VHDL_BIT = 2, - FST_SDT_VHDL_BIT_VECTOR = 3, - FST_SDT_VHDL_STD_ULOGIC = 4, + FST_SDT_VHDL_BOOLEAN = 1, + FST_SDT_VHDL_BIT = 2, + FST_SDT_VHDL_BIT_VECTOR = 3, + FST_SDT_VHDL_STD_ULOGIC = 4, FST_SDT_VHDL_STD_ULOGIC_VECTOR = 5, - FST_SDT_VHDL_STD_LOGIC = 6, - FST_SDT_VHDL_STD_LOGIC_VECTOR = 7, - FST_SDT_VHDL_UNSIGNED = 8, - FST_SDT_VHDL_SIGNED = 9, - FST_SDT_VHDL_INTEGER = 10, - FST_SDT_VHDL_REAL = 11, - FST_SDT_VHDL_NATURAL = 12, - FST_SDT_VHDL_POSITIVE = 13, - FST_SDT_VHDL_TIME = 14, - FST_SDT_VHDL_CHARACTER = 15, - FST_SDT_VHDL_STRING = 16, + FST_SDT_VHDL_STD_LOGIC = 6, + FST_SDT_VHDL_STD_LOGIC_VECTOR = 7, + FST_SDT_VHDL_UNSIGNED = 8, + FST_SDT_VHDL_SIGNED = 9, + FST_SDT_VHDL_INTEGER = 10, + FST_SDT_VHDL_REAL = 11, + FST_SDT_VHDL_NATURAL = 12, + FST_SDT_VHDL_POSITIVE = 13, + FST_SDT_VHDL_TIME = 14, + FST_SDT_VHDL_CHARACTER = 15, + FST_SDT_VHDL_STRING = 16, - FST_SDT_MAX = 16, + 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_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) }; - struct fstHier { -unsigned char htyp; + unsigned char htyp; -union { + 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; + 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; + 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; + 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; }; - struct fstETab { -char *name; -uint32_t elem_count; -char **literal_arr; -char **val_arr; + char *name; + uint32_t elem_count; + char **literal_arr; + char **val_arr; }; - /* * writer functions */ -void fstWriterClose(void *ctx); -void * fstWriterCreate(const char *nam, int use_compressed_hier); -fstEnumHandle fstWriterCreateEnumTable(void *ctx, const char *name, uint32_t elem_count, unsigned int min_valbits, const char **literal_arr, const char **val_arr); - /* used for Verilog/SV */ -fstHandle fstWriterCreateVar(void *ctx, enum fstVarType vt, enum fstVarDir vd, - uint32_t len, const char *nam, fstHandle aliasHandle); - /* 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 fstWriterEmitDumpActive(void *ctx, int enable); -void fstWriterEmitEnumTableRef(void *ctx, fstEnumHandle handle); -void fstWriterEmitValueChange(void *ctx, fstHandle handle, const void *val); -void fstWriterEmitValueChange32(void *ctx, fstHandle handle, - uint32_t bits, uint32_t val); -void fstWriterEmitValueChange64(void *ctx, fstHandle handle, - uint32_t bits, uint64_t val); -void fstWriterEmitValueChangeVec32(void *ctx, fstHandle handle, - uint32_t bits, const uint32_t *val); -void fstWriterEmitValueChangeVec64(void *ctx, fstHandle handle, - uint32_t bits, const uint64_t *val); -void fstWriterEmitVariableLengthValueChange(void *ctx, fstHandle handle, const void *val, uint32_t len); -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 fstWriterSetValueList(void *ctx, const char *vl); -void fstWriterSetVersion(void *ctx, const char *vers); +typedef struct fstWriterContext fstWriterContext; + +void fstWriterClose(fstWriterContext *ctx); +fstWriterContext *fstWriterCreate(const char *nam, int use_compressed_hier); +fstEnumHandle fstWriterCreateEnumTable(fstWriterContext *ctx, + const char *name, + uint32_t elem_count, + unsigned int min_valbits, + const char **literal_arr, + const char **val_arr); +/* used for Verilog/SV */ +fstHandle fstWriterCreateVar(fstWriterContext *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(fstWriterContext *ctx, + enum fstVarType vt, + enum fstVarDir vd, + uint32_t len, + const char *nam, + fstHandle aliasHandle, + const char *type, + enum fstSupplementalVarType svt, + enum fstSupplementalDataType sdt); +void fstWriterEmitDumpActive(fstWriterContext *ctx, int enable); +void fstWriterEmitEnumTableRef(fstWriterContext *ctx, fstEnumHandle handle); +void fstWriterEmitValueChange(fstWriterContext *ctx, fstHandle handle, const void *val); +void fstWriterEmitValueChange32(fstWriterContext *ctx, + fstHandle handle, + uint32_t bits, + uint32_t val); +void fstWriterEmitValueChange64(fstWriterContext *ctx, + fstHandle handle, + uint32_t bits, + uint64_t val); +void fstWriterEmitValueChangeVec32(fstWriterContext *ctx, + fstHandle handle, + uint32_t bits, + const uint32_t *val); +void fstWriterEmitValueChangeVec64(fstWriterContext *ctx, + fstHandle handle, + uint32_t bits, + const uint64_t *val); +void fstWriterEmitVariableLengthValueChange(fstWriterContext *ctx, + fstHandle handle, + const void *val, + uint32_t len); +void fstWriterEmitTimeChange(fstWriterContext *ctx, uint64_t tim); +void fstWriterFlushContext(fstWriterContext *ctx); +int fstWriterGetDumpSizeLimitReached(fstWriterContext *ctx); +int fstWriterGetFseekFailed(fstWriterContext *ctx); +int fstWriterGetFlushContextPending(fstWriterContext *ctx); +void fstWriterSetAttrBegin(fstWriterContext *ctx, + enum fstAttrType attrtype, + int subtype, + const char *attrname, + uint64_t arg); +void fstWriterSetAttrEnd(fstWriterContext *ctx); +void fstWriterSetComment(fstWriterContext *ctx, const char *comm); +void fstWriterSetDate(fstWriterContext *ctx, const char *dat); +void fstWriterSetDumpSizeLimit(fstWriterContext *ctx, uint64_t numbytes); +void fstWriterSetEnvVar(fstWriterContext *ctx, const char *envvar); +void fstWriterSetFileType(fstWriterContext *ctx, enum fstFileType filetype); +void fstWriterSetPackType(fstWriterContext *ctx, enum fstWriterPackType typ); +void fstWriterSetParallelMode(fstWriterContext *ctx, int enable); +void fstWriterSetRepackOnClose(fstWriterContext *ctx, + int enable); /* type = 0 (none), 1 (libz) */ +void fstWriterSetScope(fstWriterContext *ctx, + enum fstScopeType scopetype, + const char *scopename, + const char *scopecomp); +void fstWriterSetSourceInstantiationStem(fstWriterContext *ctx, + const char *path, + unsigned int line, + unsigned int use_realpath); +void fstWriterSetSourceStem(fstWriterContext *ctx, + const char *path, + unsigned int line, + unsigned int use_realpath); +void fstWriterSetTimescale(fstWriterContext *ctx, int ts); +void fstWriterSetTimescaleFromString(fstWriterContext *ctx, const char *s); +void fstWriterSetTimezero(fstWriterContext *ctx, int64_t tim); +void fstWriterSetUpscope(fstWriterContext *ctx); +void fstWriterSetValueList(fstWriterContext *ctx, const char *vl); +void fstWriterSetVersion(fstWriterContext *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); -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); +typedef struct fstReaderContext fstReaderContext; + +void fstReaderClose(fstReaderContext *ctx); +void fstReaderClrFacProcessMask(fstReaderContext *ctx, fstHandle facidx); +void fstReaderClrFacProcessMaskAll(fstReaderContext *ctx); +uint64_t fstReaderGetAliasCount(fstReaderContext *ctx); +const char *fstReaderGetCurrentFlatScope(fstReaderContext *ctx); +void *fstReaderGetCurrentScopeUserInfo(fstReaderContext *ctx); +int fstReaderGetCurrentScopeLen(fstReaderContext *ctx); +const char *fstReaderGetDateString(fstReaderContext *ctx); +int fstReaderGetDoubleEndianMatchState(fstReaderContext *ctx); +uint64_t fstReaderGetDumpActivityChangeTime(fstReaderContext *ctx, uint32_t idx); +unsigned char fstReaderGetDumpActivityChangeValue(fstReaderContext *ctx, uint32_t idx); +uint64_t fstReaderGetEndTime(fstReaderContext *ctx); +int fstReaderGetFacProcessMask(fstReaderContext *ctx, fstHandle facidx); +int fstReaderGetFileType(fstReaderContext *ctx); +int fstReaderGetFseekFailed(fstReaderContext *ctx); +fstHandle fstReaderGetMaxHandle(fstReaderContext *ctx); +uint64_t fstReaderGetMemoryUsedByWriter(fstReaderContext *ctx); +uint32_t fstReaderGetNumberDumpActivityChanges(fstReaderContext *ctx); +uint64_t fstReaderGetScopeCount(fstReaderContext *ctx); +uint64_t fstReaderGetStartTime(fstReaderContext *ctx); +signed char fstReaderGetTimescale(fstReaderContext *ctx); +int64_t fstReaderGetTimezero(fstReaderContext *ctx); +uint64_t fstReaderGetValueChangeSectionCount(fstReaderContext *ctx); +char *fstReaderGetValueFromHandleAtTime(fstReaderContext *ctx, + uint64_t tim, + fstHandle facidx, + char *buf); +uint64_t fstReaderGetVarCount(fstReaderContext *ctx); +const char *fstReaderGetVersionString(fstReaderContext *ctx); +struct fstHier *fstReaderIterateHier(fstReaderContext *ctx); +int fstReaderIterateHierRewind(fstReaderContext *ctx); +int fstReaderIterBlocks(fstReaderContext *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(fstReaderContext *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(fstReaderContext *ctx, int enable); +fstReaderContext *fstReaderOpen(const char *nam); +fstReaderContext *fstReaderOpenForUtilitiesOnly(void); +const char *fstReaderPopScope(fstReaderContext *ctx); +int fstReaderProcessHier(fstReaderContext *ctx, FILE *vcdhandle); +const char *fstReaderPushScope(fstReaderContext *ctx, const char *nam, void *user_info); +void fstReaderResetScope(fstReaderContext *ctx); +void fstReaderSetFacProcessMask(fstReaderContext *ctx, fstHandle facidx); +void fstReaderSetFacProcessMaskAll(fstReaderContext *ctx); +void fstReaderSetLimitTimeRange(fstReaderContext *ctx, uint64_t start_time, uint64_t end_time); +void fstReaderSetUnlimitedTimeRange(fstReaderContext *ctx); +void fstReaderSetVcdExtensions(fstReaderContext *ctx, int enable); /* * utility functions */ -int fstUtilityBinToEscConvertedLen(const unsigned char *s, int len); /* used for mallocs for fstUtilityBinToEsc() */ -int fstUtilityBinToEsc(unsigned char *d, const unsigned char *s, int len); -int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len); +int fstUtilityBinToEscConvertedLen(const unsigned char *s, int len); /* used for mallocs for fstUtilityBinToEsc() */ +int fstUtilityBinToEsc(unsigned char *d, const unsigned char *s, int len); +int fstUtilityEscToBin(unsigned char *d, unsigned char *s, int len); struct fstETab *fstUtilityExtractEnumTableFromString(const char *s); -void fstUtilityFreeEnumTable(struct fstETab *etab); /* must use to free fstETab properly */ - +void fstUtilityFreeEnumTable(struct fstETab *etab); /* must use to free fstETab properly */ #ifdef __cplusplus } diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index bb4eb3d82..b250d23d8 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -2400,7 +2400,7 @@ struct VCDWriter : public OutputWriter struct FSTWriter : public OutputWriter { FSTWriter(SimWorker *worker, std::string filename) : OutputWriter(worker) { - fstfile = (struct fstContext *)fstWriterCreate(filename.c_str(),1); + fstfile = fstWriterCreate(filename.c_str(),1); } virtual ~FSTWriter() @@ -2456,7 +2456,7 @@ struct FSTWriter : public OutputWriter } } - struct fstContext *fstfile = nullptr; + struct fstWriterContext *fstfile = nullptr; std::map mapping; }; From d0b9a0cb98f7e84c69a6cdd1f43205d6b9d61511 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Mon, 12 May 2025 12:48:01 +1200 Subject: [PATCH 27/74] sim.cc: Move cycle check Calling `throw dst_end_of_data_exception()` when the desired number of cycles has been reached means that the fst reader can't tidy up after itself and leads to memory leaks. This doesn't happen when the `-stop` flag is used because the `Yosys::FstData` struct tracks the end time and skips the outer callback if the simulation has gone past the desired end time. Move cycle checking into the inner callback along with the time checking means that the outer callback no longer needs to throw an exception in order to stop checking further values, while still allowing the fst reader to finish reading and deallocate memory. --- kernel/fstdata.cc | 17 +++++++-- kernel/fstdata.h | 4 +- passes/sat/sim.cc | 96 +++++++++++++++++++---------------------------- 3 files changed, 55 insertions(+), 62 deletions(-) diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index a62691fa1..c127cdf83 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -206,6 +206,7 @@ static void reconstruct_clb_attimes(void *user_data, uint64_t pnt_time, fstHandl void FstData::reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t /* plen */) { if (pnt_time > end_time || !pnt_value) return; + if (curr_cycle > last_cycle) return; // if we are past the timestamp bool is_clock = false; if (!all_samples) { @@ -225,6 +226,7 @@ void FstData::reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_faci if (pnt_time > last_time) { if (all_samples) { callback(last_time); + curr_cycle++; last_time = pnt_time; } else { if (is_clock) { @@ -232,6 +234,7 @@ void FstData::reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_faci std::string prev = past_data[pnt_facidx]; if ((prev!="1" && val=="1") || (prev!="0" && val=="0")) { callback(last_time); + curr_cycle++; last_time = pnt_time; } } @@ -241,12 +244,14 @@ void FstData::reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_faci last_data[pnt_facidx] = std::string((const char *)pnt_value); } -void FstData::reconstructAllAtTimes(std::vector &signal, uint64_t start, uint64_t end, CallbackFunction cb) +void FstData::reconstructAllAtTimes(std::vector &signal, uint64_t start, uint64_t end, unsigned int end_cycle, CallbackFunction cb) { clk_signals = signal; callback = cb; start_time = start; end_time = end; + curr_cycle = 0; + last_cycle = end_cycle; last_data.clear(); last_time = start_time; past_data.clear(); @@ -256,12 +261,16 @@ void FstData::reconstructAllAtTimes(std::vector &signal, uint64_t sta fstReaderSetUnlimitedTimeRange(ctx); fstReaderSetFacProcessMaskAll(ctx); fstReaderIterBlocks2(ctx, reconstruct_clb_attimes, reconstruct_clb_varlen_attimes, this, nullptr); - if (last_time!=end_time) { + if (last_time!=end_time && curr_cycle < last_cycle) { past_data = last_data; callback(last_time); + curr_cycle++; + } + if (curr_cycle < last_cycle) { + past_data = last_data; + callback(end_time); + curr_cycle++; } - past_data = last_data; - callback(end_time); } std::string FstData::valueOf(fstHandle signal) diff --git a/kernel/fstdata.h b/kernel/fstdata.h index f5cf1d48d..a8ae40301 100644 --- a/kernel/fstdata.h +++ b/kernel/fstdata.h @@ -50,7 +50,7 @@ class FstData std::vector& getVars() { return vars; }; void reconstruct_callback_attimes(uint64_t pnt_time, fstHandle pnt_facidx, const unsigned char *pnt_value, uint32_t plen); - void reconstructAllAtTimes(std::vector &signal, uint64_t start_time, uint64_t end_time, CallbackFunction cb); + void reconstructAllAtTimes(std::vector &signal, uint64_t start_time, uint64_t end_time, unsigned int end_cycle, CallbackFunction cb); std::string valueOf(fstHandle signal); fstHandle getHandle(std::string name); @@ -73,6 +73,8 @@ private: std::string timescale_str; uint64_t start_time; uint64_t end_time; + unsigned int last_cycle; + unsigned int curr_cycle; CallbackFunction callback; std::vector clk_signals; bool all_samples; diff --git a/passes/sat/sim.cc b/passes/sat/sim.cc index b250d23d8..e2b0022ff 100644 --- a/passes/sat/sim.cc +++ b/passes/sat/sim.cc @@ -1546,36 +1546,27 @@ struct SimWorker : SimShared log(" for %d clock cycle(s)",numcycles); log("\n"); bool all_samples = fst_clock.empty(); + unsigned int end_cycle = cycles_set ? numcycles*2 : INT_MAX; - try { - fst->reconstructAllAtTimes(fst_clock, startCount, stopCount, [&](uint64_t time) { - if (verbose) - log("Co-simulating %s %d [%lu%s].\n", (all_samples ? "sample" : "cycle"), cycle, (unsigned long)time, fst->getTimescaleString()); - bool did_something = top->setInputs(); + fst->reconstructAllAtTimes(fst_clock, startCount, stopCount, end_cycle, [&](uint64_t time) { + if (verbose) + log("Co-simulating %s %d [%lu%s].\n", (all_samples ? "sample" : "cycle"), cycle, (unsigned long)time, fst->getTimescaleString()); + bool did_something = top->setInputs(); - if (initial) { - if (!fst_noinit) did_something |= top->setInitState(); - initialize_stable_past(); - initial = false; - } - if (did_something) - update(true); - register_output_step(time); + if (initial) { + if (!fst_noinit) did_something |= top->setInitState(); + initialize_stable_past(); + initial = false; + } + if (did_something) + update(true); + register_output_step(time); - bool status = top->checkSignals(); - if (status) - log_error("Signal difference\n"); - cycle++; - - // Limit to number of cycles if provided - if (cycles_set && cycle > numcycles *2) - throw fst_end_of_data_exception(); - if (time==stopCount) - throw fst_end_of_data_exception(); - }); - } catch(fst_end_of_data_exception) { - // end of data detected - } + bool status = top->checkSignals(); + if (status) + log_error("Signal difference\n"); + cycle++; + }); write_output_files(); delete fst; @@ -2248,40 +2239,31 @@ struct SimWorker : SimShared log("Writing data to `%s`\n", (tb_filename+".txt").c_str()); std::ofstream data_file(tb_filename+".txt"); std::stringstream initstate; - try { - fst->reconstructAllAtTimes(fst_clock, startCount, stopCount, [&](uint64_t time) { - for(auto &item : clocks) - data_file << stringf("%s",fst->valueOf(item.second).c_str()); - for(auto &item : inputs) - data_file << stringf("%s",fst->valueOf(item.second).c_str()); - for(auto &item : outputs) - data_file << stringf("%s",fst->valueOf(item.second).c_str()); - data_file << stringf("%s\n",Const(time-prev_time).as_string().c_str()); + unsigned int end_cycle = cycles_set ? numcycles*2 : INT_MAX; + fst->reconstructAllAtTimes(fst_clock, startCount, stopCount, end_cycle, [&](uint64_t time) { + for(auto &item : clocks) + data_file << stringf("%s",fst->valueOf(item.second).c_str()); + for(auto &item : inputs) + data_file << stringf("%s",fst->valueOf(item.second).c_str()); + for(auto &item : outputs) + data_file << stringf("%s",fst->valueOf(item.second).c_str()); + data_file << stringf("%s\n",Const(time-prev_time).as_string().c_str()); - if (time==startCount) { - // initial state - for(auto var : fst->getVars()) { - if (var.is_reg && !Const::from_string(fst->valueOf(var.id).c_str()).is_fully_undef()) { - if (var.scope == scope) { - initstate << stringf("\t\tuut.%s = %d'b%s;\n", var.name.c_str(), var.width, fst->valueOf(var.id).c_str()); - } else if (var.scope.find(scope+".")==0) { - initstate << stringf("\t\tuut.%s.%s = %d'b%s;\n",var.scope.substr(scope.size()+1).c_str(), var.name.c_str(), var.width, fst->valueOf(var.id).c_str()); - } + if (time==startCount) { + // initial state + for(auto var : fst->getVars()) { + if (var.is_reg && !Const::from_string(fst->valueOf(var.id).c_str()).is_fully_undef()) { + if (var.scope == scope) { + initstate << stringf("\t\tuut.%s = %d'b%s;\n", var.name.c_str(), var.width, fst->valueOf(var.id).c_str()); + } else if (var.scope.find(scope+".")==0) { + initstate << stringf("\t\tuut.%s.%s = %d'b%s;\n",var.scope.substr(scope.size()+1).c_str(), var.name.c_str(), var.width, fst->valueOf(var.id).c_str()); } } } - cycle++; - prev_time = time; - - // Limit to number of cycles if provided - if (cycles_set && cycle > numcycles *2) - throw fst_end_of_data_exception(); - if (time==stopCount) - throw fst_end_of_data_exception(); - }); - } catch(fst_end_of_data_exception) { - // end of data detected - } + } + cycle++; + prev_time = time; + }); f << stringf("\treg [0:%d] data [0:%d];\n", data_len-1, cycle-1); f << "\tinitial begin;\n"; From afd5bbc7fac5b33d6cec6b545c409b8cc3fa5707 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Mon, 12 May 2025 13:18:19 +1200 Subject: [PATCH 28/74] fstdata.cc: Fix last step Includes test file for sanity checking simulation steps. --- kernel/fstdata.cc | 4 ++-- tests/sim/sim_cycles.ys | 51 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 tests/sim/sim_cycles.ys diff --git a/kernel/fstdata.cc b/kernel/fstdata.cc index c127cdf83..c7bc34dd9 100644 --- a/kernel/fstdata.cc +++ b/kernel/fstdata.cc @@ -261,12 +261,12 @@ void FstData::reconstructAllAtTimes(std::vector &signal, uint64_t sta fstReaderSetUnlimitedTimeRange(ctx); fstReaderSetFacProcessMaskAll(ctx); fstReaderIterBlocks2(ctx, reconstruct_clb_attimes, reconstruct_clb_varlen_attimes, this, nullptr); - if (last_time!=end_time && curr_cycle < last_cycle) { + if (last_time!=end_time && curr_cycle <= last_cycle) { past_data = last_data; callback(last_time); curr_cycle++; } - if (curr_cycle < last_cycle) { + if (curr_cycle <= last_cycle) { past_data = last_data; callback(end_time); curr_cycle++; diff --git a/tests/sim/sim_cycles.ys b/tests/sim/sim_cycles.ys new file mode 100644 index 000000000..7c6c943d9 --- /dev/null +++ b/tests/sim/sim_cycles.ys @@ -0,0 +1,51 @@ +read_verilog dff.v +prep + +# create fst with 20 clock cycles (41 samples, 202ns) +sim -clock clk -fst sim_cycles.fst -n 20 + +logger -expect-no-warnings + +# final step is 41 +logger -expect log "Co-simulating cycle 41" 2 +logger -warn "Co-simulating cycle 42" +sim -clock clk -r sim_cycles.fst -scope dff -n 21 -sim-cmp +sim -clock clk -r sim_cycles.fst -scope dff -stop 202 -sim-cmp +logger -check-expected + +# over limit stops at final step +logger -expect log "Co-simulating cycle 41" 2 +sim -clock clk -r sim_cycles.fst -scope dff -n 30 -sim-cmp +# -stop warns for over limit +logger -nowarn "Stop time is after simulation file end time" +sim -clock clk -r sim_cycles.fst -scope dff -stop 300 -sim-cmp +logger -check-expected + +# don't auto step last +logger -expect log "Co-simulating cycle 40" 2 +logger -warn "Co-simulating cycle 41" +sim -clock clk -r sim_cycles.fst -scope dff -n 20 -sim-cmp +sim -clock clk -r sim_cycles.fst -scope dff -stop 200 -sim-cmp +logger -check-expected + +# -n 10 == -stop 100 +# should simulate up to 20 and not more +logger -expect log "Co-simulating cycle 20" 2 +logger -warn "Co-simulating cycle 21" +sim -clock clk -r sim_cycles.fst -scope dff -n 10 -sim-cmp +sim -clock clk -r sim_cycles.fst -scope dff -stop 100 -sim-cmp +logger -check-expected + +# -n 1 == -stop 10 +logger -expect log "Co-simulating cycle 2" 2 +logger -warn "Co-simulating cycle 3" +sim -clock clk -r sim_cycles.fst -scope dff -n 1 -sim-cmp +sim -clock clk -r sim_cycles.fst -scope dff -stop 10 -sim-cmp +logger -check-expected + +# -n 0 == -stop 0 +logger -expect log "Co-simulating cycle 0" 2 +logger -warn "Co-simulating cycle 1" +sim -clock clk -r sim_cycles.fst -scope dff -n 0 -sim-cmp +sim -clock clk -r sim_cycles.fst -scope dff -stop 0 -sim-cmp +logger -check-expected From 5e72464a15b70b25d89bd2cd999c76e7d8506b32 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Tue, 6 May 2025 12:02:00 +0200 Subject: [PATCH 29/74] rtlil: enable single-bit vector wires --- backends/verilog/verilog_backend.cc | 3 +++ frontends/ast/genrtlil.cc | 1 + frontends/ast/simplify.cc | 6 ++++++ kernel/constids.inc | 1 + tests/verilog/sbvector.ys | 20 ++++++++++++++++++++ 5 files changed, 31 insertions(+) create mode 100644 tests/verilog/sbvector.ys diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 2bc6ff3b8..1b828dcbd 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -419,6 +419,9 @@ void dump_wire(std::ostream &f, std::string indent, RTLIL::Wire *wire) range = stringf(" [%d:%d]", wire->start_offset, wire->width - 1 + wire->start_offset); else range = stringf(" [%d:%d]", wire->width - 1 + wire->start_offset, wire->start_offset); + } else { + if (wire->attributes.count(ID::single_bit_vector)) + range = stringf(" [%d:%d]", wire->start_offset, wire->start_offset); } if (wire->port_input && !wire->port_output) f << stringf("%s" "input%s %s;\n", indent.c_str(), range.c_str(), id(wire->name).c_str()); diff --git a/frontends/ast/genrtlil.cc b/frontends/ast/genrtlil.cc index d3982b92b..26ed0e3e4 100644 --- a/frontends/ast/genrtlil.cc +++ b/frontends/ast/genrtlil.cc @@ -1446,6 +1446,7 @@ RTLIL::SigSpec AstNode::genRTLIL(int width_hint, bool sign_hint) wire->port_input = is_input; wire->port_output = is_output; wire->upto = range_swapped; + wire->is_signed = is_signed; for (auto &attr : attributes) { diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 3411d6c03..a45eb1cc1 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2084,6 +2084,8 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin std::swap(range_left, range_right); range_swapped = force_upto; } + if (range_left == range_right) + set_attribute(ID::single_bit_vector, mkconst_int(1, false)); } } else { if (!range_valid) @@ -2092,6 +2094,10 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin range_swapped = false; range_left = 0; range_right = 0; + if (attributes.count(ID::single_bit_vector)) { + delete attributes[ID::single_bit_vector]; + attributes.erase(ID::single_bit_vector); + } } } diff --git a/kernel/constids.inc b/kernel/constids.inc index 4fdbb3dc8..055ebf2a8 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -184,6 +184,7 @@ X(romstyle) X(S) X(SET) X(SET_POLARITY) +X(single_bit_vector) X(SIZE) X(SRC) X(src) diff --git a/tests/verilog/sbvector.ys b/tests/verilog/sbvector.ys new file mode 100644 index 000000000..3481f6f45 --- /dev/null +++ b/tests/verilog/sbvector.ys @@ -0,0 +1,20 @@ +read_verilog < Date: Mon, 12 May 2025 13:23:02 +0200 Subject: [PATCH 30/74] verific: support single_bit_vector --- frontends/verific/verific.cc | 4 ++++ tests/verilog/sbvector.ys | 20 +++++++++++++++----- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 95bede420..411804566 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -1557,6 +1557,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma wire->start_offset = min(portbus->LeftIndex(), portbus->RightIndex()); wire->upto = portbus->IsUp(); import_attributes(wire->attributes, portbus, nl, portbus->Size()); + if (portbus->Size() == 1) + wire->set_bool_attribute(ID::single_bit_vector); SetIter si ; Port *port ; FOREACH_PORT_OF_PORTBUS(portbus, si, port) { @@ -1755,6 +1757,8 @@ void VerificImporter::import_netlist(RTLIL::Design *design, Netlist *nl, std::ma break; } import_attributes(wire->attributes, netbus, nl, netbus->Size()); + if (netbus->Size() == 1) + wire->set_bool_attribute(ID::single_bit_vector); RTLIL::Const initval = Const(State::Sx, GetSize(wire)); bool initval_valid = false; diff --git a/tests/verilog/sbvector.ys b/tests/verilog/sbvector.ys index 3481f6f45..ab8092700 100644 --- a/tests/verilog/sbvector.ys +++ b/tests/verilog/sbvector.ys @@ -4,17 +4,27 @@ module foo( input [0:0] i1, input i2 ); - assign o = i1 ^ i2; + wire [0:0] w1 = i1 ^ i2; + wire w2 = ~i1; + assign o = w1 ^ w2; endmodule EOT -logger -expect log "wire width 1 input 2 \\i1" 1 -logger -expect log "wire input 3 \\i2" 1 -dump -logger -check-expected +hierarchy +proc +select -assert-count 1 w:i1 +select -assert-count 1 w:i1 a:single_bit_vector %i +select -assert-count 1 w:i2 +select -assert-count 0 w:i2 a:single_bit_vector %i +select -assert-count 1 w:w1 +select -assert-count 1 w:w1 a:single_bit_vector %i +select -assert-count 1 w:w2 +select -assert-count 0 w:w2 a:single_bit_vector %i write_verilog verilog_sbvector.out !grep -qF 'wire [0:0] i1;' verilog_sbvector.out !grep -qF 'input [0:0] i1;' verilog_sbvector.out !grep -qF 'wire i2;' verilog_sbvector.out !grep -qF 'input i2;' verilog_sbvector.out +!grep -qF 'wire [0:0] w1;' verilog_sbvector.out +!grep -qF 'wire w2;' verilog_sbvector.out From f73c6a9c9ac1dcaee9ce283c73a6cf9fae07bc6e Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Mon, 12 May 2025 13:36:25 +0200 Subject: [PATCH 31/74] write_verilog: don't dump single_bit_vector attribute --- backends/verilog/verilog_backend.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/backends/verilog/verilog_backend.cc b/backends/verilog/verilog_backend.cc index 1b828dcbd..10cf7c52e 100644 --- a/backends/verilog/verilog_backend.cc +++ b/backends/verilog/verilog_backend.cc @@ -383,6 +383,7 @@ void dump_attributes(std::ostream &f, std::string indent, dictfirst == ID::single_bit_vector) continue; if (it->first == ID::init && regattr) continue; f << stringf("%s" "%s %s", indent.c_str(), as_comment ? "/*" : "(*", id(it->first).c_str()); f << stringf(" = "); From e3ae7b14008b55262d985cbbc201daf2f0ad178b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 13 May 2025 00:24:04 +0000 Subject: [PATCH 32/74] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3800cb373..fb0ad0e37 100644 --- a/Makefile +++ b/Makefile @@ -160,7 +160,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.53+15 +YOSYS_VER := 0.53+24 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2) From 748600c1679674633c98117e8dac06b9fbcbde3e Mon Sep 17 00:00:00 2001 From: George Rennie Date: Wed, 14 May 2025 14:18:57 +0100 Subject: [PATCH 33/74] small whitespace cleanup (#5119) --- kernel/rtlil.h | 2 +- passes/opt/opt_expr.cc | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 96c8c523b..3ef092c08 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -1182,7 +1182,7 @@ struct RTLIL::Selection bool boxes = false, // the design to select from RTLIL::Design *design = nullptr - ) : + ) : selects_boxes(boxes), complete_selection(full && boxes), full_selection(full && !boxes), current_design(design) { } // checks if the given module exists in the current design and is a diff --git a/passes/opt/opt_expr.cc b/passes/opt/opt_expr.cc index 74f5b386a..742fb0029 100644 --- a/passes/opt/opt_expr.cc +++ b/passes/opt/opt_expr.cc @@ -487,7 +487,7 @@ void replace_const_cells(RTLIL::Design *design, RTLIL::Module *module, bool cons handle_clkpol_celltype_swap(cell, "$_DLATCHSR_N??_", "$_DLATCHSR_P??_", ID::E, assign_map, invert_map); handle_clkpol_celltype_swap(cell, "$_DLATCHSR_?N?_", "$_DLATCHSR_?P?_", ID::S, assign_map, invert_map); - handle_clkpol_celltype_swap(cell, "$_DLATCHSR_??N_", "$_DLATCHSR_??P_", ID::R, assign_map, invert_map); + handle_clkpol_celltype_swap(cell, "$_DLATCHSR_??N_", "$_DLATCHSR_??P_", ID::R, assign_map, invert_map); } TopoSort> cells; @@ -1715,22 +1715,22 @@ skip_identity: if (onehot) { if (bit_idx == 1) { - log_debug("Replacing pow cell `%s' in module `%s' with left-shift\n", + log_debug("Replacing pow cell `%s' in module `%s' with left-shift\n", cell->name.c_str(), module->name.c_str()); cell->type = ID($shl); cell->parameters[ID::A_WIDTH] = 1; cell->setPort(ID::A, Const(State::S1, 1)); } else { - log_debug("Replacing pow cell `%s' in module `%s' with multiply and left-shift\n", + log_debug("Replacing pow cell `%s' in module `%s' with multiply and left-shift\n", cell->name.c_str(), module->name.c_str()); cell->type = ID($mul); cell->parameters[ID::A_SIGNED] = 0; cell->setPort(ID::A, Const(bit_idx, cell->parameters[ID::A_WIDTH].as_int())); - + SigSpec y_wire = module->addWire(NEW_ID, y_size); cell->setPort(ID::Y, y_wire); - + module->addShl(NEW_ID, Const(State::S1, 1), y_wire, sig_y); } did_something = true; From ae47c49af5d71873adc8ed396a9964ebac7f6f3b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 15 May 2025 00:22:59 +0000 Subject: [PATCH 34/74] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index fb0ad0e37..939d80368 100644 --- a/Makefile +++ b/Makefile @@ -160,7 +160,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.53+24 +YOSYS_VER := 0.53+26 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2) From 7d4d544001823db10493cc9c20efea91fcad55ad Mon Sep 17 00:00:00 2001 From: "William D. Jones" Date: Thu, 15 May 2025 18:36:04 -0400 Subject: [PATCH 35/74] Strip trailing slashes when checking for directories on Windows. --- kernel/io.cc | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/kernel/io.cc b/kernel/io.cc index d5d2994b2..d7d126c4c 100644 --- a/kernel/io.cc +++ b/kernel/io.cc @@ -251,7 +251,15 @@ bool check_is_directory(const std::string& dirname) { #if defined(_WIN32) struct _stat info; - if (_stat(dirname.c_str(), &info) != 0) + auto dirname_ = dirname; + + /* On old versions of Visual Studio and current versions on MinGW, + _stat will fail if the path ends with a trailing slash. */ + if (dirname.back() == '/' || dirname.back() == '\\') { + dirname_ = dirname.substr(0, dirname.length() - 1); + } + + if (_stat(dirname_.c_str(), &info) != 0) { return false; } From 388955031ffb52fa194eacc008e2bb0345be5d18 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 17 May 2025 00:23:43 +0000 Subject: [PATCH 36/74] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index b3d6d6f29..304753d98 100644 --- a/Makefile +++ b/Makefile @@ -160,7 +160,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.53+26 +YOSYS_VER := 0.53+39 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2) From 64a115e6f0869f3d31d2a6dc6a4eee606491dca8 Mon Sep 17 00:00:00 2001 From: RonxBulld <526677628@qq.com> Date: Sun, 18 May 2025 01:07:06 +0800 Subject: [PATCH 37/74] Disable STRIP operations when appropriate. --- Makefile | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 304753d98..8eb471e23 100644 --- a/Makefile +++ b/Makefile @@ -455,6 +455,7 @@ endif ifeq ($(ENABLE_DEBUG),1) CXXFLAGS := -Og -DDEBUG $(filter-out $(OPT_LEVEL),$(CXXFLAGS)) +STRIP := endif ifeq ($(ENABLE_ABC),1) @@ -983,20 +984,20 @@ install: $(TARGETS) $(EXTRA_TARGETS) $(INSTALL_SUDO) mkdir -p $(DESTDIR)$(BINDIR) $(INSTALL_SUDO) cp $(filter-out libyosys.so,$(TARGETS)) $(DESTDIR)$(BINDIR) ifneq ($(filter $(PROGRAM_PREFIX)yosys,$(TARGETS)),) - $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys + if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys; fi endif ifneq ($(filter $(PROGRAM_PREFIX)yosys-abc,$(TARGETS)),) - $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-abc + if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-abc; fi endif ifneq ($(filter $(PROGRAM_PREFIX)yosys-filterlib,$(TARGETS)),) - $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-filterlib + if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) $(DESTDIR)$(BINDIR)/$(PROGRAM_PREFIX)yosys-filterlib; fi endif $(INSTALL_SUDO) mkdir -p $(DESTDIR)$(DATDIR) $(INSTALL_SUDO) cp -r share/. $(DESTDIR)$(DATDIR)/. ifeq ($(ENABLE_LIBYOSYS),1) $(INSTALL_SUDO) mkdir -p $(DESTDIR)$(LIBDIR) $(INSTALL_SUDO) cp libyosys.so $(DESTDIR)$(LIBDIR)/ - $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(LIBDIR)/libyosys.so + if [ -n "$(STRIP)" ]; then $(INSTALL_SUDO) $(STRIP) -S $(DESTDIR)$(LIBDIR)/libyosys.so; fi ifeq ($(ENABLE_PYOSYS),1) $(INSTALL_SUDO) mkdir -p $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys $(INSTALL_SUDO) cp libyosys.so $(DESTDIR)$(PYTHON_DESTDIR)/$(subst -,_,$(PROGRAM_PREFIX))pyosys/libyosys.so From 761dc6f62aebbe80bb6eb10bc028418bb036e302 Mon Sep 17 00:00:00 2001 From: mikesinouye Date: Wed, 21 May 2025 15:18:29 -0700 Subject: [PATCH 38/74] Allow reading of gzipped files when not in NDEBUG --- kernel/gzip.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/gzip.cc b/kernel/gzip.cc index 6790b536e..24907d8cf 100644 --- a/kernel/gzip.cc +++ b/kernel/gzip.cc @@ -127,7 +127,8 @@ std::istream* uncompressed(const std::string filename, std::ios_base::openmode m filename.c_str(), unsigned(magic[2])); gzip_istream* s = new gzip_istream(); delete f; - log_assert(s->open(filename.c_str())); + bool ok = s->open(filename.c_str()); + log_assert(ok && "Failed to open gzipped file.\n"); return s; #else log_cmd_error("File `%s' is a gzip file, but Yosys is compiled without zlib.\n", filename.c_str()); From 98eec369210302a6d2aee856a00a571d019a1b00 Mon Sep 17 00:00:00 2001 From: George Rennie Date: Wed, 21 May 2025 12:20:08 +0100 Subject: [PATCH 39/74] kernel: add comments to as_int family of methods --- kernel/rtlil.h | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/kernel/rtlil.h b/kernel/rtlil.h index 50c96c71b..fb9efca51 100644 --- a/kernel/rtlil.h +++ b/kernel/rtlil.h @@ -753,10 +753,26 @@ public: std::vector& bits(); bool as_bool() const; + + // Convert the constant value to a C++ int. + // NOTE: If the constant is too wide to fit in int (32 bits) this will + // truncate any higher bits, potentially over/underflowing. Consider using + // try_as_int, as_int_saturating, or guarding behind convertible_to_int + // instead. int as_int(bool is_signed = false) const; + + // Returns true iff the constant can be converted to an int without + // over/underflow. bool convertible_to_int(bool is_signed = false) const; + + // Returns the constant's value as an int if it can be represented without + // over/underflow, or std::nullopt otherwise. std::optional try_as_int(bool is_signed = false) const; + + // Returns the constant's value as an int if it can be represented without + // over/underflow, otherwise the max/min value for int depending on the sign. int as_int_saturating(bool is_signed = false) const; + std::string as_string(const char* any = "-") const; static Const from_string(const std::string &str); std::vector to_bits() const; @@ -1133,10 +1149,27 @@ public: bool is_onehot(int *pos = nullptr) const; bool as_bool() const; + + // Convert the SigSpec to a C++ int, assuming all bits are constant. + // NOTE: If the value is too wide to fit in int (32 bits) this will + // truncate any higher bits, potentially over/underflowing. Consider using + // try_as_int, as_int_saturating, or guarding behind convertible_to_int + // instead. int as_int(bool is_signed = false) const; + + // Returns true iff the SigSpec is constant and can be converted to an int + // without over/underflow. bool convertible_to_int(bool is_signed = false) const; + + // Returns the SigSpec's value as an int if it is a constant and can be + // represented without over/underflow, or std::nullopt otherwise. std::optional try_as_int(bool is_signed = false) const; + + // Returns an all constant SigSpec's value as an int if it can be represented + // without over/underflow, otherwise the max/min value for int depending on + // the sign. int as_int_saturating(bool is_signed = false) const; + std::string as_string() const; RTLIL::Const as_const() const; RTLIL::Wire *as_wire() const; From 6c67b29bbb52cc7f0fbb86ebde87c46503efb5e2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Fri, 23 May 2025 00:24:38 +0000 Subject: [PATCH 40/74] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 304753d98..74857d3a8 100644 --- a/Makefile +++ b/Makefile @@ -160,7 +160,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.53+39 +YOSYS_VER := 0.53+49 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2) From 4f0cbf2ee6c38faed20a1896e5b93c2c3f45a460 Mon Sep 17 00:00:00 2001 From: Gary Wong Date: Thu, 22 May 2025 18:52:33 -0600 Subject: [PATCH 41/74] Fix typo ("exist" -> "exit"). --- passes/cmds/logger.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/cmds/logger.cc b/passes/cmds/logger.cc index 3277e1608..241a8799f 100644 --- a/passes/cmds/logger.cc +++ b/passes/cmds/logger.cc @@ -67,7 +67,7 @@ struct LoggerPass : public Pass { log(" -check-expected\n"); log(" verifies that the patterns previously set up by -expect have actually\n"); log(" been met, then clears the expected log list. If this is not called\n"); - log(" manually, the check will happen at yosys exist time instead.\n"); + log(" manually, the check will happen at yosys exit time instead.\n"); log("\n"); } From 9770ece187f11482eb8e86d66765881a781a5f01 Mon Sep 17 00:00:00 2001 From: Gary Wong Date: Thu, 22 May 2025 19:12:35 -0600 Subject: [PATCH 42/74] Accept (and ignore) SystemVerilog unique/priority if. Add support to the "read_verilog -sv" parser to validate the "unique", "unique0", and "priority" keywords in contexts where they're legal according to 1800-2012 12.4.2. This affects only the grammar accepted; the behaviour of conditionals is not changed. (But accepting this syntax will provide scope for possible optimisations as future work.) Three test cases ("unique_if", "unique_if_else", and "unique_if_else_begin") verify that the keywords are accepted where legal and rejected where illegal, as described in the final paragraph of 12.4.2. --- docs/source/yosys_internals/verilog.rst | 6 ++++++ frontends/verilog/verilog_parser.y | 28 +++++++++++++++++++++++-- kernel/constids.inc | 1 + tests/verilog/unique_if.ys | 10 +++++++++ tests/verilog/unique_if_else.ys | 11 ++++++++++ tests/verilog/unique_if_else_begin.ys | 12 +++++++++++ 6 files changed, 66 insertions(+), 2 deletions(-) create mode 100644 tests/verilog/unique_if.ys create mode 100644 tests/verilog/unique_if_else.ys create mode 100644 tests/verilog/unique_if_else_begin.ys diff --git a/docs/source/yosys_internals/verilog.rst b/docs/source/yosys_internals/verilog.rst index a1941963d..eef215e5d 100644 --- a/docs/source/yosys_internals/verilog.rst +++ b/docs/source/yosys_internals/verilog.rst @@ -375,3 +375,9 @@ from SystemVerilog: ports are inputs or outputs are supported. - Assignments within expressions are supported. + +- The ``unique``, ``unique0``, and ``priority`` SystemVerilog keywords are + accepted on ``if`` and ``case`` conditionals. (Those keywords are currently + handled in the same way as their equivalent ``full_case`` and + ``parallel_case`` attributes on ``case`` statements, and checked + for syntactic validity but otherwise ignored on ``if`` statements.) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 9d0956c8e..e70542a92 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -426,7 +426,7 @@ static const AstNode *addAsgnBinopStmt(dict *attr, AstNode * %type opt_property always_comb_or_latch always_or_always_ff %type opt_signedness_default_signed opt_signedness_default_unsigned %type integer_atom_type integer_vector_type -%type attr case_attr +%type attr if_attr case_attr %type struct_union %type asgn_binop inc_or_dec_op %type genvar_identifier @@ -2871,7 +2871,7 @@ behavioral_stmt: ast_stack.pop_back(); ast_stack.pop_back(); } | - attr TOK_IF '(' expr ')' { + if_attr TOK_IF '(' expr ')' { AstNode *node = new AstNode(AST_CASE); AstNode *block = new AstNode(AST_BLOCK); AstNode *cond = new AstNode(AST_COND, AstNode::mkconst_int(1, false, 1), block); @@ -2901,6 +2901,29 @@ behavioral_stmt: ast_stack.pop_back(); }; +if_attr: + attr { + $$ = $1; + } | + attr TOK_UNIQUE0 { + AstNode *context = ast_stack.back(); + if( context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if) ) + frontend_verilog_yyerror("unique0 keyword cannot be used for 'else if' branch."); + $$ = $1; // accept unique0 keyword, but ignore it for now + } | + attr TOK_PRIORITY { + AstNode *context = ast_stack.back(); + if( context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if) ) + frontend_verilog_yyerror("priority keyword cannot be used for 'else if' branch."); + $$ = $1; // accept priority keyword, but ignore it for now + } | + attr TOK_UNIQUE { + AstNode *context = ast_stack.back(); + if( context && context->type == AST_BLOCK && context->get_bool_attribute(ID::promoted_if) ) + frontend_verilog_yyerror("unique keyword cannot be used for 'else if' branch."); + $$ = $1; // accept unique keyword, but ignore it for now + }; + case_attr: attr { $$ = $1; @@ -2948,6 +2971,7 @@ behavioral_stmt_list: optional_else: TOK_ELSE { AstNode *block = new AstNode(AST_BLOCK); + block->attributes[ID::promoted_if] = AstNode::mkconst_int(1, false ); AstNode *cond = new AstNode(AST_COND, new AstNode(AST_DEFAULT), block); SET_AST_NODE_LOC(cond, @1, @1); diff --git a/kernel/constids.inc b/kernel/constids.inc index 4fdbb3dc8..c9b645d53 100644 --- a/kernel/constids.inc +++ b/kernel/constids.inc @@ -153,6 +153,7 @@ X(parameter) X(PORTID) X(PRIORITY) X(PRIORITY_MASK) +X(promoted_if) X(Q) X(R) X(ram_block) diff --git a/tests/verilog/unique_if.ys b/tests/verilog/unique_if.ys new file mode 100644 index 000000000..07140b195 --- /dev/null +++ b/tests/verilog/unique_if.ys @@ -0,0 +1,10 @@ +read_verilog -sv < Date: Sat, 24 May 2025 00:23:33 +0000 Subject: [PATCH 43/74] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 74857d3a8..6ea8e3949 100644 --- a/Makefile +++ b/Makefile @@ -160,7 +160,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.53+49 +YOSYS_VER := 0.53+60 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2) From 73e45d29d699d4894fcd0f4739744290a7a04373 Mon Sep 17 00:00:00 2001 From: Gary Wong Date: Sat, 24 May 2025 08:32:58 -0600 Subject: [PATCH 44/74] Add semantic test cases for SystemVerilog priority/unique/unique0 "if". The tests/verilog/*_if_enc.ys scripts instantiate simple encoder modules, both with and without the SystemVerilog priority/unique/unique0 keywords, and check for consistency between the two for the subset of inputs where the priority/unique/unique0 "if" result is well-defined. These tests vacuously succeed at the moment, since priority/unique keywords are silently ignored and therefore the generated logic is trivially identical. But the test cases will be capable of detecting certain types of unsound optimisation if priority/unique handling is introduced later. --- tests/verilog/priority_if_enc.ys | 41 ++++++++++++++++++++++++++++++++ tests/verilog/unique0_if_enc.ys | 41 ++++++++++++++++++++++++++++++++ tests/verilog/unique_if_enc.ys | 41 ++++++++++++++++++++++++++++++++ 3 files changed, 123 insertions(+) create mode 100644 tests/verilog/priority_if_enc.ys create mode 100644 tests/verilog/unique0_if_enc.ys create mode 100644 tests/verilog/unique_if_enc.ys diff --git a/tests/verilog/priority_if_enc.ys b/tests/verilog/priority_if_enc.ys new file mode 100644 index 000000000..7ca09cad7 --- /dev/null +++ b/tests/verilog/priority_if_enc.ys @@ -0,0 +1,41 @@ +logger -expect log "SAT proof finished - no model found: SUCCESS" 1 + +read_verilog -sv < 0. + assign ok = encout == dutout || !$countones( x ); +endmodule +EOF + +synth -flatten -top compare_encoders +sat -prove ok 1 diff --git a/tests/verilog/unique0_if_enc.ys b/tests/verilog/unique0_if_enc.ys new file mode 100644 index 000000000..e0384067d --- /dev/null +++ b/tests/verilog/unique0_if_enc.ys @@ -0,0 +1,41 @@ +logger -expect log "SAT proof finished - no model found: SUCCESS" 1 + +read_verilog -sv < Date: Mon, 26 May 2025 12:16:58 +1200 Subject: [PATCH 45/74] Tests: Add svtypes/typedef_struct_global.ys --- tests/svtypes/typedef_struct_global.ys | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 tests/svtypes/typedef_struct_global.ys diff --git a/tests/svtypes/typedef_struct_global.ys b/tests/svtypes/typedef_struct_global.ys new file mode 100644 index 000000000..0fed440e4 --- /dev/null +++ b/tests/svtypes/typedef_struct_global.ys @@ -0,0 +1,13 @@ +read_verilog -sv << EOF +typedef struct packed { + logic y; + logic x; +} Vec_2_B; + +module top; + + Vec_2_B two_dee; + wire foo = two_dee.x; + +endmodule +EOF From 32ce23458faaaae453f6ba5a1180b1931385179e Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Mon, 26 May 2025 12:19:33 +1200 Subject: [PATCH 46/74] read_verilog: Mark struct as custom type Being a custom type means that it will be resolved *before* (e.g.) a wire can use it as a type. --- frontends/ast/simplify.cc | 1 + frontends/verilog/verilog_parser.y | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 55087c772..749767743 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -1433,6 +1433,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin current_ast_mod->children.push_back(wnode); } basic_prep = true; + is_custom_type = false; } break; diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 9d0956c8e..68c3ec6ff 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -1855,7 +1855,7 @@ struct_decl: } ; -struct_type: struct_union { astbuf2 = $1; } struct_body { $$ = astbuf2; } +struct_type: struct_union { astbuf2 = $1; astbuf2->is_custom_type = true; } struct_body { $$ = astbuf2; } ; struct_union: From 33a22b5cd135b55b9e4d0f195832282be542e4b2 Mon Sep 17 00:00:00 2001 From: George Rennie Date: Mon, 26 May 2025 15:28:14 +0100 Subject: [PATCH 47/74] kernel: fix convertible_to_int for overflowing unsigned values --- kernel/rtlil.cc | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index c08e78dce..021aff73b 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -383,7 +383,23 @@ int RTLIL::Const::as_int(bool is_signed) const bool RTLIL::Const::convertible_to_int(bool is_signed) const { auto size = get_min_size(is_signed); - return (size > 0 && size <= 32); + + if (size <= 0) + return false; + + // If it fits in 31 bits it is definitely convertible + if (size <= 31) + return true; + + // If it fits in 32 bits, it is convertible if signed or if unsigned and the + // leading bit is not 1 + if (size == 32) { + if (is_signed) + return true; + return get_bits().at(31) != State::S1; + } + + return false; } std::optional RTLIL::Const::try_as_int(bool is_signed) const From 353fd0f7f424f5a7ae303b14285f108fc648468e Mon Sep 17 00:00:00 2001 From: George Rennie Date: Mon, 26 May 2025 15:28:44 +0100 Subject: [PATCH 48/74] tests: test opt_expr for 32 bit unsigned shifts --- tests/opt/opt_expr_shift.ys | 47 +++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/tests/opt/opt_expr_shift.ys b/tests/opt/opt_expr_shift.ys index 943d370dc..5a27562f6 100644 --- a/tests/opt/opt_expr_shift.ys +++ b/tests/opt/opt_expr_shift.ys @@ -111,3 +111,50 @@ select -assert-none t:$shr select -assert-none t:$sshl select -assert-none t:$sshr select -assert-none t:$shiftx + +design -reset + +read_verilog <> 32'hffffffff; + assign sshl = in <<< 32'hffffffff; + assign sshr = in >>> 32'hffffffff; + assign shiftx = in[32'hffffffff +: 8]; + + wire signed [31:0] shamt = 32'hffffffff; + assign shl_s = in << shamt; + assign shr_s = in >> shamt; + assign sshl_s = in <<< shamt; + assign sshr_s = in >>> shamt; + assign shiftx_s = in[shamt +: 8]; +endmodule +EOT + +select -assert-count 2 t:$shl +select -assert-count 2 t:$shr +select -assert-count 2 t:$sshl +select -assert-count 2 t:$sshr +select -assert-count 1 t:$shiftx + +equiv_opt opt_expr + +design -load postopt +select -assert-none t:$shl +select -assert-none t:$shr +select -assert-none t:$sshl +select -assert-none t:$sshr +select -assert-none t:$shiftx From e0c1e88f19a34aa91d53246e86810a8467de7ae4 Mon Sep 17 00:00:00 2001 From: George Rennie Date: Mon, 26 May 2025 15:34:13 +0100 Subject: [PATCH 49/74] kernel: use try_as_int to implement as_int_compress --- kernel/rtlil.cc | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 021aff73b..1cdc15bb5 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -455,18 +455,7 @@ void RTLIL::Const::compress(bool is_signed) std::optional RTLIL::Const::as_int_compress(bool is_signed) const { - auto size = get_min_size(is_signed); - if(size == 0 || size > 32) - return std::nullopt; - - int32_t ret = 0; - for (auto i = 0; i < size && i < 32; i++) - if ((*this)[i] == State::S1) - ret |= 1 << i; - if (is_signed && (*this)[size-1] == State::S1) - for (auto i = size; i < 32; i++) - ret |= 1 << i; - return ret; + return try_as_int(is_signed); } std::string RTLIL::Const::as_string(const char* any) const From 45a6940f402c400935646cd03afc5a9482930ab0 Mon Sep 17 00:00:00 2001 From: gatecat Date: Mon, 26 May 2025 11:11:51 +0200 Subject: [PATCH 50/74] cxxrtl: Add debug items for state with private names Signed-off-by: gatecat --- backends/cxxrtl/cxxrtl_backend.cc | 5 +++-- backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi.h | 4 ++++ backends/cxxrtl/runtime/cxxrtl/cxxrtl.h | 1 + 3 files changed, 8 insertions(+), 2 deletions(-) diff --git a/backends/cxxrtl/cxxrtl_backend.cc b/backends/cxxrtl/cxxrtl_backend.cc index 819b2c1df..7080f54d5 100644 --- a/backends/cxxrtl/cxxrtl_backend.cc +++ b/backends/cxxrtl/cxxrtl_backend.cc @@ -2429,8 +2429,6 @@ struct CxxrtlWorker { inc_indent(); for (auto wire : module->wires()) { const auto &debug_wire_type = debug_wire_types[wire]; - if (!wire->name.isPublic()) - continue; count_public_wires++; switch (debug_wire_type.type) { case WireType::BUFFERED: @@ -2438,6 +2436,9 @@ struct CxxrtlWorker { // Member wire std::vector flags; + if (!wire->name.isPublic()) + flags.push_back("GENERATED"); + if (wire->port_input && wire->port_output) flags.push_back("INOUT"); else if (wire->port_output) diff --git a/backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi.h b/backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi.h index ae42733ad..62ca38943 100644 --- a/backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi.h +++ b/backends/cxxrtl/runtime/cxxrtl/capi/cxxrtl_capi.h @@ -200,6 +200,10 @@ enum cxxrtl_flag { // node, such as inputs and dangling wires. CXXRTL_UNDRIVEN = 1 << 4, + // Generated correspond to netlist nodes that correspond to state with an internal name, that + // need to be saved, but wouldn't otherwise have a debug item generated. + CXXRTL_GENERATED = 1 << 5, + // More object flags may be added in the future, but the existing ones will never change. }; diff --git a/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h b/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h index 9b4f5774f..fbbe2373f 100644 --- a/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h +++ b/backends/cxxrtl/runtime/cxxrtl/cxxrtl.h @@ -1294,6 +1294,7 @@ struct debug_item : ::cxxrtl_object { DRIVEN_SYNC = CXXRTL_DRIVEN_SYNC, DRIVEN_COMB = CXXRTL_DRIVEN_COMB, UNDRIVEN = CXXRTL_UNDRIVEN, + GENERATED = CXXRTL_GENERATED, }; debug_item(const ::cxxrtl_object &object) : cxxrtl_object(object) {} From 4f968c669521786a58573672a6a9e49fe6a648f2 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 27 May 2025 00:24:03 +0000 Subject: [PATCH 51/74] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e6b60ed39..f82265da0 100644 --- a/Makefile +++ b/Makefile @@ -160,7 +160,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.53+60 +YOSYS_VER := 0.53+67 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2) From e4ab6acb4644cddafb1387e4069855db9727bfd1 Mon Sep 17 00:00:00 2001 From: Lofty Date: Tue, 27 May 2025 09:13:14 +0100 Subject: [PATCH 52/74] Add genlib support to abc_new --- passes/techmap/abc9_exe.cc | 25 +++++++++++++++++++++---- passes/techmap/abc_new.cc | 3 ++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/passes/techmap/abc9_exe.cc b/passes/techmap/abc9_exe.cc index 651a8375c..dcc507fca 100644 --- a/passes/techmap/abc9_exe.cc +++ b/passes/techmap/abc9_exe.cc @@ -168,7 +168,7 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe vector lut_costs, bool dff_mode, std::string delay_target, std::string /*lutin_shared*/, bool fast_mode, bool show_tempdir, std::string box_file, std::string lut_file, std::vector liberty_files, std::string wire_delay, std::string tempdir_name, - std::string constr_file, std::vector dont_use_cells) + std::string constr_file, std::vector dont_use_cells, std::vector genlib_files) { std::string abc9_script; @@ -186,6 +186,10 @@ void abc9_module(RTLIL::Design *design, std::string script_file, std::string exe } if (!constr_file.empty()) abc9_script += stringf("read_constr -v \"%s\"; ", constr_file.c_str()); + } else if (!genlib_files.empty()) { + for (std::string genlib_file : genlib_files) { + abc9_script += stringf("read_genlib \"%s\"; ", genlib_file.c_str()); + } } log_assert(!box_file.empty()); @@ -384,9 +388,14 @@ struct Abc9ExePass : public Pass { log(" read the given Liberty file as a description of the target cell library.\n"); log(" this option can be used multiple times.\n"); log("\n"); + log(" -genlib \n"); + log(" read the given genlib file as a description of the target cell library.\n"); + log(" this option can be used multiple times.\n"); + log("\n"); log(" -dont_use \n"); log(" avoid usage of the technology cell when mapping the design.\n"); - log(" this option can be used multiple times.\n"); + log(" this option can be used multiple times. only supported with Liberty\n"); + log(" cell libraries.\n"); log("\n"); log(" -D \n"); log(" set delay target. the string {D} in the default scripts above is\n"); @@ -441,7 +450,7 @@ struct Abc9ExePass : public Pass { std::string exe_file = yosys_abc_executable; std::string script_file, clk_str, box_file, lut_file, constr_file; - std::vector liberty_files, dont_use_cells; + std::vector liberty_files, genlib_files, dont_use_cells; std::string delay_target, lutin_shared = "-S 1", wire_delay; std::string tempdir_name; bool fast_mode = false, dff_mode = false; @@ -530,9 +539,15 @@ struct Abc9ExePass : public Pass { continue; } if (arg == "-liberty" && argidx+1 < args.size()) { + rewrite_filename(args[argidx+1]); liberty_files.push_back(args[++argidx]); continue; } + if (arg == "-genlib" && argidx+1 < args.size()) { + rewrite_filename(args[argidx+1]); + genlib_files.push_back(args[++argidx]); + continue; + } if (arg == "-dont_use" && argidx+1 < args.size()) { dont_use_cells.push_back(args[++argidx]); continue; @@ -601,11 +616,13 @@ struct Abc9ExePass : public Pass { if (tempdir_name.empty()) log_cmd_error("abc9_exe '-cwd' option is mandatory.\n"); + if (!genlib_files.empty() && !dont_use_cells.empty()) + log_cmd_error("abc9_exe '-genlib' is incompatible with '-dont_use'.\n"); abc9_module(design, script_file, exe_file, lut_costs, dff_mode, delay_target, lutin_shared, fast_mode, show_tempdir, box_file, lut_file, liberty_files, wire_delay, tempdir_name, - constr_file, dont_use_cells); + constr_file, dont_use_cells, genlib_files); } } Abc9ExePass; diff --git a/passes/techmap/abc_new.cc b/passes/techmap/abc_new.cc index dfa2e2f71..00bd23f86 100644 --- a/passes/techmap/abc_new.cc +++ b/passes/techmap/abc_new.cc @@ -68,6 +68,7 @@ struct AbcNewPass : public ScriptPass { log(" -constr \n"); log(" -dont_use \n"); log(" -liberty \n"); + log(" -genlib \n"); log(" these options are passed on to the 'abc9_exe' command which invokes\n"); log(" the ABC tool on individual modules of the design. please see\n"); log(" 'help abc9_exe' for more details\n"); @@ -90,7 +91,7 @@ struct AbcNewPass : public ScriptPass { if (args[argidx] == "-exe" || args[argidx] == "-script" || args[argidx] == "-D" || args[argidx] == "-constr" || args[argidx] == "-dont_use" || - args[argidx] == "-liberty") { + args[argidx] == "-liberty" || args[argidx] == "-genlib") { abc_exe_options += " " + args[argidx] + " " + args[argidx + 1]; argidx++; } else if (args[argidx] == "-run" && argidx + 1 < args.size()) { From e046e3cdbf0ab2eb0e5e377eb04867bcb9b26c43 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 28 May 2025 00:24:34 +0000 Subject: [PATCH 53/74] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index f82265da0..ebf886d52 100644 --- a/Makefile +++ b/Makefile @@ -160,7 +160,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.53+67 +YOSYS_VER := 0.53+70 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2) From 0072a267cc5380963917fa2971b8198cbc54b635 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Thu, 29 May 2025 16:20:16 +1200 Subject: [PATCH 54/74] write_aiger: Add no-sort option Prevents sorting input/output bits so that they remain in the same order they were read in. --- backends/aiger/aiger.cc | 70 ++++++++++++++++++++++++++--------------- 1 file changed, 45 insertions(+), 25 deletions(-) diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index 617d7d85f..3da98d79d 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -132,7 +132,7 @@ struct AigerWriter return a; } - AigerWriter(Module *module, bool zinit_mode, bool imode, bool omode, bool bmode, bool lmode) : module(module), zinit_mode(zinit_mode), sigmap(module) + AigerWriter(Module *module, bool no_sort, bool zinit_mode, bool imode, bool omode, bool bmode, bool lmode) : module(module), zinit_mode(zinit_mode), sigmap(module) { pool undriven_bits; pool unused_bits; @@ -152,6 +152,34 @@ struct AigerWriter if (wire->port_input) sigmap.add(wire); + // handle ports + for (auto riter = module->ports.rbegin(); riter != module->ports.rend(); ++riter) { + auto *wire = module->wire(*riter); + for (int i = 0; i < GetSize(wire); i++) + { + SigBit wirebit(wire, i); + SigBit bit = sigmap(wirebit); + + if (bit.wire == nullptr) { + if (wire->port_output) { + aig_map[wirebit] = (bit == State::S1) ? 1 : 0; + output_bits.insert(wirebit); + } + continue; + } + + if (wire->port_input) + input_bits.insert(bit); + + if (wire->port_output) { + if (bit != wirebit) + alias_map[wirebit] = bit; + output_bits.insert(wirebit); + } + } + } + + // handle wires for (auto wire : module->wires()) { if (wire->attributes.count(ID::init)) { @@ -167,25 +195,13 @@ struct AigerWriter SigBit wirebit(wire, i); SigBit bit = sigmap(wirebit); - if (bit.wire == nullptr) { - if (wire->port_output) { - aig_map[wirebit] = (bit == State::S1) ? 1 : 0; - output_bits.insert(wirebit); - } + if (bit.wire == nullptr) + continue; + if (wire->port_input || wire->port_output) continue; - } undriven_bits.insert(bit); unused_bits.insert(bit); - - if (wire->port_input) - input_bits.insert(bit); - - if (wire->port_output) { - if (bit != wirebit) - alias_map[wirebit] = bit; - output_bits.insert(wirebit); - } } if (wire->width == 1) { @@ -200,12 +216,6 @@ struct AigerWriter } } - for (auto bit : input_bits) - undriven_bits.erase(bit); - - for (auto bit : output_bits) - unused_bits.erase(bit); - for (auto cell : module->cells()) { if (cell->type == ID($_NOT_)) @@ -343,8 +353,10 @@ struct AigerWriter } init_map.sort(); - input_bits.sort(); - output_bits.sort(); + if (!no_sort) { + input_bits.sort(); + output_bits.sort(); + } not_map.sort(); ff_map.sort(); and_map.sort(); @@ -901,6 +913,9 @@ struct AigerBackend : public Backend { log(" -symbols\n"); log(" include a symbol table in the generated AIGER file\n"); log("\n"); + log(" -no-sort\n"); + log(" don't sort input/output ports\n"); + log("\n"); log(" -map \n"); log(" write an extra file with port and latch symbols\n"); log("\n"); @@ -925,6 +940,7 @@ struct AigerBackend : public Backend { bool zinit_mode = false; bool miter_mode = false; bool symbols_mode = false; + bool no_sort = false; bool verbose_map = false; bool imode = false; bool omode = false; @@ -955,6 +971,10 @@ struct AigerBackend : public Backend { symbols_mode = true; continue; } + if (args[argidx] == "-no-sort") { + no_sort = true; + continue; + } if (map_filename.empty() && args[argidx] == "-map" && argidx+1 < args.size()) { map_filename = args[++argidx]; continue; @@ -1008,7 +1028,7 @@ struct AigerBackend : public Backend { if (!top_module->memories.empty()) log_error("Found unmapped memories in module %s: unmapped memories are not supported in AIGER backend!\n", log_id(top_module)); - AigerWriter writer(top_module, zinit_mode, imode, omode, bmode, lmode); + AigerWriter writer(top_module, no_sort, zinit_mode, imode, omode, bmode, lmode); writer.write_aiger(*f, ascii_mode, miter_mode, symbols_mode); if (!map_filename.empty()) { From 7a9d727bd0319619b3d1a37bd5998977ef0c3ac9 Mon Sep 17 00:00:00 2001 From: Gary Wong Date: Thu, 29 May 2025 21:26:28 -0600 Subject: [PATCH 55/74] docs: several small documentation fixes. --- docs/source/appendix/primer.rst | 8 ++++---- .../more_scripting/interactive_investigation.rst | 2 +- docs/source/using_yosys/synthesis/abc.rst | 2 +- docs/source/yosys_internals/flow/verilog_frontend.rst | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/docs/source/appendix/primer.rst b/docs/source/appendix/primer.rst index 50656af78..f54f99e52 100644 --- a/docs/source/appendix/primer.rst +++ b/docs/source/appendix/primer.rst @@ -72,7 +72,7 @@ circuits. Tools exist to synthesize high level code (usually in the form of C/C++/SystemC code with additional metadata) to behavioural HDL code (usually in the form of Verilog or VHDL code). Aside from the many commercial tools for high level -synthesis there are also a number of FOSS tools for high level synthesis . +synthesis there are also a number of FOSS tools for high level synthesis. Behavioural level ~~~~~~~~~~~~~~~~~ @@ -185,7 +185,7 @@ advantage that it has a unique normalized form. The latter has much better worst case performance and is therefore better suited for the synthesis of large logic functions. -Good FOSS tools exists for multi-level logic synthesis . +Good FOSS tools exists for multi-level logic synthesis. Yosys contains basic logic synthesis functionality but can also use ABC for the logic synthesis step. Using ABC is recommended. @@ -221,7 +221,7 @@ design description as input and generates an RTL, logical gate or physical gate level description of the design as output. Yosys' main strengths are behavioural and RTL synthesis. A wide range of commands (synthesis passes) exist within Yosys that can be used to perform a wide range of synthesis tasks within the -domain of behavioural, rtl and logic synthesis. Yosys is designed to be +domain of behavioural, RTL and logic synthesis. Yosys is designed to be extensible and therefore is a good basis for implementing custom synthesis tools for specialised tasks. @@ -572,7 +572,7 @@ of lexical tokens given in :numref:`Tab. %s `. TOK_SEMICOLON \- ============== =============== -The lexer is usually generated by a lexer generator (e.g. flex ) from a +The lexer is usually generated by a lexer generator (e.g. flex) from a description file that is using regular expressions to specify the text pattern that should match the individual tokens. diff --git a/docs/source/using_yosys/more_scripting/interactive_investigation.rst b/docs/source/using_yosys/more_scripting/interactive_investigation.rst index c6180306d..e9c9bc9ac 100644 --- a/docs/source/using_yosys/more_scripting/interactive_investigation.rst +++ b/docs/source/using_yosys/more_scripting/interactive_investigation.rst @@ -73,7 +73,7 @@ contain bits that are not 0 or 1 (i.e. ``x`` or ``z``). Ordinary 32-bit constants are written using decimal numbers. Single-bit signals are shown as thin arrows pointing from the driver to the -load. Signals that are multiple bits wide are shown as think arrows. +load. Signals that are multiple bits wide are shown as thick arrows. Finally *processes* are shown in boxes with round corners. Processes are Yosys' internal representation of the decision-trees and synchronization events diff --git a/docs/source/using_yosys/synthesis/abc.rst b/docs/source/using_yosys/synthesis/abc.rst index 91de775e6..0b24af3a1 100644 --- a/docs/source/using_yosys/synthesis/abc.rst +++ b/docs/source/using_yosys/synthesis/abc.rst @@ -176,5 +176,5 @@ implemented as whiteboxes too. Boxes are arguably the biggest advantage that ABC9 has over ABC: by being aware of carry chains and DSPs, it avoids optimising for a path that isn't the actual critical path, while the generally-longer paths result in ABC9 being able to -reduce design area by mapping other logic to larger-but-slower cells. +reduce design area by mapping other logic to smaller-but-slower cells. diff --git a/docs/source/yosys_internals/flow/verilog_frontend.rst b/docs/source/yosys_internals/flow/verilog_frontend.rst index e53466687..b6a7ba8a0 100644 --- a/docs/source/yosys_internals/flow/verilog_frontend.rst +++ b/docs/source/yosys_internals/flow/verilog_frontend.rst @@ -626,7 +626,7 @@ pass and the passes it launches: | This pass replaces the ``RTLIL::SyncRule``\ s to d-type flip-flops (with asynchronous resets if necessary). -- | `proc_dff` +- | `proc_memwr` | This pass replaces the ``RTLIL::MemWriteAction``\ s with `$memwr` cells. - | `proc_clean` From 70291f0e4954a81dfae5a236ecafda9abc43e5f7 Mon Sep 17 00:00:00 2001 From: George Rennie Date: Fri, 30 May 2025 14:25:35 +0100 Subject: [PATCH 56/74] read_verilog: fix -1 constant used to correct post increment/decrement --- frontends/verilog/verilog_parser.y | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 9d0956c8e..fa624d471 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -336,7 +336,8 @@ static AstNode *addIncOrDecExpr(AstNode *lhs, dict *attr, AS log_assert(stmt->type == AST_ASSIGN_EQ); AstNode *expr = stmt->children[0]->clone(); if (undo) { - AstNode *minus_one = AstNode::mkconst_int(-1, true, 1); + AstNode *one = AstNode::mkconst_int(1, false, 1); + AstNode *minus_one = new AstNode(AST_NEG, one); expr = new AstNode(op, expr, minus_one); } SET_AST_NODE_LOC(expr, begin, end); From 3790be114f770b336b9aa815236504f8173870bd Mon Sep 17 00:00:00 2001 From: George Rennie Date: Fri, 30 May 2025 14:36:05 +0100 Subject: [PATCH 57/74] tests: add tests for verilog pre/post increment/decrement in expressions --- tests/verilog/incdec.ys | 68 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 tests/verilog/incdec.ys diff --git a/tests/verilog/incdec.ys b/tests/verilog/incdec.ys new file mode 100644 index 000000000..9133061a5 --- /dev/null +++ b/tests/verilog/incdec.ys @@ -0,0 +1,68 @@ +# From https://github.com/YosysHQ/yosys/issues/5151 +read_verilog -sv < Date: Fri, 30 May 2025 22:05:54 +0100 Subject: [PATCH 58/74] CODEOWNERS: add myself for the ABC doc --- CODEOWNERS | 1 + 1 file changed, 1 insertion(+) diff --git a/CODEOWNERS b/CODEOWNERS index 879bb8dee..ef8c803ed 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -20,6 +20,7 @@ passes/opt/opt_lut.cc @whitequark passes/techmap/abc9*.cc @eddiehung @Ravenslofty backends/aiger/xaiger.cc @eddiehung docs/ @KrystalDelusion +docs/source/using_yosys/synthesis/abc.rst @KrystalDelusion @Ravenslofty .github/workflows/*.yml @mmicko ## External Contributors From 06db8828b2aa4c06f9bd5dae069a016026abadc0 Mon Sep 17 00:00:00 2001 From: KrystalDelusion <93062060+KrystalDelusion@users.noreply.github.com> Date: Sat, 31 May 2025 09:10:27 +1200 Subject: [PATCH 59/74] abc.rst: Clarify larger-but-slower --- docs/source/using_yosys/synthesis/abc.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/source/using_yosys/synthesis/abc.rst b/docs/source/using_yosys/synthesis/abc.rst index 0b24af3a1..ba12cabc1 100644 --- a/docs/source/using_yosys/synthesis/abc.rst +++ b/docs/source/using_yosys/synthesis/abc.rst @@ -176,5 +176,6 @@ implemented as whiteboxes too. Boxes are arguably the biggest advantage that ABC9 has over ABC: by being aware of carry chains and DSPs, it avoids optimising for a path that isn't the actual critical path, while the generally-longer paths result in ABC9 being able to -reduce design area by mapping other logic to smaller-but-slower cells. +reduce design area by mapping other logic to slower cells with greater logic +density. From aac562d36af6c8bf16072c2cc8ed0a2f778a3413 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Sat, 31 May 2025 09:55:00 +1200 Subject: [PATCH 60/74] aiger.cc: Explicit unsorted-pool-as-LIFO --- backends/aiger/aiger.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/backends/aiger/aiger.cc b/backends/aiger/aiger.cc index 3da98d79d..5b07a7195 100644 --- a/backends/aiger/aiger.cc +++ b/backends/aiger/aiger.cc @@ -153,6 +153,9 @@ struct AigerWriter sigmap.add(wire); // handle ports + // provided the input_bits and output_bits don't get sorted they + // will be returned in reverse order, so add them in reverse to + // match for (auto riter = module->ports.rbegin(); riter != module->ports.rend(); ++riter) { auto *wire = module->wire(*riter); for (int i = 0; i < GetSize(wire); i++) @@ -353,6 +356,7 @@ struct AigerWriter } init_map.sort(); + // we are relying here on unsorted pools iterating last-in-first-out if (!no_sort) { input_bits.sort(); output_bits.sort(); From ab0e3cc05f9e25759450f9fd60d0f0056a4a75e1 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Sat, 31 May 2025 12:04:42 +1200 Subject: [PATCH 61/74] Proc: Use selections consistently All `proc_*` passes now use the same module and process for loops, using `design->all_selected_modules()` and `mod->selected_processes()` respectively. This simplifies the code, and makes the couple `proc_*` passes that were ignoring boxed modules stop doing that (which seems to have been erroneous rather than intentional). --- passes/proc/proc_arst.cc | 63 ++++++++++++++++++-------------------- passes/proc/proc_clean.cc | 18 +++++------ passes/proc/proc_dff.cc | 12 +++----- passes/proc/proc_dlatch.cc | 9 +++--- passes/proc/proc_init.cc | 12 +++----- passes/proc/proc_memwr.cc | 9 +++--- passes/proc/proc_mux.cc | 8 ++--- passes/proc/proc_prune.cc | 11 ++----- passes/proc/proc_rmdead.cc | 14 +++------ passes/proc/proc_rom.cc | 11 ++----- 10 files changed, 69 insertions(+), 98 deletions(-) diff --git a/passes/proc/proc_arst.cc b/passes/proc/proc_arst.cc index f01682957..3cd3f6fe4 100644 --- a/passes/proc/proc_arst.cc +++ b/passes/proc/proc_arst.cc @@ -288,43 +288,40 @@ struct ProcArstPass : public Pass { extra_args(args, argidx, design); pool delete_initattr_wires; - for (auto mod : design->modules()) - if (design->selected(mod)) { - SigMap assign_map(mod); - for (auto &proc_it : mod->processes) { - if (!design->selected(mod, proc_it.second)) - continue; - proc_arst(mod, proc_it.second, assign_map); - if (global_arst.empty() || mod->wire(global_arst) == nullptr) - continue; - std::vector arst_actions; - for (auto sync : proc_it.second->syncs) - if (sync->type == RTLIL::SyncType::STp || sync->type == RTLIL::SyncType::STn) - for (auto &act : sync->actions) { - RTLIL::SigSpec arst_sig, arst_val; - for (auto &chunk : act.first.chunks()) - if (chunk.wire && chunk.wire->attributes.count(ID::init)) { - RTLIL::SigSpec value = chunk.wire->attributes.at(ID::init); - value.extend_u0(chunk.wire->width, false); - arst_sig.append(chunk); - arst_val.append(value.extract(chunk.offset, chunk.width)); - delete_initattr_wires.insert(chunk.wire); - } - if (arst_sig.size()) { - log("Added global reset to process %s: %s <- %s\n", - proc_it.first.c_str(), log_signal(arst_sig), log_signal(arst_val)); - arst_actions.push_back(RTLIL::SigSig(arst_sig, arst_val)); + for (auto mod : design->all_selected_modules()) { + SigMap assign_map(mod); + for (auto proc : mod->selected_processes()) { + proc_arst(mod, proc, assign_map); + if (global_arst.empty() || mod->wire(global_arst) == nullptr) + continue; + std::vector arst_actions; + for (auto sync : proc->syncs) + if (sync->type == RTLIL::SyncType::STp || sync->type == RTLIL::SyncType::STn) + for (auto &act : sync->actions) { + RTLIL::SigSpec arst_sig, arst_val; + for (auto &chunk : act.first.chunks()) + if (chunk.wire && chunk.wire->attributes.count(ID::init)) { + RTLIL::SigSpec value = chunk.wire->attributes.at(ID::init); + value.extend_u0(chunk.wire->width, false); + arst_sig.append(chunk); + arst_val.append(value.extract(chunk.offset, chunk.width)); + delete_initattr_wires.insert(chunk.wire); } + if (arst_sig.size()) { + log("Added global reset to process %s: %s <- %s\n", + proc->name.c_str(), log_signal(arst_sig), log_signal(arst_val)); + arst_actions.push_back(RTLIL::SigSig(arst_sig, arst_val)); } - if (!arst_actions.empty()) { - RTLIL::SyncRule *sync = new RTLIL::SyncRule; - sync->type = global_arst_neg ? RTLIL::SyncType::ST0 : RTLIL::SyncType::ST1; - sync->signal = mod->wire(global_arst); - sync->actions = arst_actions; - proc_it.second->syncs.push_back(sync); - } + } + if (!arst_actions.empty()) { + RTLIL::SyncRule *sync = new RTLIL::SyncRule; + sync->type = global_arst_neg ? RTLIL::SyncType::ST0 : RTLIL::SyncType::ST1; + sync->signal = mod->wire(global_arst); + sync->actions = arst_actions; + proc->syncs.push_back(sync); } } + } for (auto wire : delete_initattr_wires) wire->attributes.erase(ID::init); diff --git a/passes/proc/proc_clean.cc b/passes/proc/proc_clean.cc index 95cb0e88c..b8bd74f50 100644 --- a/passes/proc/proc_clean.cc +++ b/passes/proc/proc_clean.cc @@ -208,19 +208,15 @@ struct ProcCleanPass : public Pass { } extra_args(args, argidx, design); - for (auto mod : design->modules()) { + for (auto mod : design->all_selected_modules()) { std::vector delme; - if (!design->selected(mod)) - continue; - for (auto &proc_it : mod->processes) { - if (!design->selected(mod, proc_it.second)) - continue; - proc_clean(mod, proc_it.second, total_count, quiet); - if (proc_it.second->syncs.size() == 0 && proc_it.second->root_case.switches.size() == 0 && - proc_it.second->root_case.actions.size() == 0) { + for (auto proc : mod->selected_processes()) { + proc_clean(mod, proc, total_count, quiet); + if (proc->syncs.size() == 0 && proc->root_case.switches.size() == 0 && + proc->root_case.actions.size() == 0) { if (!quiet) - log("Removing empty process `%s.%s'.\n", log_id(mod), proc_it.second->name.c_str()); - delme.push_back(proc_it.second); + log("Removing empty process `%s.%s'.\n", log_id(mod), proc->name.c_str()); + delme.push_back(proc); } } for (auto proc : delme) { diff --git a/passes/proc/proc_dff.cc b/passes/proc/proc_dff.cc index d094abf1b..7e3c56552 100644 --- a/passes/proc/proc_dff.cc +++ b/passes/proc/proc_dff.cc @@ -306,13 +306,11 @@ struct ProcDffPass : public Pass { extra_args(args, 1, design); - for (auto mod : design->modules()) - if (design->selected(mod)) { - ConstEval ce(mod); - for (auto &proc_it : mod->processes) - if (design->selected(mod, proc_it.second)) - proc_dff(mod, proc_it.second, ce); - } + for (auto mod : design->all_selected_modules()) { + ConstEval ce(mod); + for (auto proc : mod->selected_processes()) + proc_dff(mod, proc, ce); + } } } ProcDffPass; diff --git a/passes/proc/proc_dlatch.cc b/passes/proc/proc_dlatch.cc index e038a202c..f170dbf36 100644 --- a/passes/proc/proc_dlatch.cc +++ b/passes/proc/proc_dlatch.cc @@ -463,11 +463,10 @@ struct ProcDlatchPass : public Pass { extra_args(args, 1, design); - for (auto module : design->selected_modules()) { - proc_dlatch_db_t db(module); - for (auto &proc_it : module->processes) - if (design->selected(module, proc_it.second)) - proc_dlatch(db, proc_it.second); + for (auto mod : design->all_selected_modules()) { + proc_dlatch_db_t db(mod); + for (auto proc : mod->selected_processes()) + proc_dlatch(db, proc); db.fixup_muxes(); } } diff --git a/passes/proc/proc_init.cc b/passes/proc/proc_init.cc index 86e704852..817ced404 100644 --- a/passes/proc/proc_init.cc +++ b/passes/proc/proc_init.cc @@ -91,13 +91,11 @@ struct ProcInitPass : public Pass { extra_args(args, 1, design); - for (auto mod : design->modules()) - if (design->selected(mod)) { - SigMap sigmap(mod); - for (auto &proc_it : mod->processes) - if (design->selected(mod, proc_it.second)) - proc_init(mod, sigmap, proc_it.second); - } + for (auto mod : design->all_selected_modules()) { + SigMap sigmap(mod); + for (auto proc : mod->selected_processes()) + proc_init(mod, sigmap, proc); + } } } ProcInitPass; diff --git a/passes/proc/proc_memwr.cc b/passes/proc/proc_memwr.cc index 58bf9fdd3..88aea39bb 100644 --- a/passes/proc/proc_memwr.cc +++ b/passes/proc/proc_memwr.cc @@ -99,9 +99,9 @@ struct ProcMemWrPass : public Pass { extra_args(args, 1, design); - for (auto module : design->selected_modules()) { + for (auto mod : design->all_selected_modules()) { dict next_port_id; - for (auto cell : module->cells()) { + for (auto cell : mod->cells()) { if (cell->type.in(ID($memwr), ID($memwr_v2))) { bool is_compat = cell->type == ID($memwr); IdString memid = cell->parameters.at(ID::MEMID).decode_string(); @@ -110,9 +110,8 @@ struct ProcMemWrPass : public Pass { next_port_id[memid] = port_id + 1; } } - for (auto &proc_it : module->processes) - if (design->selected(module, proc_it.second)) - proc_memwr(module, proc_it.second, next_port_id); + for (auto proc : mod->selected_processes()) + proc_memwr(mod, proc, next_port_id); } } } ProcMemWrPass; diff --git a/passes/proc/proc_mux.cc b/passes/proc/proc_mux.cc index 2f539c960..61e7f4960 100644 --- a/passes/proc/proc_mux.cc +++ b/passes/proc/proc_mux.cc @@ -468,11 +468,9 @@ struct ProcMuxPass : public Pass { } extra_args(args, argidx, design); - for (auto mod : design->modules()) - if (design->selected(mod)) - for (auto &proc_it : mod->processes) - if (design->selected(mod, proc_it.second)) - proc_mux(mod, proc_it.second, ifxmode); + for (auto mod : design->all_selected_modules()) + for (auto proc : mod->selected_processes()) + proc_mux(mod, proc, ifxmode); } } ProcMuxPass; diff --git a/passes/proc/proc_prune.cc b/passes/proc/proc_prune.cc index 3433557ee..08903d93f 100644 --- a/passes/proc/proc_prune.cc +++ b/passes/proc/proc_prune.cc @@ -127,15 +127,10 @@ struct ProcPrunePass : public Pass { extra_args(args, 1, design); - for (auto mod : design->modules()) { - if (!design->selected(mod)) - continue; + for (auto mod : design->all_selected_modules()) { PruneWorker worker(mod); - for (auto &proc_it : mod->processes) { - if (!design->selected(mod, proc_it.second)) - continue; - worker.do_process(proc_it.second); - } + for (auto proc : mod->selected_processes()) + worker.do_process(proc); total_removed_count += worker.removed_count; total_promoted_count += worker.promoted_count; } diff --git a/passes/proc/proc_rmdead.cc b/passes/proc/proc_rmdead.cc index 2ec11415a..8f5eda085 100644 --- a/passes/proc/proc_rmdead.cc +++ b/passes/proc/proc_rmdead.cc @@ -147,21 +147,17 @@ struct ProcRmdeadPass : public Pass { extra_args(args, 1, design); int total_counter = 0; - for (auto mod : design->modules()) { - if (!design->selected(mod)) - continue; - for (auto &proc_it : mod->processes) { - if (!design->selected(mod, proc_it.second)) - continue; + for (auto mod : design->all_selected_modules()) { + for (auto proc : mod->selected_processes()) { int counter = 0, full_case_counter = 0; - for (auto switch_it : proc_it.second->root_case.switches) + for (auto switch_it : proc->root_case.switches) proc_rmdead(switch_it, counter, full_case_counter); if (counter > 0) log("Removed %d dead cases from process %s in module %s.\n", counter, - log_id(proc_it.first), log_id(mod)); + log_id(proc), log_id(mod)); if (full_case_counter > 0) log("Marked %d switch rules as full_case in process %s in module %s.\n", - full_case_counter, log_id(proc_it.first), log_id(mod)); + full_case_counter, log_id(proc), log_id(mod)); total_counter += counter; } } diff --git a/passes/proc/proc_rom.cc b/passes/proc/proc_rom.cc index 5f8e47ceb..d3b781e60 100644 --- a/passes/proc/proc_rom.cc +++ b/passes/proc/proc_rom.cc @@ -243,15 +243,10 @@ struct ProcRomPass : public Pass { extra_args(args, 1, design); - for (auto mod : design->modules()) { - if (!design->selected(mod)) - continue; + for (auto mod : design->all_selected_modules()) { RomWorker worker(mod); - for (auto &proc_it : mod->processes) { - if (!design->selected(mod, proc_it.second)) - continue; - worker.do_process(proc_it.second); - } + for (auto proc : mod->selected_processes()) + worker.do_process(proc); total_count += worker.count; } From 45e8ff476edacc4f3a2bd18a90ae0dbf09b9c182 Mon Sep 17 00:00:00 2001 From: George Rennie Date: Sat, 31 May 2025 01:08:15 +0100 Subject: [PATCH 62/74] read_verilog: copy inout ports in and out of functions/tasks --- frontends/ast/simplify.cc | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 55087c772..1f9944e2e 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -4099,16 +4099,24 @@ skip_dynamic_range_lvalue_expansion:; delete arg; continue; } + AstNode *wire_id = new AstNode(AST_IDENTIFIER); wire_id->str = wire->str; - AstNode *assign = child->is_input ? - new AstNode(AST_ASSIGN_EQ, wire_id, arg) : - new AstNode(AST_ASSIGN_EQ, arg, wire_id); - assign->children[0]->was_checked = true; - if (child->is_input) + + if (child->is_input) { + AstNode *assign = new AstNode(AST_ASSIGN_EQ, wire_id->clone(), arg->clone()); + assign->children[0]->was_checked = true; new_stmts.push_back(assign); - else + } + + if (child->is_output) { + AstNode *assign = new AstNode(AST_ASSIGN_EQ, arg->clone(), wire_id->clone()); + assign->children[0]->was_checked = true; output_assignments.push_back(assign); + } + + delete arg; + delete wire_id; } } From 785cabcb0f77ae35258ee0bd6c48ccbdd72474c7 Mon Sep 17 00:00:00 2001 From: Krystine Sherwin <93062060+KrystalDelusion@users.noreply.github.com> Date: Sat, 31 May 2025 12:16:37 +1200 Subject: [PATCH 63/74] abc9_ops: Skip opt_expr in proc --- passes/techmap/abc9_ops.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/passes/techmap/abc9_ops.cc b/passes/techmap/abc9_ops.cc index 6cb569b5a..ee0a903c2 100644 --- a/passes/techmap/abc9_ops.cc +++ b/passes/techmap/abc9_ops.cc @@ -123,7 +123,7 @@ void check(RTLIL::Design *design, bool dff_mode) log_error("Module '%s' with (* abc9_flop *) is a blackbox.\n", log_id(derived_type)); if (derived_module->has_processes()) - Pass::call_on_module(design, derived_module, "proc"); + Pass::call_on_module(design, derived_module, "proc -noopt"); bool found = false; for (auto derived_cell : derived_module->cells()) { @@ -204,7 +204,7 @@ void prep_hier(RTLIL::Design *design, bool dff_mode) if (!unmap_design->module(derived_type)) { if (derived_module->has_processes()) - Pass::call_on_module(design, derived_module, "proc"); + Pass::call_on_module(design, derived_module, "proc -noopt"); if (derived_module->get_bool_attribute(ID::abc9_flop)) { for (auto derived_cell : derived_module->cells()) @@ -834,7 +834,7 @@ void prep_xaiger(RTLIL::Module *module, bool dff) holes_cell = holes_module->addCell(NEW_ID, cell->type); if (box_module->has_processes()) - Pass::call_on_module(design, box_module, "proc"); + Pass::call_on_module(design, box_module, "proc -noopt"); int box_inputs = 0; for (auto port_name : box_ports.at(cell->type)) { From 97f51bb4b73ad32036c0d4273487221afabcacb6 Mon Sep 17 00:00:00 2001 From: George Rennie Date: Sat, 31 May 2025 01:21:06 +0100 Subject: [PATCH 64/74] tests: add tests for task/function argument input/output copying --- tests/verilog/func_task_arg_copying.ys | 132 +++++++++++++++++++++++++ 1 file changed, 132 insertions(+) create mode 100644 tests/verilog/func_task_arg_copying.ys diff --git a/tests/verilog/func_task_arg_copying.ys b/tests/verilog/func_task_arg_copying.ys new file mode 100644 index 000000000..e87c2781b --- /dev/null +++ b/tests/verilog/func_task_arg_copying.ys @@ -0,0 +1,132 @@ +# https://github.com/YosysHQ/yosys/issues/5157 +read_verilog -sv < Date: Sat, 31 May 2025 00:23:36 +0000 Subject: [PATCH 65/74] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ebf886d52..cff6796c3 100644 --- a/Makefile +++ b/Makefile @@ -160,7 +160,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.53+70 +YOSYS_VER := 0.53+81 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2) From c37b7b3bf4d347f67636cc8978e38fbc49e09173 Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Wed, 4 Jun 2025 10:32:03 +0200 Subject: [PATCH 66/74] simplify: fix single_bit_vector memory leak --- frontends/ast/simplify.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontends/ast/simplify.cc b/frontends/ast/simplify.cc index 749767743..ef5e49519 100644 --- a/frontends/ast/simplify.cc +++ b/frontends/ast/simplify.cc @@ -2087,7 +2087,7 @@ bool AstNode::simplify(bool const_fold, int stage, int width_hint, bool sign_hin std::swap(range_left, range_right); range_swapped = force_upto; } - if (range_left == range_right) + if (range_left == range_right && !attributes.count(ID::single_bit_vector)) set_attribute(ID::single_bit_vector, mkconst_int(1, false)); } } else { From 50b63c64818c604ad6a9b98071687acfbdfd0698 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 5 Jun 2025 00:24:30 +0000 Subject: [PATCH 67/74] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cff6796c3..66d051be4 100644 --- a/Makefile +++ b/Makefile @@ -160,7 +160,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.53+81 +YOSYS_VER := 0.53+98 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2) From a16227b2091d3a7a0c5207ad06842a496607587b Mon Sep 17 00:00:00 2001 From: "Emil J. Tywoniak" Date: Fri, 6 Jun 2025 15:14:40 +0200 Subject: [PATCH 68/74] Revert "Change the implementation of log_debug in kernel/log.h from a macro function to a normal function." This reverts commit 15cfce061a118111984e013a46fd0bbdc064a9ed. --- kernel/log.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/log.h b/kernel/log.h index 6c834c6c6..e26ef072c 100644 --- a/kernel/log.h +++ b/kernel/log.h @@ -148,7 +148,7 @@ static inline bool ys_debug(int n = 0) { if (log_force_debug) return true; log_d #else static inline bool ys_debug(int = 0) { return false; } #endif -static inline void log_debug(const char *format, ...) { if (ys_debug(1)) { va_list args; va_start(args, format); logv(format, args); va_end(args); } } +# define log_debug(...) do { if (ys_debug(1)) log(__VA_ARGS__); } while (0) static inline void log_suppressed() { if (log_debug_suppressed && !log_make_debug) { From f1dea786031c232ffb26e322a3131eb928f91c94 Mon Sep 17 00:00:00 2001 From: "N. Engelhardt" Date: Fri, 6 Jun 2025 15:37:42 +0200 Subject: [PATCH 69/74] don't warn for every blackbox from verific --- passes/hierarchy/hierarchy.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/passes/hierarchy/hierarchy.cc b/passes/hierarchy/hierarchy.cc index d94b5cef6..69ef744ca 100644 --- a/passes/hierarchy/hierarchy.cc +++ b/passes/hierarchy/hierarchy.cc @@ -1452,7 +1452,7 @@ struct HierarchyPass : public Pass { bool resize_widths = !keep_portwidths && GetSize(w) != GetSize(conn.second); if (resize_widths && verific_mod && boxed_params) - log_warning("Ignoring width mismatch on %s.%s.%s from verific, is port width parametrizable?\n", + log_debug("Ignoring width mismatch on %s.%s.%s from verific, is port width parametrizable?\n", log_id(module), log_id(cell), log_id(conn.first) ); else if (resize_widths) { From f22248f056b640f63aaeff40510b78d45244d0d4 Mon Sep 17 00:00:00 2001 From: "N. Engelhardt" Date: Fri, 6 Jun 2025 16:30:50 +0200 Subject: [PATCH 70/74] downgrade verific warnings about common coding styles --- frontends/verific/verific.cc | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/frontends/verific/verific.cc b/frontends/verific/verific.cc index 411804566..d12f8a5a5 100644 --- a/frontends/verific/verific.cc +++ b/frontends/verific/verific.cc @@ -3489,6 +3489,14 @@ struct VerificPass : public Pass { // WARNING: instantiating unknown module 'XYZ' (VERI-1063) Message::SetMessageType("VERI-1063", VERIFIC_ERROR); + // Downgrade warnings about things that are normal + // VERIFIC-WARNING [VERI-1209] foo.sv:98: expression size 7 truncated to fit in target size 6 + Message::SetMessageType("VERI-1209", VERIFIC_INFO); + // VERIFIC-WARNING [VERI-1142] foo.sv:55: system task 'display' is ignored for synthesis + Message::SetMessageType("VERI-1142", VERIFIC_INFO); + // VERIFIC-WARNING [VERI-2418] foo.svh:503: parameter 'all_cfgs_gp' declared inside package 'bp_common_pkg' shall be treated as localparam + Message::SetMessageType("VERI-2418", VERIFIC_INFO); + // https://github.com/YosysHQ/yosys/issues/1055 RuntimeFlags::SetVar("veri_elaborate_top_level_modules_having_interface_ports", 1) ; #endif @@ -3547,6 +3555,9 @@ struct VerificPass : public Pass { } else if (Strings::compare(args[argidx].c_str(), "warnings")) { Message::SetAllMessageType(VERIFIC_WARNING, new_type); } else if (Strings::compare(args[argidx].c_str(), "infos")) { + Message::SetMessageType("VERI-1209", new_type); + Message::SetMessageType("VERI-1142", new_type); + Message::SetMessageType("VERI-2418", new_type); Message::SetAllMessageType(VERIFIC_INFO, new_type); } else if (Strings::compare(args[argidx].c_str(), "comments")) { Message::SetAllMessageType(VERIFIC_COMMENT, new_type); From 3fe31294d63d610da9f776932fdc56481532bb66 Mon Sep 17 00:00:00 2001 From: "N. Engelhardt" Date: Fri, 6 Jun 2025 16:41:25 +0200 Subject: [PATCH 71/74] disable warning for intentional use of deprecated function (to assert the feature isn't used any more) --- kernel/rtlil.cc | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/kernel/rtlil.cc b/kernel/rtlil.cc index 1cdc15bb5..189db0648 100644 --- a/kernel/rtlil.cc +++ b/kernel/rtlil.cc @@ -2409,7 +2409,14 @@ void RTLIL::Module::check() // assertion check below to make sure that there are no // cases where a cell has a blackbox attribute since // that is deprecated + #ifdef __GNUC__ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wdeprecated-declarations" + #endif log_assert(!it.second->get_blackbox_attribute()); + #ifdef __GNUC__ + #pragma GCC diagnostic pop + #endif } } From 2a25d9241339042ec3a9cea7267091180b7148e9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sat, 7 Jun 2025 00:24:11 +0000 Subject: [PATCH 72/74] Bump version --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 66d051be4..4db573410 100644 --- a/Makefile +++ b/Makefile @@ -160,7 +160,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.53+98 +YOSYS_VER := 0.53+101 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2) From db72ec3bde296a9512b2d1e6fabf81cfb07c2c1b Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 9 Jun 2025 07:23:54 +0200 Subject: [PATCH 73/74] Release version 0.54 --- CHANGELOG | 15 ++++++++++++++- Makefile | 4 ++-- docs/source/conf.py | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index bdf30260e..bc216234a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,8 +2,21 @@ List of major changes and improvements between releases ======================================================= -Yosys 0.53 .. Yosys 0.54-dev +Yosys 0.53 .. Yosys 0.54 -------------------------- + * New commands and options + - Added "-genlib" option to "abc_new" and "abc9_exe" passes. + - Added "-verbose" and "-quiet" options to "libcache" pass. + - Added "-no-sort" option to "write_aiger" pass. + + * Various + - Added "muldiv_c" peepopt. + - Accept (and ignore) SystemVerilog unique/priority if. + - "read_verilog" copy inout ports in and out of functions/tasks. + - Enable single-bit vector wires in RTLIL. + + * Xilinx support + - Single-port URAM mapping to support memories 2048 x 144b Yosys 0.52 .. Yosys 0.53 -------------------------- diff --git a/Makefile b/Makefile index 4db573410..0b81181c1 100644 --- a/Makefile +++ b/Makefile @@ -160,7 +160,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.53+101 +YOSYS_VER := 0.54 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2) @@ -183,7 +183,7 @@ endif OBJS = kernel/version_$(GIT_REV).o bumpversion: - sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 53c22ab.. | wc -l`/;" Makefile +# sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 53c22ab.. | wc -l`/;" Makefile ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABC_USE_NAMESPACE=abc VERBOSE=$(Q) diff --git a/docs/source/conf.py b/docs/source/conf.py index bfcb28730..100605336 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -6,7 +6,7 @@ import os project = 'YosysHQ Yosys' author = 'YosysHQ GmbH' copyright ='2025 YosysHQ GmbH' -yosys_ver = "0.53" +yosys_ver = "0.54" # select HTML theme html_theme = 'furo-ys' From c16cc539d4afca8fdf42aac2168a62bc2c3d2ff0 Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Mon, 9 Jun 2025 08:12:26 +0200 Subject: [PATCH 74/74] Next dev cycle --- CHANGELOG | 3 +++ Makefile | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index bc216234a..537c5682d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -2,6 +2,9 @@ List of major changes and improvements between releases ======================================================= +Yosys 0.54 .. Yosys 0.55-dev +-------------------------- + Yosys 0.53 .. Yosys 0.54 -------------------------- * New commands and options diff --git a/Makefile b/Makefile index 0b81181c1..b53526039 100644 --- a/Makefile +++ b/Makefile @@ -160,7 +160,7 @@ ifeq ($(OS), Haiku) CXXFLAGS += -D_DEFAULT_SOURCE endif -YOSYS_VER := 0.54 +YOSYS_VER := 0.54+0 YOSYS_MAJOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f1) YOSYS_MINOR := $(shell echo $(YOSYS_VER) | cut -d'.' -f2 | cut -d'+' -f1) YOSYS_COMMIT := $(shell echo $(YOSYS_VER) | cut -d'+' -f2) @@ -183,7 +183,7 @@ endif OBJS = kernel/version_$(GIT_REV).o bumpversion: -# sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline 53c22ab.. | wc -l`/;" Makefile + sed -i "/^YOSYS_VER := / s/+[0-9][0-9]*$$/+`git log --oneline db72ec3.. | wc -l`/;" Makefile ABCMKARGS = CC="$(CXX)" CXX="$(CXX)" ABC_USE_LIBSTDCXX=1 ABC_USE_NAMESPACE=abc VERBOSE=$(Q)