From d5c07e5b6f5c91666867751233f5c537068a7136 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jun 2020 16:36:26 +0000 Subject: cxxrtl: track aliases in VCD writer. This commit changes the VCD writer such that for all signals that share `debug_item.curr`, it would only emit a single VCD identifier, and sample the value once. Commit 9b39c6f7 added redundancy to debug information by including alias wires, and increased the size of VCD files proportionally; this commit eliminates the redundancy from VCD files so that their size is the same as before. --- backends/cxxrtl/cxxrtl_vcd.h | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) (limited to 'backends/cxxrtl/cxxrtl_vcd.h') diff --git a/backends/cxxrtl/cxxrtl_vcd.h b/backends/cxxrtl/cxxrtl_vcd.h index 5706917ca..8ba94ea77 100644 --- a/backends/cxxrtl/cxxrtl_vcd.h +++ b/backends/cxxrtl/cxxrtl_vcd.h @@ -34,6 +34,7 @@ class vcd_writer { std::vector current_scope; std::vector variables; std::vector cache; + std::map aliases; bool streaming = false; void emit_timescale(unsigned number, const std::string &unit) { @@ -103,10 +104,16 @@ 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]); + const variable ®ister_variable(size_t width, chunk_t *curr) { + if (aliases.count(curr)) { + return variables[aliases[curr]]; + } else { + const size_t chunks = (width + (sizeof(chunk_t) * 8 - 1)) / (sizeof(chunk_t) * 8); + aliases[curr] = variables.size(); + variables.emplace_back(variable { variables.size(), width, curr, cache.size() }); + cache.insert(cache.end(), &curr[0], &curr[chunks]); + return variables.back(); + } } bool test_variable(const variable &var) { @@ -151,20 +158,17 @@ public: switch (item.type) { // Not the best naming but oh well... case debug_item::VALUE: - append_variable(item.width, item.curr); - emit_var(variables.back(), "wire", name); + emit_var(register_variable(item.width, item.curr), "wire", name); break; case debug_item::WIRE: - append_variable(item.width, item.curr); - emit_var(variables.back(), "reg", name); + emit_var(register_variable(item.width, item.curr), "reg", name); break; case debug_item::MEMORY: { const size_t stride = (item.width + (sizeof(chunk_t) * 8 - 1)) / (sizeof(chunk_t) * 8); 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) + ']'; - append_variable(item.width, nth_curr); - emit_var(variables.back(), "reg", nth_name); + emit_var(register_variable(item.width, nth_curr), "reg", nth_name); } break; } -- cgit v1.2.3 From 467152d79fd4c8e25b48481f742fe318b1395728 Mon Sep 17 00:00:00 2001 From: whitequark Date: Mon, 8 Jun 2020 17:38:11 +0000 Subject: cxxrtl: don't check immutable values for changes in VCD writer. This commit changes the VCD writer such that for all signals that have `debug_item.type == VALUE && debug_item.next == nullptr`, it would only sample the value once. Commit f2d7a187 added more debug information by including constant wires, and decreased the performance of VCD writer proportionally because the constant wires were still repeatedly sampled; this commit eliminates the performance hit. --- backends/cxxrtl/cxxrtl_vcd.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'backends/cxxrtl/cxxrtl_vcd.h') diff --git a/backends/cxxrtl/cxxrtl_vcd.h b/backends/cxxrtl/cxxrtl_vcd.h index 8ba94ea77..5f5f612b5 100644 --- a/backends/cxxrtl/cxxrtl_vcd.h +++ b/backends/cxxrtl/cxxrtl_vcd.h @@ -104,19 +104,25 @@ class vcd_writer { buffer += '\n'; } - const variable ®ister_variable(size_t width, chunk_t *curr) { + const variable ®ister_variable(size_t width, chunk_t *curr, bool immutable = false) { if (aliases.count(curr)) { return variables[aliases[curr]]; } else { const size_t chunks = (width + (sizeof(chunk_t) * 8 - 1)) / (sizeof(chunk_t) * 8); aliases[curr] = variables.size(); - variables.emplace_back(variable { variables.size(), width, curr, cache.size() }); - cache.insert(cache.end(), &curr[0], &curr[chunks]); + if (immutable) { + variables.emplace_back(variable { variables.size(), width, curr, (size_t)-1 }); + } else { + variables.emplace_back(variable { variables.size(), width, curr, cache.size() }); + cache.insert(cache.end(), &curr[0], &curr[chunks]); + } return variables.back(); } } bool test_variable(const variable &var) { + if (var.prev_off == (size_t)-1) + return false; // immutable 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; @@ -158,7 +164,7 @@ public: switch (item.type) { // Not the best naming but oh well... case debug_item::VALUE: - emit_var(register_variable(item.width, item.curr), "wire", name); + emit_var(register_variable(item.width, item.curr, /*immutable=*/item.next == nullptr), "wire", name); break; case debug_item::WIRE: emit_var(register_variable(item.width, item.curr), "reg", name); -- cgit v1.2.3