vcd reportWaveforms()

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2022-10-10 15:16:42 -07:00
parent 3f5b22d3b0
commit 6a27aa897b
1 changed files with 112 additions and 18 deletions

View File

@ -18,6 +18,7 @@
#include <cctype> #include <cctype>
#include <vector> #include <vector>
#include <map> #include <map>
#include <algorithm>
#include "Zlib.hh" #include "Zlib.hh"
#include "ReadVcd.hh" #include "ReadVcd.hh"
@ -28,9 +29,13 @@ using std::string;
using std::isspace; using std::isspace;
using std::vector; using std::vector;
using std::map; using std::map;
using std::max;
using std::min;
class VcdVar; class VcdVar;
class VcdValue; class VcdValue;
typedef vector<VcdValue> VcdValues;
typedef int64_t VarTime;
class VcdReader class VcdReader
{ {
@ -49,6 +54,8 @@ private:
void makeVarIdMap(); void makeVarIdMap();
void appendVarValue(string id, void appendVarValue(string id,
char value); char value);
size_t varMaxValueCount();
VarTime varMinTimeDelta();
string getToken(); string getToken();
string readStmtString(); string readStmtString();
vector<string> readStmtTokens(); vector<string> readStmtTokens();
@ -64,8 +71,11 @@ private:
string time_unit_; string time_unit_;
double time_unit_scale_; double time_unit_scale_;
vector<VcdVar> vars_; vector<VcdVar> vars_;
size_t max_var_name_length_;
int max_var_width_;
map<string, VcdVar*> id_var_map_; map<string, VcdVar*> id_var_map_;
int64_t time_; VarTime time_;
VarTime time_max_;
}; };
class VcdVar class VcdVar
@ -80,31 +90,32 @@ public:
VarType type() const { return type_; } VarType type() const { return type_; }
int width() const { return width_; } int width() const { return width_; }
const string& id() const { return id_; } const string& id() const { return id_; }
void pushValue(int64_t time, void pushValue(VarTime time,
char value); char value);
void pushBusValue(int64_t time, void pushBusValue(VarTime time,
int64_t bus_value); VarTime bus_value);
VcdValues values() { return values_; }
private: private:
string name_; string name_;
VarType type_; VarType type_;
int width_; int width_;
string id_; string id_;
vector<VcdValue> values_; VcdValues values_;
}; };
class VcdValue class VcdValue
{ {
public: public:
VcdValue(uint64_t time, VcdValue(VarTime time,
char value, char value,
uint64_t bus_value); uint64_t bus_value);
uint64_t time() const { return time_; } VarTime time() const { return time_; }
char value() const { return value_; } char value() const { return value_; }
uint64_t busValue() const { return bus_value_; } uint64_t busValue() const { return bus_value_; }
private: private:
uint64_t time_; VarTime time_;
// 01XUZ or '\0' when width > 1 to use bus_value_. // 01XUZ or '\0' when width > 1 to use bus_value_.
char value_; char value_;
uint64_t bus_value_; uint64_t bus_value_;
@ -156,7 +167,11 @@ VcdReader::read(const char *filename)
} }
VcdReader::VcdReader() : 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 id = tokens[2];
string name = tokens[3]; string name = tokens[3];
vars_.push_back(VcdVar(name, type, width, id)); 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]); appendVarValue(id, token[1]);
} }
else { 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(); string id = getToken();
auto var_itr = id_var_map_.find(id); auto var_itr = id_var_map_.find(id);
if (var_itr == id_var_map_.end()) if (var_itr == id_var_map_.end())
@ -261,6 +280,7 @@ VcdReader::parseVarValues()
} }
token = getToken(); token = getToken();
} }
time_max_ = time_;
} }
void void
@ -271,10 +291,35 @@ VcdReader::appendVarValue(string id,
if (var_itr == id_var_map_.end()) if (var_itr == id_var_map_.end())
printf("unknown var %s\n", id.c_str()); printf("unknown var %s\n", id.c_str());
VcdVar *var = var_itr->second; VcdVar *var = var_itr->second;
printf("%s = %c\n", var->name().c_str(), value);
var->pushValue(time_, 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<VarTime>::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 string
VcdReader::readStmtString() VcdReader::readStmtString()
{ {
@ -324,11 +369,60 @@ VcdReader::reportWaveforms()
{ {
printf("Date: %s\n", date_.c_str()); printf("Date: %s\n", date_.c_str());
printf("Timescale: %.2f%s\n", time_scale_, time_unit_.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_) { for (VcdVar &var : vars_) {
printf(" %s %d %s\n", printf(" %-*s",
var.name().c_str(), static_cast<int>(max_var_name_length_),
var.width(), var.name().c_str());
var.id().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 void
VcdVar::pushValue(int64_t time, VcdVar::pushValue(VarTime time,
char value) char value)
{ {
values_.push_back(VcdValue(time, value, 0)); values_.push_back(VcdValue(time, value, 0));
} }
void void
VcdVar::pushBusValue(int64_t time, VcdVar::pushBusValue(VarTime time,
int64_t bus_value) int64_t bus_value)
{ {
values_.push_back(VcdValue(time, '\0', bus_value)); values_.push_back(VcdValue(time, '\0', bus_value));
} }
VcdValue::VcdValue(uint64_t time, VcdValue::VcdValue(VarTime time,
char value, char value,
uint64_t bus_value) : uint64_t bus_value) :
time_(time), time_(time),