From ece25a45d4b12f0436be238a13e622b58282036e Mon Sep 17 00:00:00 2001 From: whitequark Date: Sun, 13 Dec 2020 07:03:16 +0000 Subject: cxxrtl: implement debug information outlining. Aggressive wire localization and inlining is necessary for CXXRTL to achieve high performance. However, that comes with a cost: reduced debug information coverage. Previously, as a workaround, the `-Og` option could have been used to guarantee complete coverage, at a cost of a significant performance penalty. This commit introduces debug information outlining. The main eval() function is compiled with the user-specified optimization settings. In tandem, an auxiliary debug_eval() function, compiled from the same netlist, can be used to reconstruct the values of localized/inlined signals on demand. To the extent that it is possible, debug_eval() reuses the results of computations performed by eval(), only filling in the missing values. Benchmarking a representative design (Minerva SoC SRAM) shows that: * Switching from `-O4`/`-Og` to `-O6` reduces runtime by ~40%. * Switching from `-g1` to `-g2`, both used with `-O6`, increases compile time by ~25%. * Although `-g2` increases the resident size of generated modules, this has no effect on runtime. Because the impact of `-g2` is minimal and the benefits of having unconditional 100% debug information coverage (and the performance improvement as well) are major, this commit removes `-Og` and changes the defaults to `-O6 -g2`. We'll have our cake and eat it too! --- backends/cxxrtl/cxxrtl_vcd.h | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) (limited to 'backends/cxxrtl/cxxrtl_vcd.h') diff --git a/backends/cxxrtl/cxxrtl_vcd.h b/backends/cxxrtl/cxxrtl_vcd.h index dbeabbaf2..6ee98b428 100644 --- a/backends/cxxrtl/cxxrtl_vcd.h +++ b/backends/cxxrtl/cxxrtl_vcd.h @@ -28,10 +28,13 @@ class vcd_writer { size_t ident; size_t width; chunk_t *curr; - size_t prev_off; + size_t cache_offset; + debug_outline *outline; + bool *outline_warm; }; std::vector current_scope; + std::map outlines; std::vector variables; std::vector cache; std::map aliases; @@ -112,16 +115,22 @@ class vcd_writer { buffer += '\n'; } - const variable ®ister_variable(size_t width, chunk_t *curr, bool constant = false) { + void reset_outlines() { + for (auto &outline_it : outlines) + outline_it.second = /*warm=*/(outline_it.first == nullptr); + } + + variable ®ister_variable(size_t width, chunk_t *curr, bool constant = false, debug_outline *outline = nullptr) { if (aliases.count(curr)) { return variables[aliases[curr]]; } else { + auto outline_it = outlines.emplace(outline, /*warm=*/(outline == nullptr)).first; const size_t chunks = (width + (sizeof(chunk_t) * 8 - 1)) / (sizeof(chunk_t) * 8); aliases[curr] = variables.size(); if (constant) { - variables.emplace_back(variable { variables.size(), width, curr, (size_t)-1 }); + variables.emplace_back(variable { variables.size(), width, curr, (size_t)-1, outline_it->first, &outline_it->second }); } else { - variables.emplace_back(variable { variables.size(), width, curr, cache.size() }); + variables.emplace_back(variable { variables.size(), width, curr, cache.size(), outline_it->first, &outline_it->second }); cache.insert(cache.end(), &curr[0], &curr[chunks]); } return variables.back(); @@ -129,13 +138,17 @@ class vcd_writer { } bool test_variable(const variable &var) { - if (var.prev_off == (size_t)-1) + if (var.cache_offset == (size_t)-1) return false; // constant + if (!*var.outline_warm) { + var.outline->eval(); + *var.outline_warm = true; + } 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])) { + if (std::equal(&var.curr[0], &var.curr[chunks], &cache[var.cache_offset])) { return false; } else { - std::copy(&var.curr[0], &var.curr[chunks], &cache[var.prev_off]); + std::copy(&var.curr[0], &var.curr[chunks], &cache[var.cache_offset]); return true; } } @@ -197,6 +210,10 @@ public: emit_var(register_variable(item.width, item.curr), "wire", name, item.lsb_at, multipart); break; + case debug_item::OUTLINE: + emit_var(register_variable(item.width, item.curr, /*constant=*/false, item.outline), + "wire", name, item.lsb_at, multipart); + break; } } @@ -228,6 +245,7 @@ public: emit_scope({}); emit_enddefinitions(); } + reset_outlines(); emit_time(timestamp); for (auto var : variables) if (test_variable(var) || first_sample) { -- cgit v1.2.3