commit 9beb46c3b84eb98217324f06fb4a752e23665930
parent 46947c53efa2dd716ba099327a0515215edd40dd
Author: Sylvia Ivory <git@sivory.net>
Date: Thu, 22 Jan 2026 20:15:55 -0800
Add profiler lab (needs new root)
Diffstat:
3 files changed, 60 insertions(+), 44 deletions(-)
diff --git a/src/devices/timer.zig b/src/devices/timer.zig
@@ -100,6 +100,10 @@ noinline fn timer_handler(pc: usize) void {
mem.barrier(.Write); // Sync before restoring
}
+pub inline fn set_tick(tick: *const fn (usize) void) void {
+ tick_fn = tick;
+}
+
pub inline fn get_count() u32 {
return count;
}
diff --git a/src/labs/4-profiler.zig b/src/labs/4-profiler.zig
@@ -0,0 +1,55 @@
+const std = @import("std");
+const interrupts = @import("pi").interrupts;
+
+const uart = @import("devices/mini-uart.zig");
+const clock = @import("devices/clock.zig");
+const timer = @import("devices/timer.zig");
+
+// 1Mb
+var buffer: [1024 * 1024]u8 = undefined;
+var fba: std.heap.FixedBufferAllocator = undefined;
+var hist: std.AutoHashMap(usize, usize) = undefined;
+var enabled = true;
+
+extern const __code_start__: u32;
+extern const __code_end__: u32;
+
+fn tick(pc: usize) void {
+ if (!enabled) return;
+
+ const res = hist.getOrPutValue(pc, 0) catch unreachable;
+ const new_value = res.value_ptr.* + 1;
+
+ hist.put(pc, new_value) catch unreachable;
+}
+
+fn dump(min: usize) void {
+ enabled = false;
+ uart.writer.print("call profile:\n", .{}) catch {};
+ var iterator = hist.iterator();
+
+ while (iterator.next()) |entry| {
+ if (entry.value_ptr.* < min) continue;
+ uart.writer.print(" 0x{X}: {d}\n", .{ entry.key_ptr.*, entry.value_ptr.* }) catch {};
+ }
+ enabled = true;
+}
+
+pub fn main() !void {
+ timer.initialize(.Sixteen, 0x100);
+ timer.set_tick(tick);
+
+ fba = .init(&buffer);
+ hist = .init(fba.allocator());
+
+ interrupts.enable_interrupts();
+
+ var iter: usize = 0;
+ while (timer.get_count() < 200) {
+ try uart.writer.print("iter={d}: count = {d}, period = {d}us, 0x{x}\n", .{ iter, timer.get_count(), timer.get_period(), timer.get_period() });
+ iter += 1;
+ if (iter % 10 == 0) {
+ dump(2);
+ }
+ }
+}
diff --git a/src/main.zig b/src/main.zig
@@ -1,44 +1 @@
-const interrupts = @import("pi").interrupts;
-
-const uart = @import("devices/mini-uart.zig");
-const clock = @import("devices/clock.zig");
-const timer = @import("devices/timer.zig");
-
-pub fn main() !void {
- try uart.writer.print("entered main safely...\n", .{});
-
- timer.initialize(.Sixteen, 0x100);
-
- try uart.writer.print("initialized timer...\n", .{});
-
- interrupts.enable_interrupts();
-
- try uart.writer.print("enabled interrupts...\n", .{});
-
- const start = clock.current_count();
- var iter: u32 = 0;
- const N = 20;
-
- while (timer.get_count() < N) {
- try uart.writer.print("iter={d}: count={d}, time between interrupts = {d} usec (0x{x})\n", .{
- iter,
- timer.get_count(),
- timer.get_period(),
- timer.get_period(),
- });
- iter += 1;
- }
-
- const total = clock.current_count() - start;
- const total_sec = total / (1000 * 1000);
- const total_ms = (total / 1000) % 10000;
- const total_us = (total % 1000);
-
- try uart.writer.print(
- \\ total iterations: {}
- \\ total interrupts: {}
- \\ iterations / interrupt: {}
- \\ average period: {}
- \\ total execution time: {}s.{}ms.{}us
- , .{ iter, N, iter / N, timer.get_period_sum() / (N - 1), total_sec, total_ms, total_us });
-}
+fn main() void {}