From 01d15e05b2fbb85a5df7f17000902cf6c86cb2e4 Mon Sep 17 00:00:00 2001 From: James Cherry Date: Wed, 26 Oct 2022 14:27:30 -0700 Subject: [PATCH] read_vcd factor Vdd out of VcdReader Signed-off-by: James Cherry --- search/ReadVcd.cc | 355 ++++++++++++++++++++++++++++++---------------- 1 file changed, 236 insertions(+), 119 deletions(-) diff --git a/search/ReadVcd.cc b/search/ReadVcd.cc index aa303f62..045d50c5 100644 --- a/search/ReadVcd.cc +++ b/search/ReadVcd.cc @@ -47,50 +47,6 @@ typedef vector VcdScope; // Much better syntax definition // https://web.archive.org/web/20120323132708/http://www.beyondttl.com/vcd.php -class VcdReader : public StaState -{ -public: - VcdReader(StaState *sta); - void read(const char *filename); - void reportWaveforms(); - -private: - void parseTimescale(); - void parseVar(); - void parseScope(); - void parseUpscope(); - void parseVarValues(); - void makeVarIdMap(); - void appendVarValue(string id, - char value); - string getToken(); - string readStmtString(); - vector readStmtTokens(); - VcdValues &values(VcdVar &var); - - gzFile stream_; - string token_; - const char *filename_; - int file_line_; - int stmt_line_; - - string date_; - string comment_; - string version_; - double time_scale_; - string time_unit_; - double time_unit_scale_; - vector vars_; - size_t max_var_name_length_; - int max_var_width_; - map id_values_map_; - VarTime time_; - VarTime prev_time_; - VarTime min_delta_time_; - VarTime time_max_; - VcdScope scope_; -}; - class VcdVar { public: @@ -111,6 +67,56 @@ private: string id_; }; +class Vcd : public StaState +{ +public: + Vcd(StaState *sta); + VcdValues &values(VcdVar &var); + void reportWaveforms(); + + const string &date() const { return date_; } + void setDate(const string &date); + const string &comment() const { return comment_; } + void setComment(const string &comment); + const string &version() const { return version_; } + void setVersion(const string &version); + double timeScale() const { return time_scale_; } + void setTimeScale(double time_scale); + const string &timeUnit() const { return time_unit_; } + void setTimeUnit(const string &time_unit, + double time_unit_scale); + VarTime timeMax() const { return time_max_; } + void setTimeMax(VarTime time_max); + VarTime minDeltaTime() const { return min_delta_time_; } + void setMinDeltaTime(VarTime min_delta_time); + void makeVar(string &name, + VcdVar::VarType type, + int width, + string &id); + bool varIdValid(string &id); + void varAppendValue(string &id, + VarTime time, + char value); + void varAppendBusValue(string &id, + VarTime time, + int64_t bus_value); + +private: + string date_; + string comment_; + string version_; + double time_scale_; + string time_unit_; + double time_unit_scale_; + + vector vars_; + size_t max_var_name_length_; + int max_var_width_; + map id_values_map_; + VarTime min_delta_time_; + VarTime time_max_; +}; + class VcdValue { public: @@ -128,19 +134,52 @@ private: uint64_t bus_value_; }; +//////////////////////////////////////////////////////////////// + +class VcdReader : public StaState +{ +public: + VcdReader(StaState *sta); + Vcd read(const char *filename); + +private: + void parseTimescale(); + void setTimeUnit(const string &time_unit); + void parseVar(); + void parseScope(); + void parseUpscope(); + void parseVarValues(); + string getToken(); + string readStmtString(); + vector readStmtTokens(); + + gzFile stream_; + string token_; + const char *filename_; + int file_line_; + int stmt_line_; + + Vcd *vcd_; + VarTime time_; + VarTime prev_time_; + VcdScope scope_; +}; + void readVcdFile(const char *filename, StaState *sta) { VcdReader reader(sta); - reader.read(filename); - reader.reportWaveforms(); + Vcd vcd = reader.read(filename); + vcd.reportWaveforms(); } -void +Vcd VcdReader::read(const char *filename) { + Vcd vcd(this); + vcd_ = &vcd; stream_ = gzopen(filename, "r"); if (stream_) { filename_ = filename; @@ -149,11 +188,11 @@ VcdReader::read(const char *filename) string token = getToken(); while (!token.empty()) { if (token == "$date") - date_ = readStmtString(); + vcd_->setDate(readStmtString()); else if (token == "$comment") - comment_ = readStmtString(); + vcd_->setComment(readStmtString()); else if (token == "$version") - version_ = readStmtString(); + vcd_->setVersion(readStmtString()); else if (token == "$timescale") parseTimescale(); else if (token == "$var") @@ -162,11 +201,9 @@ VcdReader::read(const char *filename) parseScope(); else if (token == "$upscope") parseUpscope(); - else if (token == "$enddefinitions") { + else if (token == "$enddefinitions") // empty body readStmtString(); - makeVarIdMap(); - } else if (token == "$dumpall") parseVarValues(); else if (token == "$dumpvars") @@ -180,18 +217,15 @@ VcdReader::read(const char *filename) } gzclose(stream_); } + return vcd; } VcdReader::VcdReader(StaState *sta) : StaState(sta), stmt_line_(0), - time_unit_scale_(0.0), - max_var_name_length_(0), - max_var_width_(0), + vcd_(nullptr), time_(0), - prev_time_(0), - min_delta_time_(std::numeric_limits::max()), - time_max_(0) + prev_time_(0) { } @@ -201,24 +235,30 @@ VcdReader::parseTimescale() vector tokens = readStmtTokens(); if (tokens.size() == 1) { size_t last; - time_scale_ = std::stod(tokens[0], &last); - time_unit_ = tokens[0].substr(last); + vcd_->setTimeScale(std::stod(tokens[0], &last)); + setTimeUnit(tokens[0].substr(last)); } else if (tokens.size() == 2) { - time_scale_ = std::stod(tokens[0]); - time_unit_ = tokens[1]; + vcd_->setTimeScale(std::stod(tokens[0])); + setTimeUnit(tokens[1]); } else report_->fileError(800, filename_, stmt_line_, "timescale syntax error."); +} - if (time_unit_ == "fs") - time_unit_scale_ = 1e-15; - else if (time_unit_ == "ps") - time_unit_scale_ = 1e-12; - else if (time_unit_ == "ns") - time_unit_scale_ = 1e-9; +void +VcdReader::setTimeUnit(const string &time_unit) +{ + double time_unit_scale = 1.0; + if (time_unit == "fs") + time_unit_scale = 1e-15; + else if (time_unit == "ps") + time_unit_scale = 1e-12; + else if (time_unit == "ns") + time_unit_scale = 1e-9; else report_->fileError(801, filename_, stmt_line_, "Unknown timescale unit."); + vcd_->setTimeUnit(time_unit, time_unit_scale);; } void @@ -260,9 +300,7 @@ VcdReader::parseVar() if (tokens.size() == 5) name += tokens[4]; - 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); + vcd_->makeVar(name, type, width, id); } else report_->fileError(802, filename_, stmt_line_, "Variable syntax error."); @@ -283,16 +321,6 @@ VcdReader::parseUpscope() scope_.pop_back(); } -// Make entries for each ID used by variables. -void -VcdReader::makeVarIdMap() -{ - for (VcdVar &var : vars_) { - const string &id = var.id(); - id_values_map_[id].clear(); - } -} - void VcdReader::parseVarValues() { @@ -302,64 +330,45 @@ VcdReader::parseVarValues() prev_time_ = time_; time_ = stoll(token.substr(1)); if (time_ > prev_time_) - min_delta_time_ = min(time_ - prev_time_, min_delta_time_); + vcd_->setMinDeltaTime(min(time_ - prev_time_, vcd_->minDeltaTime())); } else if (token[0] == '0' || token[0] == '1' || token[0] == 'X' || token[0] == 'U' - || token[0] == 'Z') - appendVarValue(token.substr(1), token[0]); + || token[0] == 'Z') { + string id = token.substr(1); + if (!vcd_->varIdValid(id)) + report_->fileError(804, filename_, stmt_line_, + "unknown variable %s", id.c_str()); + vcd_->varAppendValue(id, time_, token[0]); + } else if (token[0] == 'b') { if (token[1] == 'X' || token[1] == 'U' || token[1] == 'Z') { string id = getToken(); - // Mixed 0/1/X/U not supported. - appendVarValue(id, token[1]); + if (!vcd_->varIdValid(id)) + report_->fileError(804, filename_, stmt_line_, + "unknown variable %s", id.c_str()); + // Bus mixed 0/1/X/U not supported. + vcd_->varAppendValue(id, time_, token[1]); } else { string bin = token.substr(1); char *end; int64_t bus_value = strtol(bin.c_str(), &end, 2); string id = getToken(); - auto values_itr = id_values_map_.find(id); - if (values_itr == id_values_map_.end()) + if (!vcd_->varIdValid(id)) report_->fileError(804, filename_, stmt_line_, "unknown variable %s", id.c_str()); - VcdValues &values = values_itr->second; - values.push_back(VcdValue(time_, '\0', bus_value)); + else + vcd_->varAppendBusValue(id, time_, bus_value); } } token = getToken(); } - time_max_ = time_; -} - -void -VcdReader::appendVarValue(string id, - char value) -{ - auto values_itr = id_values_map_.find(id); - if (values_itr == id_values_map_.end()) - report_->fileError(805, filename_, stmt_line_, - "Unknown variable %s", id.c_str()); - VcdValues &values = values_itr->second; - values.push_back(VcdValue(time_, value, 0)); -} - -VcdValues & -VcdReader::values(VcdVar &var) -{ - if (id_values_map_.find(var.id()) == id_values_map_.end()) { - report_->error(805, "Unknown variable %s ID %s", - var.name().c_str(), - var.id().c_str()); - static VcdValues empty; - return empty; - } - else - return id_values_map_[var.id()]; + vcd_->setTimeMax(time_); } string @@ -415,8 +424,19 @@ VcdReader::getToken() return token; } +//////////////////////////////////////////////////////////////// + +Vcd::Vcd(StaState *sta) : + StaState(sta), + time_unit_scale_(0.0), + max_var_name_length_(0), + max_var_width_(0), + time_max_(0) +{ +} + void -VcdReader::reportWaveforms() +Vcd::reportWaveforms() { report_->reportLine("Date: %s", date_.c_str()); report_->reportLine("Timescale: %.2f%s", time_scale_, time_unit_.c_str()); @@ -486,6 +506,103 @@ VcdReader::reportWaveforms() //////////////////////////////////////////////////////////////// +void +Vcd::setTimeUnit(const string &time_unit, + double time_unit_scale) +{ + time_unit_ = time_unit; + time_unit_scale_ = time_unit_scale; +} + +void +Vcd::setDate(const string &date) +{ + date_ = date; +} + +void +Vcd::setComment(const string &comment) +{ + comment_ = comment; +} + +void +Vcd::setVersion(const string &version) +{ + version_ = version; +} + +void +Vcd::setTimeScale(double time_scale) +{ + time_scale_ = time_scale; +} + +void +Vcd::setMinDeltaTime(VarTime min_delta_time) +{ + min_delta_time_ = min_delta_time; +} + +void +Vcd::setTimeMax(VarTime time_max) +{ + time_max_ = time_max; +} + +void +Vcd::makeVar(string &name, + VcdVar::VarType type, + int width, + string &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); + // Make entry for var ID. + id_values_map_[id].clear(); +} + +bool +Vcd::varIdValid(string &id) +{ + return id_values_map_.find(id) != id_values_map_.end(); +} + +void +Vcd::varAppendValue(string &id, + VarTime time, + char value) +{ + VcdValues &values = id_values_map_[id]; + values.push_back(VcdValue(time, value, 0)); +} + +void +Vcd::varAppendBusValue(string &id, + VarTime time, + int64_t bus_value) +{ + VcdValues &values = id_values_map_[id]; + values.push_back(VcdValue(time, '\0', bus_value)); +} + +VcdValues & +Vcd::values(VcdVar &var) +{ + if (id_values_map_.find(var.id()) == id_values_map_.end()) { + report_->error(805, "Unknown variable %s ID %s", + var.name().c_str(), + var.id().c_str()); + static VcdValues empty; + return empty; + } + else + return id_values_map_[var.id()]; +} + +//////////////////////////////////////////////////////////////// + VcdVar::VcdVar(string name, VarType type, int width,