Vcd var lookup

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2022-11-01 19:08:22 -07:00
parent 3ba89a1a9c
commit aff6342435
7 changed files with 173 additions and 44 deletions

Binary file not shown.

View File

@ -122,4 +122,12 @@ report_vcd_waveforms(const char *filename)
reportVcdWaveforms(filename, Sta::sta()); reportVcdWaveforms(filename, Sta::sta());
} }
// debugging
void
report_vcd_var_values(const char *filename,
const char *var_name)
{
reportVcdVarValues(filename, var_name, Sta::sta());
}
%} // inline %} // inline

View File

@ -28,7 +28,6 @@
namespace sta { namespace sta {
using std::min; using std::min;
using std::swap;
using std::to_string; using std::to_string;
class ReadVcdActivities : public StaState class ReadVcdActivities : public StaState
@ -41,9 +40,17 @@ public:
private: private:
void setActivities(); 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, 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 *filename_;
const char *scope_; const char *scope_;
@ -83,8 +90,6 @@ ReadVcdActivities::readActivities()
for (Clock *clk : *sta_->sdc()->clocks()) for (Clock *clk : *sta_->sdc()->clocks())
clk_period_ = min(clk->period(), clk_period_); clk_period_ = min(clk->period(), clk_period_);
//checkClkPeriods();
setActivities(); setActivities();
} }
@ -92,12 +97,12 @@ void
ReadVcdActivities::setActivities() ReadVcdActivities::setActivities()
{ {
size_t scope_length = strlen(scope_); size_t scope_length = strlen(scope_);
for (VcdVar &var : vcd_.vars()) { for (VcdVar *var : vcd_.vars()) {
const VcdValues &var_values = vcd_.values(var); const VcdValues &var_values = vcd_.values(var);
if (!var_values.empty() if (!var_values.empty()
&& (var.type() == VcdVarType::wire && (var->type() == VcdVarType::wire
|| var.type() == VcdVarType::reg)) { || var->type() == VcdVarType::reg)) {
string var_name = var.name(); string var_name = var->name();
// string::starts_with in c++20 // string::starts_with in c++20
if (scope_length if (scope_length
&& var_name.substr(0, scope_length) == scope_) && var_name.substr(0, scope_length) == scope_)
@ -106,8 +111,8 @@ ReadVcdActivities::setActivities()
var_name += ' '; var_name += ' ';
const char *sta_name = verilogToSta(var_name.c_str()); const char *sta_name = verilogToSta(var_name.c_str());
if (var.width() == 1) if (var->width() == 1)
findVarActivity(sta_name, 0, var_values); setVarActivity(sta_name, var_values, 0);
else { else {
char *bus_name; char *bus_name;
int from, to; int from, to;
@ -120,7 +125,7 @@ ReadVcdActivities::setActivities()
pin_name += '['; pin_name += '[';
pin_name += to_string(bus_bit); pin_name += to_string(bus_bit);
pin_name += ']'; pin_name += ']';
findVarActivity(pin_name.c_str(), value_bit, var_values); setVarActivity(pin_name.c_str(), var_values, value_bit);
value_bit++; value_bit++;
} }
} }
@ -130,7 +135,7 @@ ReadVcdActivities::setActivities()
pin_name += '['; pin_name += '[';
pin_name += to_string(bus_bit); pin_name += to_string(bus_bit);
pin_name += ']'; pin_name += ']';
findVarActivity(pin_name.c_str(), value_bit, var_values); setVarActivity(pin_name.c_str(), var_values, value_bit);
value_bit++; value_bit++;
} }
} }
@ -140,11 +145,39 @@ ReadVcdActivities::setActivities()
} }
void void
ReadVcdActivities::findVarActivity(const char *pin_name, ReadVcdActivities::setVarActivity(const char *pin_name,
int value_bit, const VcdValues &var_values,
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(); char prev_value = var_values[0].value();
VcdTime prev_time = var_values[0].time(); VcdTime prev_time = var_values[0].time();
VcdTime high_time = 0; VcdTime high_time = 0;
@ -164,20 +197,23 @@ ReadVcdActivities::findVarActivity(const char *pin_name,
VcdTime time_max = vcd_.timeMax(); VcdTime time_max = vcd_.timeMax();
if (prev_value == '1') if (prev_value == '1')
high_time += time_max - prev_time; high_time += time_max - prev_time;
float duty = static_cast<float>(high_time) / time_max; duty = static_cast<float>(high_time) / time_max;
float activity = transition_count activity = transition_count
/ (time_max * vcd_.timeUnitScale() / clk_period_); / (time_max * vcd_.timeUnitScale() / clk_period_);
}
Pin *pin = network_->findPin(pin_name); void
if (pin) { ReadVcdActivities::checkClkPeriod(const Pin *pin,
debugPrint(debug_, "read_vcd_activities", 1, int transition_count)
"%s transitions %d activity %.2f duty %.2f", {
pin_name, VcdTime time_max = vcd_.timeMax();
transition_count, float sim_period = time_max * vcd_.timeUnitScale() / ((transition_count - 1) / 2.0);
activity,
duty); ClockSet *clks = sdc_->findLeafPinClocks(pin);
power_->setUserActivity(pin, activity, duty, if (clks) {
PwrActivityOrigin::user); for (Clock *clk : *clks) {
//printf("%.2e %.2e\n", clk->period(), sim_period);
}
} }
} }

View File

@ -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 void
Vcd::setTimeUnit(const string &time_unit, Vcd::setTimeUnit(const string &time_unit,
@ -72,7 +115,7 @@ Vcd::setMinDeltaTime(VcdTime min_delta_time)
void void
Vcd::setTimeMax(VcdTime time_max) Vcd::setTimeMax(VcdTime time_max)
{ {
time_max_ = time_max; time_max_ = time_max;
} }
void void
@ -81,13 +124,21 @@ Vcd::makeVar(string &name,
int width, int width,
string &id) 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_name_length_ = std::max(max_var_name_length_, name.size());
max_var_width_ = std::max(max_var_width_, width); max_var_width_ = std::max(max_var_width_, width);
// Make entry for var ID. // Make entry for var ID.
id_values_map_[id].clear(); id_values_map_[id].clear();
} }
VcdVar *
Vcd::var(const string name)
{
return var_name_map_[name];
}
bool bool
Vcd::varIdValid(string &id) Vcd::varIdValid(string &id)
{ {
@ -113,17 +164,17 @@ Vcd::varAppendBusValue(string &id,
} }
VcdValues & 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", report_->error(805, "Unknown variable %s ID %s",
var.name().c_str(), var->name().c_str(),
var.id().c_str()); var->id().c_str());
static VcdValues empty; static VcdValues empty;
return empty; return empty;
} }
else else
return id_values_map_[var.id()]; return id_values_map_[var->id()];
} }
//////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////

