vcd x/z transitions count as 1/2

Signed-off-by: James Cherry <cherry@parallaxsw.com>
This commit is contained in:
James Cherry 2022-11-02 18:17:04 -07:00
parent 16ae589193
commit bbc0495ebd
1 changed files with 30 additions and 21 deletions

View File

@ -46,18 +46,20 @@ private:
void findVarActivity(const VcdValues &var_values, void findVarActivity(const VcdValues &var_values,
int value_bit, int value_bit,
// Return values. // Return values.
int &transition_count, double &transition_count,
float &activity, double &activity,
float &duty); double &duty);
void checkClkPeriod(const Pin *pin, void checkClkPeriod(const Pin *pin,
int transition_count); double transition_count);
const char *filename_; const char *filename_;
const char *scope_; const char *scope_;
Vcd vcd_; Vcd vcd_;
float clk_period_; double clk_period_;
Sta *sta_; Sta *sta_;
Power *power_; Power *power_;
static constexpr double sim_clk_period_tolerance_ = .1;
}; };
void void
@ -88,7 +90,7 @@ ReadVcdActivities::readActivities()
clk_period_ = INF; clk_period_ = INF;
for (Clock *clk : *sta_->sdc()->clocks()) for (Clock *clk : *sta_->sdc()->clocks())
clk_period_ = min(clk->period(), clk_period_); clk_period_ = min(static_cast<double>(clk->period()), clk_period_);
setActivities(); setActivities();
} }
@ -151,12 +153,11 @@ ReadVcdActivities::setVarActivity(const char *pin_name,
{ {
const Pin *pin = network_->findPin(pin_name); const Pin *pin = network_->findPin(pin_name);
if (pin) { if (pin) {
int transition_count; double transition_count, activity, duty;
float activity, duty;
findVarActivity(var_values, value_bit, findVarActivity(var_values, value_bit,
transition_count, activity, duty); transition_count, activity, duty);
debugPrint(debug_, "read_vcd_activities", 1, debugPrint(debug_, "read_vcd_activities", 1,
"%s transitions %d activity %.2f duty %.2f", "%s transitions %.1f activity %.2f duty %.2f",
pin_name, pin_name,
transition_count, transition_count,
activity, activity,
@ -173,11 +174,11 @@ void
ReadVcdActivities::findVarActivity(const VcdValues &var_values, ReadVcdActivities::findVarActivity(const VcdValues &var_values,
int value_bit, int value_bit,
// Return values. // Return values.
int &transition_count, double &transition_count,
float &activity, double &activity,
float &duty) double &duty)
{ {
transition_count = 0; transition_count = 0.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;
@ -191,32 +192,40 @@ ReadVcdActivities::findVarActivity(const VcdValues &var_values,
if (prev_value == '1') if (prev_value == '1')
high_time += time - prev_time; high_time += time - prev_time;
if (value != prev_value) if (value != prev_value)
transition_count++; transition_count += (value == 'X'
|| value == 'Z'
|| prev_value == 'X'
|| prev_value == 'Z')
? .5
: 1.0;
prev_time = time; prev_time = time;
prev_value = value; prev_value = value;
} }
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;
duty = static_cast<float>(high_time) / time_max; duty = static_cast<double>(high_time) / time_max;
activity = transition_count activity = transition_count
/ (time_max * vcd_.timeUnitScale() / clk_period_); / (time_max * vcd_.timeUnitScale() / clk_period_);
} }
void void
ReadVcdActivities::checkClkPeriod(const Pin *pin, ReadVcdActivities::checkClkPeriod(const Pin *pin,
int transition_count) double transition_count)
{ {
VcdTime time_max = vcd_.timeMax(); VcdTime time_max = vcd_.timeMax();
float sim_period = time_max * vcd_.timeUnitScale() / ((transition_count - 1) / 2.0); double sim_period = time_max * vcd_.timeUnitScale() / (transition_count / 2.0);
ClockSet *clks = sdc_->findLeafPinClocks(pin); ClockSet *clks = sdc_->findLeafPinClocks(pin);
if (clks) { if (clks) {
for (Clock *clk : *clks) { for (Clock *clk : *clks) {
report_->warn(806, "clock %s vcd period %s differs from clock definition %s", 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(806, "clock %s vcd period %s differs from SDC clock period %s",
clk->name(), clk->name(),
delayAsString(clk->period(), this), delayAsString(sim_period, this),
delayAsString(sim_period, this)); delayAsString(clk_period, this));
} }
} }
} }