OpenSTA/power/ReadVcdActivities.cc

259 lines
7.7 KiB
C++
Raw Permalink Normal View History

// OpenSTA, Static Timing Analyzer
// Copyright (c) 2024, Parallax Software, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
#include "ReadVcdActivities.hh"
#include <inttypes.h>
2024-09-24 03:04:26 +02:00
#include <set>
#include "VcdReader.hh"
#include "Debug.hh"
#include "Network.hh"
#include "VerilogNamespace.hh"
#include "ParseBus.hh"
#include "Sdc.hh"
#include "Power.hh"
#include "Sta.hh"
namespace sta {
using std::abs;
using std::min;
using std::to_string;
class ReadVcdActivities : public StaState
{
public:
ReadVcdActivities(const char *filename,
const char *scope,
Sta *sta);
void readActivities();
private:
void setActivities();
void setVarActivity(VcdVar *var,
string &var_name,
const VcdValues &var_value);
void setVarActivity(const char *pin_name,
const VcdValues &var_values,
int value_bit);
void findVarActivity(const VcdValues &var_values,
int value_bit,
// Return values.
double &transition_count,
double &activity,
double &duty);
void checkClkPeriod(const Pin *pin,
double transition_count);
const char *filename_;
const char *scope_;
Vcd vcd_;
double clk_period_;
Sta *sta_;
Power *power_;
2024-09-24 03:04:26 +02:00
std::set<const Pin*> annotated_pins_;
static constexpr double sim_clk_period_tolerance_ = .1;
};
void
readVcdActivities(const char *filename,
const char *scope,
Sta *sta)
{
ReadVcdActivities reader(filename, scope, sta);
reader.readActivities();
}
ReadVcdActivities::ReadVcdActivities(const char *filename,
const char *scope,
Sta *sta) :
StaState(sta),
filename_(filename),
scope_(scope),
vcd_(sta),
clk_period_(0.0),
sta_(sta),
power_(sta->power())
{
}
void
ReadVcdActivities::readActivities()
{
vcd_ = readVcdFile(filename_, sta_);
clk_period_ = INF;
for (Clock *clk : *sta_->sdc()->clocks())
clk_period_ = min(static_cast<double>(clk->period()), clk_period_);
if (vcd_.timeMax() > 0)
setActivities();
else
report_->warn(1450, "VCD max time is zero.");
report_->reportLine("Annotated %zu pin activities.", annotated_pins_.size());
}
void
ReadVcdActivities::setActivities()
{
size_t scope_length = strlen(scope_);
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();
// string::starts_with in c++20
if (scope_length) {
if (var_name.substr(0, scope_length) == scope_) {
var_name = var_name.substr(scope_length + 1);
setVarActivity(var, var_name, var_values);
}
}
else
setVarActivity(var, var_name, var_values);
}
}
}
void
ReadVcdActivities::setVarActivity(VcdVar *var,
string &var_name,
const VcdValues &var_values)
{
if (var->width() == 1) {
string sta_name = netVerilogToSta(var_name.c_str());
rm tmp string uses commit 2d0a4f8e9a8b46faa2ba91e1be636c3c3ad95a7f Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 21:25:37 2023 -0700 leaks Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 5514910a91707d615bac0bbed3a29f579eca8de2 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 18:21:54 2023 -0700 foo Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 076a51d5816444e883232933c2ded7309291d0bc Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 16:38:42 2023 -0700 parse bus string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 2b80e563cbbb6563a6b716431f391bbb6639f816 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 15:57:05 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 9e4f2308658232d0b1ee9efcd948bb19ae5dd30f Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 14:37:35 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit ebad3afd49b08e7194452dd082c3c7c05767f875 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 10:59:11 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 69647913932312a04ca06e7a04cca17ed50d4daf Author: James Cherry <cherry@parallaxsw.com> Date: Fri Mar 24 21:02:20 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 55e67996a7b0651dbb5ee06cb89fe0410648c3c1 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 10:42:43 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 73cee43925c0d32940989c616440b4da18640121 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 09:55:17 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit eba6d1413b8d87a64a90141e5263a56eede1df51 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 09:40:16 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 95d6ed78144512a37fd7c1d3d8a62fc4c8965818 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 08:18:46 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit faf82464d7be7fd6c958a21d401fa48ece4ac341 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 07:49:11 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit cfc9064496cb6f46ec562b104bc7fff2fbc1b32e Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 07:37:12 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 057933a6ac356a7541883aa64b5109c7a0e8b8d1 Author: James Cherry <cherry@parallaxsw.com> Date: Fri Mar 24 21:02:20 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit fdeb6436a72413356a627dd1de1d8cec7fca4c4a Author: James Cherry <cherry@parallaxsw.com> Date: Fri Mar 24 19:53:44 2023 -0700 rm TmpString uses Signed-off-by: James Cherry <cherry@parallaxsw.com> Signed-off-by: James Cherry <cherry@parallaxsw.com>
2023-03-26 15:34:36 +02:00
setVarActivity(sta_name.c_str(), var_values, 0);
}
else {
bool is_bus, is_range, subscript_wild;
rm tmp string uses commit 2d0a4f8e9a8b46faa2ba91e1be636c3c3ad95a7f Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 21:25:37 2023 -0700 leaks Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 5514910a91707d615bac0bbed3a29f579eca8de2 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 18:21:54 2023 -0700 foo Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 076a51d5816444e883232933c2ded7309291d0bc Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 16:38:42 2023 -0700 parse bus string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 2b80e563cbbb6563a6b716431f391bbb6639f816 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 15:57:05 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 9e4f2308658232d0b1ee9efcd948bb19ae5dd30f Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 14:37:35 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit ebad3afd49b08e7194452dd082c3c7c05767f875 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 10:59:11 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 69647913932312a04ca06e7a04cca17ed50d4daf Author: James Cherry <cherry@parallaxsw.com> Date: Fri Mar 24 21:02:20 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 55e67996a7b0651dbb5ee06cb89fe0410648c3c1 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 10:42:43 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 73cee43925c0d32940989c616440b4da18640121 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 09:55:17 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit eba6d1413b8d87a64a90141e5263a56eede1df51 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 09:40:16 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 95d6ed78144512a37fd7c1d3d8a62fc4c8965818 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 08:18:46 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit faf82464d7be7fd6c958a21d401fa48ece4ac341 Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 07:49:11 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit cfc9064496cb6f46ec562b104bc7fff2fbc1b32e Author: James Cherry <cherry@parallaxsw.com> Date: Sat Mar 25 07:37:12 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit 057933a6ac356a7541883aa64b5109c7a0e8b8d1 Author: James Cherry <cherry@parallaxsw.com> Date: Fri Mar 24 21:02:20 2023 -0700 rm tmp string Signed-off-by: James Cherry <cherry@parallaxsw.com> commit fdeb6436a72413356a627dd1de1d8cec7fca4c4a Author: James Cherry <cherry@parallaxsw.com> Date: Fri Mar 24 19:53:44 2023 -0700 rm TmpString uses Signed-off-by: James Cherry <cherry@parallaxsw.com> Signed-off-by: James Cherry <cherry@parallaxsw.com>
2023-03-26 15:34:36 +02:00
string bus_name;
int from, to;
parseBusName(var_name.c_str(), '[', ']', '\\',
is_bus, is_range, bus_name, from, to, subscript_wild);
if (is_bus) {
string sta_bus_name = netVerilogToSta(bus_name.c_str());
int value_bit = 0;
if (to < from) {
for (int bus_bit = to; bus_bit <= from; bus_bit++) {
string pin_name = sta_bus_name;
pin_name += '[';
pin_name += to_string(bus_bit);
pin_name += ']';
setVarActivity(pin_name.c_str(), var_values, value_bit);
value_bit++;
}
}
else {
for (int bus_bit = to; bus_bit >= from; bus_bit--) {
string pin_name = sta_bus_name;
pin_name += '[';
pin_name += to_string(bus_bit);
pin_name += ']';
setVarActivity(pin_name.c_str(), var_values, value_bit);
value_bit++;
}
}
}
else
report_->warn(1451, "problem parsing bus %s.", var_name.c_str());
}
}
void
ReadVcdActivities::setVarActivity(const char *pin_name,
const VcdValues &var_values,
int value_bit)
{
const Pin *pin = sdc_network_->findPin(pin_name);
if (pin) {
debugPrint(debug_, "read_vcd_activities", 3, "%s values", pin_name);
double transition_count, activity, duty;
findVarActivity(var_values, value_bit,
transition_count, activity, duty);
debugPrint(debug_, "read_vcd_activities", 1,
"%s transitions %.1f activity %.2f duty %.2f",
pin_name,
transition_count,
activity,
duty);
if (sdc_->isLeafPinClock(pin))
checkClkPeriod(pin, transition_count);
power_->setUserActivity(pin, activity, duty, PwrActivityOrigin::vcd);
annotated_pins_.insert(pin);
}
}
void
ReadVcdActivities::findVarActivity(const VcdValues &var_values,
int value_bit,
// Return values.
double &transition_count,
double &activity,
double &duty)
{
transition_count = 0.0;
char prev_value = var_values[0].value(value_bit);
VcdTime prev_time = var_values[0].time();
VcdTime high_time = 0;
for (const VcdValue &var_value : var_values) {
VcdTime time = var_value.time();
char value = var_value.value(value_bit);
debugPrint(debug_, "read_vcd_activities", 3, " %" PRId64 " %c", time, value);
if (prev_value == '1')
high_time += time - prev_time;
if (value != prev_value)
transition_count += (value == 'X'
|| value == 'Z'
|| prev_value == 'X'
|| prev_value == 'Z')
? .5
: 1.0;
prev_time = time;
prev_value = value;
}
VcdTime time_max = vcd_.timeMax();
if (prev_value == '1')
high_time += time_max - prev_time;
duty = static_cast<double>(high_time) / time_max;
activity = transition_count / (time_max * vcd_.timeScale() / clk_period_);
}
void
ReadVcdActivities::checkClkPeriod(const Pin *pin,
double transition_count)
{
VcdTime time_max = vcd_.timeMax();
double sim_period = time_max * vcd_.timeScale() / (transition_count / 2.0);
ClockSet *clks = sdc_->findLeafPinClocks(pin);
if (clks) {
for (Clock *clk : *clks) {
double clk_period = clk->period();
if (abs((clk_period - sim_period) / clk_period) > .1)
// Warn if sim clock period differs from SDC by 10%.
report_->warn(1452, "clock %s vcd period %s differs from SDC clock period %s",
clk->name(),
delayAsString(sim_period, this),
delayAsString(clk_period, this));
}
}
}
}