github.com/jflude/taocp@v0.0.0-20240210234939-99f2a91af3c2/mix/interrupt.go (about) 1 package mix 2 3 import "container/heap" 4 5 const tickRate = 1000 6 7 // see Ex. 18, Section 1.4.4 8 func (c *Computer) checkInterrupt(currentState bool) { 9 if c.ctrl != currentState { 10 if c.ctrl { 11 c.saveRegs() 12 c.next = -12 13 } else { 14 c.loadRegs() 15 } 16 return 17 } 18 if since := c.Elapsed - c.lastTick; since >= tickRate { 19 c.checkInterlock(-10, -10) 20 prev := int64(c.Contents[mBase-10].Int()) 21 now := prev - since/tickRate 22 if prev > 0 && now <= 0 { 23 c.schedule(c.lastTick+prev*tickRate, -11) 24 } 25 c.Contents[mBase-10] = NewWord(int(now)) 26 c.lastTick = c.Elapsed - c.Elapsed%tickRate 27 } 28 if !c.ctrl && c.pending.Len() > 0 && c.pending[0].when <= c.Elapsed { 29 ev := heap.Pop(&c.pending).(event) 30 c.saveRegs() 31 c.ctrl = true 32 c.next = ev.loc 33 } 34 } 35 36 func (c *Computer) saveRegs() { 37 c.checkInterlock(-9, 0) 38 copy(c.Contents[mBase-9:], c.Reg[:J]) 39 w := c.Reg[J] 40 w.SetField(Spec(0, 2), NewWord(c.next)) 41 ov := 0 42 if c.Overflow { 43 ov = 1 44 } 45 w.SetField(Spec(3, 3), NewWord(Spec(ov, c.Comparison+1))) 46 c.Contents[mBase-1] = w 47 } 48 49 func (c *Computer) loadRegs() { 50 c.checkInterlock(-9, 0) 51 copy(c.Reg[:J], c.Contents[mBase-9:]) 52 w := c.Contents[mBase-1] 53 c.Reg[J] = w.Field(Spec(4, 5)) 54 c.next = w.Field(Spec(1, 2)).Int() 55 ovci := w.Field(Spec(3, 3)).Int() 56 c.Overflow = (ovci/8 == 1) 57 c.Comparison = ovci%8 - 1 58 } 59 60 func (c *Computer) schedule(when int64, loc int) { 61 heap.Push(&c.pending, event{when, loc}) 62 }