diff --git a/doc/OpenSTA.odt b/doc/OpenSTA.odt index a6c9a62d..c627a6a5 100644 Binary files a/doc/OpenSTA.odt and b/doc/OpenSTA.odt differ diff --git a/power/Power.i b/power/Power.i index 002598f5..c30e174b 100644 --- a/power/Power.i +++ b/power/Power.i @@ -122,4 +122,12 @@ report_vcd_waveforms(const char *filename) reportVcdWaveforms(filename, Sta::sta()); } +// debugging +void +report_vcd_var_values(const char *filename, + const char *var_name) +{ + reportVcdVarValues(filename, var_name, Sta::sta()); +} + %} // inline diff --git a/power/ReadVcdActivities.cc b/power/ReadVcdActivities.cc index 7bb5c5f5..7a804c43 100644 --- a/power/ReadVcdActivities.cc +++ b/power/ReadVcdActivities.cc @@ -28,7 +28,6 @@ namespace sta { using std::min; -using std::swap; using std::to_string; class ReadVcdActivities : public StaState @@ -41,9 +40,17 @@ public: private: void setActivities(); - void findVarActivity(const char *pin_name, + void setVarActivity(const char *pin_name, + const VcdValues &var_values, + int value_bit); + void findVarActivity(const VcdValues &var_values, int value_bit, - const VcdValues &var_values); + // Return values. + int &transition_count, + float &activity, + float &duty); + void checkClkPeriod(const Pin *pin, + int transition_count); const char *filename_; const char *scope_; @@ -83,8 +90,6 @@ ReadVcdActivities::readActivities() for (Clock *clk : *sta_->sdc()->clocks()) clk_period_ = min(clk->period(), clk_period_); - //checkClkPeriods(); - setActivities(); } @@ -92,12 +97,12 @@ void ReadVcdActivities::setActivities() { size_t scope_length = strlen(scope_); - for (VcdVar &var : vcd_.vars()) { + for (VcdVar *var : vcd_.vars()) { const VcdValues &var_values = vcd_.values(var); if (!var_values.empty() - && (var.type() == VcdVarType::wire - || var.type() == VcdVarType::reg)) { - string var_name = var.name(); + && (var->type() == VcdVarType::wire + || var->type() == VcdVarType::reg)) { + string var_name = var->name(); // string::starts_with in c++20 if (scope_length && var_name.substr(0, scope_length) == scope_) @@ -106,8 +111,8 @@ ReadVcdActivities::setActivities() var_name += ' '; const char *sta_name = verilogToSta(var_name.c_str()); - if (var.width() == 1) - findVarActivity(sta_name, 0, var_values); + if (var->width() == 1) + setVarActivity(sta_name, var_values, 0); else { char *bus_name; int from, to; @@ -120,7 +125,7 @@ ReadVcdActivities::setActivities() pin_name += '['; pin_name += to_string(bus_bit); pin_name += ']'; - findVarActivity(pin_name.c_str(), value_bit, var_values); + setVarActivity(pin_name.c_str(), var_values, value_bit); value_bit++; } } @@ -130,7 +135,7 @@ ReadVcdActivities::setActivities() pin_name += '['; pin_name += to_string(bus_bit); pin_name += ']'; - findVarActivity(pin_name.c_str(), value_bit, var_values); + setVarActivity(pin_name.c_str(), var_values, value_bit); value_bit++; } } @@ -140,11 +145,39 @@ ReadVcdActivities::setActivities() } void -ReadVcdActivities::findVarActivity(const char *pin_name, - int value_bit, - const VcdValues &var_values) +ReadVcdActivities::setVarActivity(const char *pin_name, + const VcdValues &var_values, + int value_bit) { - int transition_count = 0; + const Pin *pin = network_->findPin(pin_name); + if (pin) { + int transition_count; + float activity, duty; + findVarActivity(var_values, value_bit, + transition_count, activity, duty); + debugPrint(debug_, "read_vcd_activities", 1, + "%s transitions %d activity %.2f duty %.2f", + pin_name, + transition_count, + activity, + duty); + if (sdc_->isLeafPinClock(pin)) + checkClkPeriod(pin, transition_count); + else + power_->setUserActivity(pin, activity, duty, + PwrActivityOrigin::user); + } +} + +void +ReadVcdActivities::findVarActivity(const VcdValues &var_values, + int value_bit, + // Return values. + int &transition_count, + float &activity, + float &duty) +{ + transition_count = 0; char prev_value = var_values[0].value(); VcdTime prev_time = var_values[0].time(); VcdTime high_time = 0; @@ -164,20 +197,23 @@ ReadVcdActivities::findVarActivity(const char *pin_name, VcdTime time_max = vcd_.timeMax(); if (prev_value == '1') high_time += time_max - prev_time; - float duty = static_cast(high_time) / time_max; - float activity = transition_count + duty = static_cast(high_time) / time_max; + activity = transition_count / (time_max * vcd_.timeUnitScale() / clk_period_); +} - Pin *pin = network_->findPin(pin_name); - if (pin) { - debugPrint(debug_, "read_vcd_activities", 1, - "%s transitions %d activity %.2f duty %.2f", - pin_name, - transition_count, - activity, - duty); - power_->setUserActivity(pin, activity, duty, - PwrActivityOrigin::user); +void +ReadVcdActivities::checkClkPeriod(const Pin *pin, + int transition_count) +{ + VcdTime time_max = vcd_.timeMax(); + float sim_period = time_max * vcd_.timeUnitScale() / ((transition_count - 1) / 2.0); + + ClockSet *clks = sdc_->findLeafPinClocks(pin); + if (clks) { + for (Clock *clk : *clks) { + //printf("%.2e %.2e\n", clk->period(), sim_period); + } } } diff --git a/power/Vcd.cc b/power/Vcd.cc index e9990cd1..3fe8d808 100644 --- a/power/Vcd.cc +++ b/power/Vcd.cc @@ -29,7 +29,50 @@ Vcd::Vcd(StaState *sta) : { } -//////////////////////////////////////////////////////////////// +Vcd::Vcd(const Vcd &vcd) : + StaState(vcd), + date_(vcd.date_), + comment_(vcd.comment_), + version_(vcd.version_), + time_scale_(vcd.time_scale_), + time_unit_(vcd.time_unit_), + time_unit_scale_(vcd.time_unit_scale_), + vars_(vcd.vars_), + var_name_map_(vcd.var_name_map_), + max_var_name_length_(vcd.max_var_name_length_), + max_var_width_(vcd.max_var_width_), + id_values_map_(vcd.id_values_map_), + min_delta_time_(vcd.min_delta_time_), + time_max_(vcd.time_max_) +{ +} + +Vcd& +Vcd::operator=(Vcd &&vcd1) +{ + date_ = vcd1.date_; + comment_ = vcd1.comment_; + version_ = vcd1.version_; + time_scale_ = vcd1.time_scale_; + time_unit_ = vcd1.time_unit_; + time_unit_scale_ = vcd1.time_unit_scale_; + vars_ = vcd1.vars_; + var_name_map_ = vcd1.var_name_map_; + max_var_name_length_ = vcd1.max_var_name_length_; + max_var_width_ = vcd1.max_var_width_; + id_values_map_ = vcd1.id_values_map_; + min_delta_time_ = vcd1.min_delta_time_; + time_max_ = vcd1.time_max_; + + vcd1.vars_.clear(); + return *this; +} + +Vcd::~Vcd() +{ + for (VcdVar *var : vars_) + delete var; +} void Vcd::setTimeUnit(const string &time_unit, @@ -72,7 +115,7 @@ Vcd::setMinDeltaTime(VcdTime min_delta_time) void Vcd::setTimeMax(VcdTime time_max) { - time_max_ = time_max; + time_max_ = time_max; } void @@ -81,13 +124,21 @@ Vcd::makeVar(string &name, int width, string &id) { - vars_.push_back(VcdVar(name, type, width, id)); + VcdVar *var = new VcdVar(name, type, width, id); + vars_.push_back(var); + var_name_map_[name] = var; 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(); } +VcdVar * +Vcd::var(const string name) +{ + return var_name_map_[name]; +} + bool Vcd::varIdValid(string &id) { @@ -113,17 +164,17 @@ Vcd::varAppendBusValue(string &id, } VcdValues & -Vcd::values(VcdVar &var) +Vcd::values(VcdVar *var) { - if (id_values_map_.find(var.id()) == id_values_map_.end()) { + 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()); + var->name().c_str(), + var->id().c_str()); static VcdValues empty; return empty; } else - return id_values_map_[var.id()]; + return id_values_map_[var->id()]; } //////////////////////////////////////////////////////////////// diff --git a/power/Vcd.hh b/power/Vcd.hh index 2d859c19..ea3c376b 100644 --- a/power/Vcd.hh +++ b/power/Vcd.hh @@ -36,6 +36,7 @@ class VcdValue; typedef vector VcdValues; typedef int64_t VcdTime; typedef vector VcdScope; +typedef map VcdNameMap; enum class VcdVarType { wire, reg, parameter, real }; @@ -43,7 +44,12 @@ class Vcd : public StaState { public: Vcd(StaState *sta); - VcdValues &values(VcdVar &var); + Vcd(const Vcd &vcd); + // Move copy assignment. + Vcd& operator=(Vcd &&vcd1); + ~Vcd(); + VcdVar *var(const string name); + VcdValues &values(VcdVar *var); const string &date() const { return date_; } void setDate(const string &date); @@ -61,7 +67,7 @@ public: void setTimeMax(VcdTime time_max); VcdTime minDeltaTime() const { return min_delta_time_; } void setMinDeltaTime(VcdTime min_delta_time); - vector vars() { return vars_; } + vector vars() { return vars_; } void makeVar(string &name, VcdVarType type, int width, @@ -84,7 +90,8 @@ private: string time_unit_; double time_unit_scale_; - vector vars_; + vector vars_; + VcdNameMap var_name_map_; size_t max_var_name_length_; int max_var_width_; map id_values_map_; diff --git a/power/VcdReader.cc b/power/VcdReader.cc index 35d833b3..b1fcfbe3 100644 --- a/power/VcdReader.cc +++ b/power/VcdReader.cc @@ -344,11 +344,11 @@ reportWaveforms(Vcd &vcd, int time_delta = vcd.minDeltaTime(); int max_var_name_length = vcd.maxVarNameLength(); - for (VcdVar &var : vcd.vars()) { + for (VcdVar *var : vcd.vars()) { string line; stringPrint(line, " %-*s", static_cast(max_var_name_length), - var.name().c_str()); + var->name().c_str()); const VcdValues &var_values = vcd.values(var); if (!var_values.empty()) { size_t value_index = 0; @@ -367,7 +367,7 @@ reportWaveforms(Vcd &vcd, // 01UZX char value = var_value.value(); char prev_value = prev_var_value.value(); - if (var.width() == 1) { + if (var->width() == 1) { if (value == '0' || value == '1') { for (int z = 0; z < zoom; z++) { if (z == 0 @@ -404,4 +404,25 @@ reportWaveforms(Vcd &vcd, } } +void +reportVcdVarValues(const char *filename, + const char *var_name, + StaState *sta) +{ + Vcd vcd = readVcdFile(filename, sta); + VcdVar *var = vcd.var(var_name); + if (var) { + Report *report = sta->report(); + for (const VcdValue &var_value : vcd.values(var)) { + double time = var_value.time() * vcd.timeUnitScale(); + char value = var_value.value(); + if (value == '\0') + report->reportLine("%.2e %llu", + time, var_value.busValue()); + else + report->reportLine("%.2e %c", time, value); + } + } +} + } diff --git a/power/VcdReader.hh b/power/VcdReader.hh index d20c1017..87779eef 100644 --- a/power/VcdReader.hh +++ b/power/VcdReader.hh @@ -30,4 +30,10 @@ void reportVcdWaveforms(const char *filename, StaState *sta); -} +void +reportVcdVarValues(const char *filename, + const char *var_name, + StaState *sta); + +} // namespace +