diff options
author | whitequark <whitequark@whitequark.org> | 2020-06-06 21:55:53 +0000 |
---|---|---|
committer | whitequark <whitequark@whitequark.org> | 2020-06-07 03:48:00 +0000 |
commit | 68362a90530328f15cb93a04f1b1cc65858b93c0 (patch) | |
tree | 15eddde02988b75924f3becf5ccccaf7961d1ab6 | |
parent | 9c361026698eb52ebbeda8cf39f9d907bb640f39 (diff) | |
download | yosys-68362a90530328f15cb93a04f1b1cc65858b93c0.tar.gz yosys-68362a90530328f15cb93a04f1b1cc65858b93c0.tar.bz2 yosys-68362a90530328f15cb93a04f1b1cc65858b93c0.zip |
cxxrtl: only write VCD values that were actually updated.
On a representative design (Minerva SoC) this reduces VCD file size
by ~20× and runtime by ~3×.
-rw-r--r-- | backends/cxxrtl/cxxrtl_vcd.h | 40 |
1 files changed, 30 insertions, 10 deletions
diff --git a/backends/cxxrtl/cxxrtl_vcd.h b/backends/cxxrtl/cxxrtl_vcd.h index 537bd5661..5706917ca 100644 --- a/backends/cxxrtl/cxxrtl_vcd.h +++ b/backends/cxxrtl/cxxrtl_vcd.h @@ -28,10 +28,12 @@ class vcd_writer { size_t ident; size_t width; chunk_t *curr; + size_t prev_off; }; std::vector<std::string> current_scope; std::vector<variable> variables; + std::vector<chunk_t> cache; bool streaming = false; void emit_timescale(unsigned number, const std::string &unit) { @@ -101,6 +103,22 @@ class vcd_writer { buffer += '\n'; } + void append_variable(size_t width, chunk_t *curr) { + const size_t chunks = (width + (sizeof(chunk_t) * 8 - 1)) / (sizeof(chunk_t) * 8); + variables.emplace_back(variable { variables.size(), width, curr, cache.size() }); + cache.insert(cache.end(), &curr[0], &curr[chunks]); + } + + bool test_variable(const variable &var) { + const size_t chunks = (var.width + (sizeof(chunk_t) * 8 - 1)) / (sizeof(chunk_t) * 8); + if (std::equal(&var.curr[0], &var.curr[chunks], &cache[var.prev_off])) { + return false; + } else { + std::copy(&var.curr[0], &var.curr[chunks], &cache[var.prev_off]); + return true; + } + } + static std::vector<std::string> split_hierarchy(const std::string &hier_name) { std::vector<std::string> hierarchy; size_t prev = 0; @@ -133,11 +151,11 @@ public: switch (item.type) { // Not the best naming but oh well... case debug_item::VALUE: - variables.emplace_back(variable { variables.size(), item.width, item.curr }); + append_variable(item.width, item.curr); emit_var(variables.back(), "wire", name); break; case debug_item::WIRE: - variables.emplace_back(variable { variables.size(), item.width, item.curr }); + append_variable(item.width, item.curr); emit_var(variables.back(), "reg", name); break; case debug_item::MEMORY: { @@ -145,7 +163,7 @@ public: for (size_t index = 0; index < item.depth; index++) { chunk_t *nth_curr = &item.curr[stride * index]; std::string nth_name = name + '[' + std::to_string(index) + ']'; - variables.emplace_back(variable { variables.size(), item.width, nth_curr }); + append_variable(item.width, nth_curr); emit_var(variables.back(), "reg", nth_name); } break; @@ -175,17 +193,19 @@ public: } void sample(uint64_t timestamp) { - if (!streaming) { + bool first_sample = !streaming; + if (first_sample) { emit_scope({}); emit_enddefinitions(); } emit_time(timestamp); - for (auto var : variables) { - if (var.width == 1) - emit_scalar(var); - else - emit_vector(var); - } + for (auto var : variables) + if (test_variable(var) || first_sample) { + if (var.width == 1) + emit_scalar(var); + else + emit_vector(var); + } } }; |