View File

@ -36,6 +36,7 @@ class VcdValue;
typedef vector<VcdValue> VcdValues; typedef vector<VcdValue> VcdValues;
typedef int64_t VcdTime; typedef int64_t VcdTime;
typedef vector<string> VcdScope; typedef vector<string> VcdScope;
typedef map<string, VcdVar*> VcdNameMap;
enum class VcdVarType { wire, reg, parameter, real }; enum class VcdVarType { wire, reg, parameter, real };
@ -43,7 +44,12 @@ class Vcd : public StaState
{ {
public: public:
Vcd(StaState *sta); 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_; } const string &date() const { return date_; }
void setDate(const string &date); void setDate(const string &date);
@ -61,7 +67,7 @@ public:
void setTimeMax(VcdTime time_max); void setTimeMax(VcdTime time_max);
VcdTime minDeltaTime() const { return min_delta_time_; } VcdTime minDeltaTime() const { return min_delta_time_; }
void setMinDeltaTime(VcdTime min_delta_time); void setMinDeltaTime(VcdTime min_delta_time);
vector<VcdVar> vars() { return vars_; } vector<VcdVar*> vars() { return vars_; }
void makeVar(string &name, void makeVar(string &name,
VcdVarType type, VcdVarType type,
int width, int width,
@ -84,7 +90,8 @@ private:
string time_unit_; string time_unit_;
double time_unit_scale_; double time_unit_scale_;
vector<VcdVar> vars_; vector<VcdVar*> vars_;
VcdNameMap var_name_map_;
size_t max_var_name_length_; size_t max_var_name_length_;
int max_var_width_; int max_var_width_;
map<string, VcdValues> id_values_map_; map<string, VcdValues> id_values_map_;

View File

@ -344,11 +344,11 @@ reportWaveforms(Vcd &vcd,
int time_delta = vcd.minDeltaTime(); int time_delta = vcd.minDeltaTime();
int max_var_name_length = vcd.maxVarNameLength(); int max_var_name_length = vcd.maxVarNameLength();
for (VcdVar &var : vcd.vars()) { for (VcdVar *var : vcd.vars()) {
string line; string line;
stringPrint(line, " %-*s", stringPrint(line, " %-*s",
static_cast<int>(max_var_name_length), static_cast<int>(max_var_name_length),
var.name().c_str()); var->name().c_str());
const VcdValues &var_values = vcd.values(var); const VcdValues &var_values = vcd.values(var);
if (!var_values.empty()) { if (!var_values.empty()) {
size_t value_index = 0; size_t value_index = 0;
@ -367,7 +367,7 @@ reportWaveforms(Vcd &vcd,
// 01UZX // 01UZX
char value = var_value.value(); char value = var_value.value();
char prev_value = prev_var_value.value(); char prev_value = prev_var_value.value();
if (var.width() == 1) { if (var->width() == 1) {
if (value == '0' || value == '1') { if (value == '0' || value == '1') {
for (int z = 0; z < zoom; z++) { for (int z = 0; z < zoom; z++) {
if (z == 0 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);
}
}
}
} }

View File

@ -30,4 +30,10 @@ void
reportVcdWaveforms(const char *filename, reportVcdWaveforms(const char *filename,
StaState *sta); StaState *sta);
} void
reportVcdVarValues(const char *filename,
const char *var_name,
StaState *sta);
} // namespace