Skip to content

Commit c7728b8

Browse files
committed
Recalibrate timer coefficient after MMU cache
After MMU cache optimization (8×2 set-associative, 99%+ hit rate), CPU execution became faster, reducing timer calls by 18.9%. Update coefficient from 2.15e8 to 1.744e8 based on measurements. Add calibration statistics (enabled via SEMU_TIMER_STATS) to help future recalibration if needed.
1 parent 8d8e6b3 commit c7728b8

File tree

1 file changed

+53
-4
lines changed

1 file changed

+53
-4
lines changed

utils.c

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
#include <math.h>
12
#include <stdbool.h>
3+
#include <stdio.h>
24
#include <time.h>
35

46
#include "utils.h"
@@ -24,6 +26,10 @@ bool boot_complete = false;
2426
static double ticks_increment;
2527
static double boot_ticks;
2628

29+
/* Timer calibration statistics */
30+
static uint64_t timer_call_count = 0;
31+
static int timer_n_harts = 1;
32+
2733
/* Calculate "x * n / d" without unnecessary overflow or loss of precision.
2834
*
2935
* Reference:
@@ -88,6 +94,7 @@ static uint64_t semu_timer_clocksource(semu_timer_t *timer)
8894
static bool first_switch = true;
8995

9096
if (!boot_complete) {
97+
timer_call_count++;
9198
boot_ticks += ticks_increment;
9299
return (uint64_t) boot_ticks;
93100
}
@@ -98,6 +105,34 @@ static uint64_t semu_timer_clocksource(semu_timer_t *timer)
98105

99106
/* Calculate the offset between the real time and the emulator time */
100107
offset = (int64_t) (real_ticks - boot_ticks);
108+
109+
#ifdef SEMU_TIMER_STATS
110+
/* Output timer calibration statistics (only when SEMU_TIMER_STATS is
111+
* defined) */
112+
double actual_coefficient = (double) timer_call_count / timer_n_harts;
113+
double current_coefficient = 1.744e8;
114+
double recommended_coefficient = actual_coefficient;
115+
116+
fprintf(stderr, "\n[Timer Calibration Statistics]\n");
117+
fprintf(stderr, " Boot completed after %llu timer calls\n",
118+
(unsigned long long) timer_call_count);
119+
fprintf(stderr, " Number of harts: %d\n", timer_n_harts);
120+
fprintf(stderr, " Actual coefficient: %.3e (%.2f calls per hart)\n",
121+
actual_coefficient, actual_coefficient);
122+
fprintf(stderr, " Current coefficient: %.3e\n", current_coefficient);
123+
fprintf(stderr, " Difference: %.2f%% %s\n",
124+
fabs(actual_coefficient - current_coefficient) /
125+
current_coefficient * 100.0,
126+
actual_coefficient > current_coefficient ? "(more calls)"
127+
: "(fewer calls)");
128+
fprintf(stderr, "\n[Recommendation]\n");
129+
fprintf(stderr, " Update utils.c line 121 to:\n");
130+
fprintf(stderr,
131+
" ticks_increment = (SEMU_BOOT_TARGET_TIME * CLOCK_FREQ) / "
132+
"(%.3e * n_harts);\n",
133+
recommended_coefficient);
134+
fprintf(stderr, "\n");
135+
#endif
101136
}
102137
return (uint64_t) ((int64_t) real_ticks - offset);
103138
}
@@ -108,14 +143,28 @@ void semu_timer_init(semu_timer_t *timer, uint64_t freq, int n_harts)
108143
timer->begin = mult_frac(host_time_ns(), timer->freq, 1e9);
109144
boot_ticks = timer->begin; /* Initialize the fake ticks for boot process */
110145

146+
/* Store n_harts for calibration statistics */
147+
timer_n_harts = n_harts;
148+
111149
/* According to statistics, the number of times 'semu_timer_clocksource'
112-
* called is approximately 'SMP count * 2.15 * 1e8'. By the time the boot
150+
* called is approximately 'SMP count * 1.744 * 1e8'. By the time the boot
113151
* process is completed, the emulator will have a total of 'boot seconds *
114-
* frequency' ticks. Therefore, each time, '(boot seconds * frequency) /
115-
* (2.15 * 1e8 * SMP count)' ticks need to be added.
152+
* frequency' ticks. Therefore, each time, (boot seconds * frequency) /
153+
* (1.744 * 1e8 * SMP count) ticks need to be added.
154+
*
155+
* Note: This coefficient was recalibrated after MMU cache optimization
156+
* (8×2 set-associative with 99%+ hit rate). The original coefficient
157+
* (2.15 * 1e8) was based on measurements before the optimization. With
158+
* faster CPU execution, fewer timer calls are needed to complete boot.
159+
*
160+
* Calibration history:
161+
* - Original (pre-MMU cache): 2.15 × 10^8
162+
* - After MMU cache (measured): 1.696 × 10^8 (-21.1%)
163+
* - Verification measurement: 1.744 × 10^8 (error: 2.85%)
164+
* - Final coefficient: 1.744 × 10^8 (based on verification)
116165
*/
117166
ticks_increment =
118-
(SEMU_BOOT_TARGET_TIME * CLOCK_FREQ) / (2.15 * 1e8 * n_harts);
167+
(SEMU_BOOT_TARGET_TIME * CLOCK_FREQ) / (1.744 * 1e8 * n_harts);
119168
}
120169

121170
uint64_t semu_timer_get(semu_timer_t *timer)

0 commit comments

Comments
 (0)