Merge pull request #2480 from YosysHQ/dave/nexus-lram
[yosys.git] / backends / cxxrtl / cxxrtl_vcd.h
index dbeabbaf2d8548862f77e1a69e4fb40af2e02b54..6ee98b4284db16080b45054f50b400be70e677bc 100644 (file)
@@ -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<std::string> current_scope;
+       std::map<debug_outline*, bool> outlines;
        std::vector<variable> variables;
        std::vector<chunk_t> cache;
        std::map<chunk_t*, size_t> aliases;
@@ -112,16 +115,22 @@ class vcd_writer {
                buffer += '\n';
        }
 
-       const variable &register_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 &register_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) {