diff options
| author | Julian Blake Kongslie | 2023-03-19 14:22:39 -0700 |
|---|---|---|
| committer | Julian Blake Kongslie | 2023-03-19 14:22:39 -0700 |
| commit | 7e93a297c4ac68a51b5b5847979827a8c5975ceb (patch) | |
| tree | 40287680cd9ca3edef85f0d9765958832abfa225 /spin/mi.pml | |
| parent | Fix focal 69. (diff) | |
| download | biggolf-7e93a297c4ac68a51b5b5847979827a8c5975ceb.tar.xz | |
Add various spin models, including one that might actually work.
Diffstat (limited to 'spin/mi.pml')
| -rw-r--r-- | spin/mi.pml | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/spin/mi.pml b/spin/mi.pml new file mode 100644 index 0000000..52a384e --- /dev/null +++ b/spin/mi.pml | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | // vim: set sw=3 : | ||
| 2 | |||
| 3 | mtype { | ||
| 4 | I, M, | ||
| 5 | ItoM, MtoI, // from upstream | ||
| 6 | SnoopItoM, // from downstream | ||
| 7 | Fetch, Store, | ||
| 8 | Busy, Done, Fail | ||
| 9 | } | ||
| 10 | |||
| 11 | m_type cachestate; // I, M, Busy | ||
| 12 | m_type evilstate; // I, Free, ItoM, MtoI | ||
| 13 | int evilsource; // which upstream is the evilstate "on behalf of"; -1 is downstream | ||
| 14 | int evilnotsent; // bitmask of upstreams we have not yet sent snoops to | ||
| 15 | int evilnotreplied; // bitmask of upstreams that have not yet replied to snoops | ||
| 16 | int evilnewstate; // new M/E/S/I state | ||
| 17 | |||
| 18 | evil buffer: | ||
| 19 | state | ||
| 20 | bitmask of upstreams we have not yet snooped | ||
| 21 | bitmask of upstreams that have not yet replied | ||
| 22 | source of this buffer's transaction | ||
| 23 | |||
| 24 | proctype cache() | ||
| 25 | { | ||
| 26 | do | ||
| 27 | :: i = (i + 1) % N | ||
| 28 | :: assert(cachestate == I || cachestate == M || cachestate == Busy) | ||
| 29 | :: assert(evilstate == I || evilstate == ItoM || evilstate == MtoI || evilstate == SnoopItoM || evilstate == Busy) | ||
| 30 | :: atomic { cachestate == I -> cachestate = Busy } | ||
| 31 | :: atomic { cachestate == Busy -> cachestate = I } | ||
| 32 | :: atomic { evilstate == I -> assert(evilsource == -1 && evilnotsent == 0 && evilnotreplied == 0 && evilnewstate == I) -> evilstate = Busy } | ||
| 33 | :: atomic { evilstate == Busy -> assert(evilsource == -1 && evilnotsent == 0 && evilnotreplied == 0 && evilnewstate == I) -> evilstate = I } | ||
| 34 | |||
| 35 | :: downrecvq?SnoopItoM -> if | ||
| 36 | :: cachestate == M -> cachestate = I -> downsendq!M | ||
| 37 | :: else -> if | ||
| 38 | :: evilstate == I -> evilstate = SnoopItoM -> evilnotsent = (1 << N) - 1 | ||
| 39 | :: else -> assert(evilstate != SnoopItoM) -> downsendq!Fail | ||
| 40 | fi | ||
| 41 | fi | ||
| 42 | :: atomic { (evilstate == ItoM || evilstate == SnoopItoM) && evilnotsent & (1 << i) && can send to upstream i -> evilnotsent &= ~(1 << i) -> evilnotreplied |= 1 << i -> upsendq[i]!SnoopItoM } | ||
| 43 | :: atomic { (evilstate == ItoM || evilstate == SnoopItoM) && evilnotsent == 0 && evilnotreplied == 0 -> if :: evilnewstate == I -> if :: evilstate == ItoM -> upsendq[evilsource]!I :: else -> downsendq!I fi :: else -> evilnewstate = I fi -> evilstate = I -> evilsource = -1 } | ||
| 44 | :: atomic { uprecvq[i]?I -> assert(evilstate == ItoM || evilstate == SnoopItoM) -> assert((evilnotsent & (1 << i)) == 0 && (evilnotreplied & (1 << i)) != 0)) -> evilnotreplied &= ~(1 << i) } | ||
| 45 | :: atomic { uprecvq[i]?M -> assert(evilstate == ItoM || evilstate == SnoopItoM) -> assert((evilnotsent & (1 << i)) == 0 && (evilnotreplied & (1 << i)) != 0)) -> evilnotreplied &= ~(1 << i) -> evilnewstate = M -> if :: evilstate == ItoM -> upsendq[evilsource]!M :: else -> downsendq!M fi } | ||
| 46 | |||
| 47 | |||
| 48 | |||
| 49 | |||
| 50 | |||
| 51 | |||
| 52 | |||
| 53 | |||
| 54 | :: atomic { downrep[i] is empty -> if | ||
| 55 | :: upreq[i]?Fetch -> if | ||
| 56 | :: atomic { cachestate == Busy -> uprep[i]!Fail } | ||
| 57 | :: atomic { cachestate == M -> uprep[i]!Done } | ||
| 58 | :: cachestate == I -> do | ||
| 59 | :: uprep[i]!Fail | ||
| 60 | :: atomic { evilstate == I -> evilstate = ItoM -> evilsource = i -> downreq!ItoM -> uprep[i]!Busy } | ||
| 61 | od | ||
| 62 | fi | ||
| 63 | :: upreq[i]?Store -> if | ||
| 64 | :: atomic { cachestate == Busy -> uprep[i]!Fail } | ||
| 65 | :: atomic { cachestate == M -> uprep[i]!Done } | ||
| 66 | :: cachestate == I -> do | ||
| 67 | :: uprep[i]!Fail | ||
| 68 | :: atomic { evilstate == I -> evilstate = ItoM -> evilsource = i -> downreq!ItoM -> uprep[i]!Busy } | ||
| 69 | od | ||
| 70 | fi | ||
| 71 | :: upreq[i]?ItoM -> if | ||
| 72 | :: atomic { cachestate == M -> cachestate = I -> uprep[i]!ItoM } | ||
| 73 | :: atomic { cachestate == I && evilstate == I -> if | ||
| 74 | :: can send downstream -> evilstate = SnoopItoM -> evilsource = i -> assert(evilwaiting == 0) -> | ||
| 75 | j = 0 -> do :: j < N -> if :: i != j -> upsnoop[j]!SnoopItoM -> evilwaiting |= 1 << j :: else fi -> j = j + 1 :: else -> break fi od -> | ||
| 76 | uprep[i]!Busy | ||
| 77 | :: !can send downstream -> uprep[i]!Fail | ||
| 78 | fi } | ||
| 79 | fi | ||
| 80 | |||
