diff options
Diffstat (limited to 'src/pardes/app.zig')
| -rw-r--r-- | src/pardes/app.zig | 26 |
1 files changed, 24 insertions, 2 deletions
diff --git a/src/pardes/app.zig b/src/pardes/app.zig index 23da203..2f13865 100644 --- a/src/pardes/app.zig +++ b/src/pardes/app.zig @@ -101,6 +101,11 @@ extern fn pardes_p4_wants_frame() callconv(.c) bool; /// Has the user asked to leave? There is nowhere to go, so this only stops the loop. extern fn pardes_p4_quit() callconv(.c) bool; +/// The last frame's three stages in CPU cycles: the copy of pardes's Surface into vaxis's grid, +/// vaxis's own diff-and-emit, and the push into the UART. Only meaningful under `-Dprof`; the +/// editor object always exports it, and it costs two CSR reads per stage. +extern fn pardes_p4_frame_prof(copy: *u64, render: *u64, flush: *u64) callconv(.c) void; + // ------------------------------------------------------------------------------------ the sink /// The write callback handed to `pardes_p4_init`. No context is needed - there is one UART. @@ -230,11 +235,28 @@ export fn zig_main() noreturn { if (err != 0) soc.rom.print("MARK PARDES_RENDER_FAIL rc=%u\r\n", .{err}); if (prof) { const render_cy = soc.cycles() - t0; + // A SECOND render with nothing changed since the first. It splits the cost in two: + // whatever this still costs is the price of walking and diffing the whole editor + // state, paid regardless of output, while the difference between the two is the + // price of the change itself. `wants_frame` is false now, so this only happens + // under -Dprof and never on a shipping build. + const t1 = soc.cycles(); + _ = pardes_p4_render(); + const idle_cy = soc.cycles() - t1; // Reported in cycles, not microseconds: the divisor is the CPU clock, which this // firmware does not set and has only ever measured, so converting here would bake a // guess into the data. `experiments/` divides by the clock it measured. - soc.rom.print("PROF in=%u render=%u\r\n", .{ - @as(u32, @intCast(input_cy)), @as(u32, @intCast(render_cy)), + var copy_cy: u64 = 0; + var vx_cy: u64 = 0; + var flush_cy: u64 = 0; + pardes_p4_frame_prof(©_cy, &vx_cy, &flush_cy); + soc.rom.print("PROF in=%u render=%u idle=%u copy=%u vaxis=%u flush=%u\r\n", .{ + @as(u32, @intCast(input_cy)), + @as(u32, @intCast(render_cy)), + @as(u32, @intCast(idle_cy)), + @as(u32, @intCast(copy_cy)), + @as(u32, @intCast(vx_cy)), + @as(u32, @intCast(flush_cy)), }); } } |
