theory StarForth_Loop7_Heartrate imports StarForth_Base begin (* ========================================================================= StarForth_Loop7_Heartrate — Adaptive Heartrate (Physics Loop #7) Mirrors: src/vm_time.c (heartbeat thread, tick_target_ns updates) include/vm.h (HeartbeatState.tick_target_ns) The heartbeat thread wakes on a nanosecond timer (tick_target_ns cadence). Loop #7 adjusts tick_target_ns based on observed jitter and load: • If ticks are arriving too slowly (jitter > threshold), shorten period. • If ticks arrive fast enough, lengthen period to save CPU. Invariants: • tick_target_ns > 0 at all times. • tick_target_ns ∈ [TICK_MIN_NS, TICK_MAX_NS]. • hb_tick_count increases monotonically. ======================================================================== *) (* ========================================================================= Section 1: Heartrate bounds ======================================================================== *) (* Minimum tick period: 100 μs = 100,000 ns (matches HEARTBEAT_WINDOW_TUNING_FREQUENCY comment: tune every 1000 ticks, implying a ~1ms default tick period). *) definition TICK_MIN_NS :: nat where "TICK_MIN_NS = 100000" \ \100 μs\ definition TICK_MAX_NS :: nat where "TICK_MAX_NS = 100000000" \ \100 ms\ definition TICK_DEFAULT_NS :: nat where "TICK_DEFAULT_NS = 1000000" \ \1 ms\ lemma tick_min_pos: "TICK_MIN_NS > 0" by (simp add: TICK_MIN_NS_def) lemma tick_default_in_range: "TICK_MIN_NS \ TICK_DEFAULT_NS \ TICK_DEFAULT_NS \ TICK_MAX_NS" by (simp add: TICK_MIN_NS_def TICK_DEFAULT_NS_def TICK_MAX_NS_def) (* ========================================================================= Section 2: Heartbeat state well-formedness ======================================================================== *) definition hb_state_wf :: "heartbeat_state \ bool" where "hb_state_wf hb \ hb_tick_target_ns hb \ TICK_MIN_NS \ hb_tick_target_ns hb \ TICK_MAX_NS \ hb_tick_target_ns hb > 0" lemma hb_state_wf_pos: assumes "hb_state_wf hb" shows "hb_tick_target_ns hb > 0" using assms by (simp add: hb_state_wf_def) lemma hb_state_wf_lb: assumes "hb_state_wf hb" shows "hb_tick_target_ns hb \ TICK_MIN_NS" using assms by (simp add: hb_state_wf_def) lemma hb_state_wf_ub: assumes "hb_state_wf hb" shows "hb_tick_target_ns hb \ TICK_MAX_NS" using assms by (simp add: hb_state_wf_def) (* ========================================================================= Section 3: Tick period adjustment ======================================================================== *) (* Shorten tick period (increase tick rate) — saturate at TICK_MIN_NS. *) definition hb_shorten_period :: "nat \ heartbeat_state \ heartbeat_state" where "hb_shorten_period delta hb = hb\hb_tick_target_ns := max TICK_MIN_NS (hb_tick_target_ns hb - delta)\" (* Lengthen tick period (decrease tick rate) — saturate at TICK_MAX_NS. *) definition hb_lengthen_period :: "nat \ heartbeat_state \ heartbeat_state" where "hb_lengthen_period delta hb = hb\hb_tick_target_ns := min TICK_MAX_NS (hb_tick_target_ns hb + delta)\" lemma hb_shorten_lb: "hb_tick_target_ns (hb_shorten_period delta hb) \ TICK_MIN_NS" by (simp add: hb_shorten_period_def) lemma hb_shorten_pos: "hb_tick_target_ns (hb_shorten_period delta hb) > 0" using tick_min_pos by (simp add: hb_shorten_period_def) lemma hb_shorten_preserves_wf: assumes "hb_state_wf hb" shows "hb_state_wf (hb_shorten_period delta hb)" using assms by (simp add: hb_state_wf_def hb_shorten_period_def TICK_MAX_NS_def TICK_MIN_NS_def) lemma hb_lengthen_ub: "hb_tick_target_ns (hb_lengthen_period delta hb) \ TICK_MAX_NS" by (simp add: hb_lengthen_period_def) lemma hb_lengthen_preserves_pos: assumes "hb_tick_target_ns hb > 0" shows "hb_tick_target_ns (hb_lengthen_period delta hb) > 0" using assms by (simp add: hb_lengthen_period_def) lemma hb_lengthen_preserves_wf: assumes "hb_state_wf hb" shows "hb_state_wf (hb_lengthen_period delta hb)" using assms by (simp add: hb_state_wf_def hb_lengthen_period_def TICK_MIN_NS_def TICK_MAX_NS_def) (* ========================================================================= Section 4: Tick counter monotonicity ======================================================================== *) definition hb_fire_tick :: "heartbeat_state \ heartbeat_state" where "hb_fire_tick hb = hb\hb_tick_count := hb_tick_count hb + 1\" lemma hb_fire_tick_count_increases: "hb_tick_count (hb_fire_tick hb) = hb_tick_count hb + 1" by (simp add: hb_fire_tick_def) lemma hb_fire_tick_count_monotone: "hb_tick_count (hb_fire_tick hb) \ hb_tick_count hb" by (simp add: hb_fire_tick_def) lemma hb_fire_tick_preserves_target: "hb_tick_target_ns (hb_fire_tick hb) = hb_tick_target_ns hb" by (simp add: hb_fire_tick_def) lemma hb_fire_tick_preserves_wf: assumes "hb_state_wf hb" shows "hb_state_wf (hb_fire_tick hb)" using assms by (simp add: hb_state_wf_def hb_fire_tick_def) (* ========================================================================= Section 5: VM-level heartbeat well-formedness ======================================================================== *) lemma wf_vm_hb_pos: assumes "wf_vm vm" shows "hb_tick_target_ns (heartbeat vm) > 0" using assms by (simp add: wf_vm_def) lemma ds_word_preserves_heartbeat_wf: assumes "hb_state_wf (heartbeat vm)" shows "hb_state_wf (heartbeat (vm\data_stack := xs\))" using assms by simp end