diff --git a/search/ReadVcd.cc b/search/ReadVcd.cc index 6a613899..6dac93e4 100644 --- a/search/ReadVcd.cc +++ b/search/ReadVcd.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include "Zlib.hh" #include "ReadVcd.hh" @@ -28,9 +29,13 @@ using std::string; using std::isspace; using std::vector; using std::map; +using std::max; +using std::min; class VcdVar; class VcdValue; +typedef vector VcdValues; +typedef int64_t VarTime; class VcdReader { @@ -49,6 +54,8 @@ private: void makeVarIdMap(); void appendVarValue(string id, char value); + size_t varMaxValueCount(); + VarTime varMinTimeDelta(); string getToken(); string readStmtString(); vector readStmtTokens(); @@ -64,8 +71,11 @@ private: string time_unit_; double time_unit_scale_; vector vars_; + size_t max_var_name_length_; + int max_var_width_; map id_var_map_; - int64_t time_; + VarTime time_; + VarTime time_max_; }; class VcdVar @@ -80,31 +90,32 @@ public: VarType type() const { return type_; } int width() const { return width_; } const string& id() const { return id_; } - void pushValue(int64_t time, + void pushValue(VarTime time, char value); - void pushBusValue(int64_t time, - int64_t bus_value); + void pushBusValue(VarTime time, + VarTime bus_value); + VcdValues values() { return values_; } private: string name_; VarType type_; int width_; string id_; - vector values_; + VcdValues values_; }; class VcdValue { public: - VcdValue(uint64_t time, + VcdValue(VarTime time, char value, uint64_t bus_value); - uint64_t time() const { return time_; } + VarTime time() const { return time_; } char value() const { return value_; } uint64_t busValue() const { return bus_value_; } private: - uint64_t time_; + VarTime time_; // 01XUZ or '\0' when width > 1 to use bus_value_. char value_; uint64_t bus_value_; @@ -156,7 +167,11 @@ VcdReader::read(const char *filename) } VcdReader::VcdReader() : - time_(0) + time_unit_scale_(0.0), + max_var_name_length_(0), + max_var_width_(0), + time_(0), + time_max_(0) { } @@ -199,6 +214,8 @@ VcdReader::parseVar() string id = tokens[2]; string name = tokens[3]; vars_.push_back(VcdVar(name, type, width, id)); + max_var_name_length_ = std::max(max_var_name_length_, name.size()); + max_var_width_ = std::max(max_var_width_, width); } } @@ -249,7 +266,9 @@ VcdReader::parseVarValues() appendVarValue(id, token[1]); } else { - int64_t bus_value = stoll(token.substr(1)); + string bin = token.substr(1); + char *end; + int64_t bus_value = strtol(bin.c_str(), &end, 2); string id = getToken(); auto var_itr = id_var_map_.find(id); if (var_itr == id_var_map_.end()) @@ -261,6 +280,7 @@ VcdReader::parseVarValues() } token = getToken(); } + time_max_ = time_; } void @@ -271,10 +291,35 @@ VcdReader::appendVarValue(string id, if (var_itr == id_var_map_.end()) printf("unknown var %s\n", id.c_str()); VcdVar *var = var_itr->second; - printf("%s = %c\n", var->name().c_str(), value); var->pushValue(time_, value); } +size_t +VcdReader::varMaxValueCount() +{ + size_t max_count = 0; + for (VcdVar &var : vars_) + max_count = max(max_count, var.values().size()); + return max_count; +} + +VarTime +VcdReader::varMinTimeDelta() +{ + VarTime min_delta = std::numeric_limits::max(); + for (VcdVar &var : vars_) { + VcdValues var_values = var.values(); + VarTime prev_time = var_values[0].time(); + for (VcdValue &value : var_values) { + VarTime time_delta = value.time() - prev_time; + if (time_delta > 0) + min_delta = min(min_delta, time_delta); + prev_time = value.time(); + } + } + return min_delta; +} + string VcdReader::readStmtString() { @@ -324,11 +369,60 @@ VcdReader::reportWaveforms() { printf("Date: %s\n", date_.c_str()); printf("Timescale: %.2f%s\n", time_scale_, time_unit_.c_str()); + // Characters per time sample. + int zoom = (max_var_width_ + 7) / 4; + int time_delta = varMinTimeDelta(); + // for (double time = 0.0; time < time_max_; time += time_delta) { + // //printf("%-*g", time_delta * zoom - 1, time * time_scale_ * time_unit_scale_); + // printf("%g", time * time_scale_ * time_unit_scale_); + // } + // printf("\n"); + for (VcdVar &var : vars_) { - printf(" %s %d %s\n", - var.name().c_str(), - var.width(), - var.id().c_str()); + printf(" %-*s", + static_cast(max_var_name_length_), + var.name().c_str()); + VcdValues var_values = var.values(); + size_t value_index = 0; + VcdValue var_value = var_values[value_index]; + VcdValue prev_var_value = var_values[value_index]; + VarTime next_value_time = var_values[value_index + 1].time(); + for (double time = 0.0; time < time_max_; time += time_delta) { + if (time >= next_value_time) { + if (value_index < var_values.size() - 1) + value_index++; + var_value = var_values[value_index]; + if (value_index < var_values.size()) + next_value_time = var_values[value_index + 1].time(); + } + if (var_value.value()) { + // 01UZX + char value = var_value.value(); + char prev_value = prev_var_value.value(); + if (var.width() == 1) { + if (value == '0' || value == '1') { + for (int z = 0; z < zoom; z++) { + if (z == 0 + && value != prev_value + && (prev_value == '0' + || prev_value == '1')) + printf("%s", prev_value == '1' ? "╲" : "╱"); + else + printf("%s", value == '1' ? "▔" : "▁"); + } + } + else + printf("%-*c", zoom, value); + } + else + printf("%-*c", zoom, value); + } + else + // bus + printf("%-*llX", zoom, var_value.busValue()); + prev_var_value = var_value; + } + printf("\n"); } } @@ -346,20 +440,20 @@ VcdVar::VcdVar(string name, } void -VcdVar::pushValue(int64_t time, +VcdVar::pushValue(VarTime time, char value) { values_.push_back(VcdValue(time, value, 0)); } void -VcdVar::pushBusValue(int64_t time, +VcdVar::pushBusValue(VarTime time, int64_t bus_value) { values_.push_back(VcdValue(time, '\0', bus_value)); } -VcdValue::VcdValue(uint64_t time, +VcdValue::VcdValue(VarTime time, char value, uint64_t bus_value) : time_(time),