-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathplot-execution-time-change.py
More file actions
88 lines (67 loc) · 3.7 KB
/
Copy pathplot-execution-time-change.py
File metadata and controls
88 lines (67 loc) · 3.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import matplotlib.pyplot as plt
import numpy as np
def plot_execution_time_change(f_base_hz, f_new_hz, base_cpi=1.0):
"""
Plots the % change in execution time of the new design vs. the baseline.
Parameters:
f_base_hz (float): Baseline frequency in Hz (e.g., 50_000_000 for 50 MHz).
f_new_hz (float): New frequency in Hz (e.g., 55_000_000 for 55 MHz).
base_cpi (float): The baseline Cycles Per Instruction (default is 1.0).
"""
# Create an array of potential MUL dependency percentages from 0% to 20%
x_pct = np.linspace(0, 20, 200)
# 1. Calculate New CPI for the entire array
# Every 1% of MUL dependency adds 0.01 to the CPI (due to the 1-cycle stall)
cpi_new = base_cpi + (x_pct / 100)
# 2. Calculate Execution Time Ratio: (CPI_new / CPI_base) * (F_base / F_new)
# Note: Instruction count cancels out!
time_ratio = (cpi_new / base_cpi) * (f_base_hz / f_new_hz)
# 3. Convert to Percentage Change (+ means slower, - means faster)
exec_time_change_pct = (time_ratio - 1) * 100
# Calculate the exact break-even point (where execution time change is 0%)
break_even_pct = ((f_new_hz / f_base_hz) - 1) * base_cpi * 100
# --- Plotting ---
fig, ax = plt.subplots(figsize=(10, 6))
# Plot the main trend line
ax.plot(x_pct, exec_time_change_pct, color='black', linewidth=2.8, zorder=3)
# Add a break-even horizontal line at 0%
ax.axhline(0, color='gray', linestyle='--', linewidth=1.5, zorder=2)
# Fill areas to show "Faster" vs "Slower"
ax.fill_between(x_pct, exec_time_change_pct, 0, where=(exec_time_change_pct < 0),
color='green', alpha=0.2, label='Faster')
ax.fill_between(x_pct, exec_time_change_pct, 0, where=(exec_time_change_pct > 0),
color='red', alpha=0.2, label='Slower')
# Draw dashed vertical line from break-even point to the x-axis
if 0 <= break_even_pct <= x_pct[-1]:
ymin, ymax = ax.get_ylim()
# Draw the dashed line down to the bottom
ax.vlines(x=break_even_pct, ymin=ymin, ymax=0, color='purple', linestyle='--', linewidth=1.5, zorder=4)
# Plot the point on the break-even line (0%)
ax.scatter([break_even_pct], [0], color='purple', s=90, zorder=5, label='Break-even cutoff')
# Annotate the X-axis intersection (Dependency Rate)
ax.annotate(f'{break_even_pct:.1f}%', xy=(break_even_pct, ymin),
xytext=(5, 5), textcoords='offset points', color='purple', fontweight='bold', zorder=6)
ax.set_ylim(ymin, ymax) # Lock the y-axis limits back to original bounds
# Formatting the plot
f_base_mhz = f_base_hz / 1_000_000
f_new_mhz = f_new_hz / 1_000_000
ax.set_title(f"Execution Time Impact of Removing MUL Forwarding\nBaseline: {f_base_mhz:.1f} MHz → New: {f_new_mhz:.1f} MHz",
fontsize=16, fontweight='bold')
ax.set_xlabel("MUL dependency rate (% of instructions)", fontsize=13, fontweight='bold')
ax.set_ylabel("Execution time change (%)", fontsize=13, fontweight='bold')
ax.tick_params(axis='both', labelsize=11)
# Y-axis formatter to explicitly show + or -
ax.yaxis.set_major_formatter(plt.FuncFormatter(lambda y, _: f'{y:+.1f}%'))
ax.grid(True, linestyle=':', alpha=0.7)
ax.legend(loc='upper left', fontsize=11)
plt.tight_layout()
plt.show()
# --- RUN THE SCRIPT ---
# Example Scenario:
# The baseline core ran at 66.6 MHz, and removing the forwarding path
# allowed you to hit 73.0 MHz.
if __name__ == "__main__":
plot_execution_time_change(
f_base_hz=66_600_000, # MHz baseline
f_new_hz=73_000_000 # MHz new design
)