Vcd var lookup
Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
parent
3ba89a1a9c
commit
aff6342435
BIN
doc/OpenSTA.odt
BIN
doc/OpenSTA.odt
Binary file not shown.
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<float>(high_time) / time_max;
|
||||
float activity = transition_count
|
||||
duty = static_cast<float>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
67
power/Vcd.cc
67
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()];
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
|
|
|||
13
power/Vcd.hh
13
power/Vcd.hh
|
|
@ -36,6 +36,7 @@ class VcdValue;
|
|||
typedef vector<VcdValue> VcdValues;
|
||||
typedef int64_t VcdTime;
|
||||
typedef vector<string> VcdScope;
|
||||
typedef map<string, VcdVar*> 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<VcdVar> vars() { return vars_; }
|
||||
vector<VcdVar*> vars() { return vars_; }
|
||||
void makeVar(string &name,
|
||||
VcdVarType type,
|
||||
int width,
|
||||
|
|
@ -84,7 +90,8 @@ private:
|
|||
string time_unit_;
|
||||
double time_unit_scale_;
|
||||
|
||||
vector<VcdVar> vars_;
|
||||
vector<VcdVar*> vars_;
|
||||
VcdNameMap var_name_map_;
|
||||
size_t max_var_name_length_;
|
||||
int max_var_width_;
|
||||
map<string, VcdValues> id_values_map_;
|
||||
|
|
|
|||
|
|
@ -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<int>(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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -30,4 +30,10 @@ void
|
|||
reportVcdWaveforms(const char *filename,
|
||||
StaState *sta);
|
||||
|
||||
}
|
||||
void
|
||||
reportVcdVarValues(const char *filename,
|
||||
const char *var_name,
|
||||
StaState *sta);
|
||||
|
||||
} // namespace
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue