summaryrefslogtreecommitdiff
path: root/spin/mesi.pml
diff options
context:
space:
mode:
authorJulian Blake Kongslie2023-03-19 14:22:39 -0700
committerJulian Blake Kongslie2023-03-19 14:22:39 -0700
commit7e93a297c4ac68a51b5b5847979827a8c5975ceb (patch)
tree40287680cd9ca3edef85f0d9765958832abfa225 /spin/mesi.pml
parentFix focal 69. (diff)
downloadbiggolf-7e93a297c4ac68a51b5b5847979827a8c5975ceb.tar.xz
Add various spin models, including one that might actually work.
Diffstat (limited to '')
-rw-r--r--spin/mesi.pml132
1 files changed, 132 insertions, 0 deletions
diff --git a/spin/mesi.pml b/spin/mesi.pml
new file mode 100644
index 0000000..5bb1c69
--- /dev/null
+++ b/spin/mesi.pml
@@ -0,0 +1,132 @@
1// vim: set sw=3 :
2
3mtype { FETCH, FETCHDONE, STORE, STOREDONE, FILLREQ, FILLRESP, EVICT, SNOOP, SNOOPRESP, NACK, M, E, S, I }
4#define CACHE00 0
5#define CACHE01 1
6#define CACHE10 2
7#define NUM_CACHES 3
8
9// System diagram
10//
11// CPU0 CPU1
12// | |
13// CACHE00 CACHE01
14// | |
15// CACHE10-+
16// |
17// DRAM
18//
19// c2m queues are named c2m_<receiving process>, e.g. c2m_cache10
20//
21// m2c queues are stored in the global m2c_info array so that they can be found as needed for snoops
22
23typedef m2c_info_t {
24 chan m2c;
25 int snoops_from;
26}
27
28m2c_info_t m2c_info[2];
29
30#define C2M_T [0] of {mtype /* message type */, chan /* response channel */, mtype /* have */, mtype /* want */}
31#define M2C_T [0] of {mtype /* message type */, mtype /* result */}
32
33proctype dram(chan c2m)
34{
35 chan r;
36 mtype want;
37 do
38 :: c2m?FETCH,r,_,_ -> r!FETCHDONE,S
39 :: c2m?STORE,r,_,_ -> r!STOREDONE,M
40 :: c2m?FILLREQ,r,_,want -> r!FILLRESP,want
41 :: c2m?EVICT,r,_,want
42 od
43}
44
45proctype cache(chan up; chan down; chan m2c; int whoami)
46{
47 chan r;
48 mtype cachestate = I; // this should be part of a global array so we can assert that at most one cache has M or E state
49 do
50 :: up?FETCH,r,_,_ -> if
51 :: /* no buffer available */ r!NACK,I
52 :: cachestate != I -> r!FETCHDONE,S
53 :: cachestate == I -> down!FILLREQ,m2c,cachestate,S ->
54 do
55 :: if
56 :: atomic { m2c?FILLRESP,cachestate -> r!FETCHDONE,S -> break }
57 :: atomic { m2c?NACK,_ -> down!FILLREQ,m2c,cachestate,S }
58 :: atomic { m2c?SNOOP,_ -> down!SNOOPRESP,m2c,cachestate,I }
59 fi
60 od
61 fi
62 :: up?STORE,r,_,_
63 :: up?FILLREQ,r,_,S
64 :: up?FILLREQ,r,_,E
65 :: up?EVICT,r,M,I -> atomic { assert(cachestate == I) -> cachestate = M }
66 :: up?EVICT,r,M,I -> atomic { assert(cachestate == I) -> down!EVICT,m2c,M,I }
67 :: m2c?SNOOP,E -> atomic { down!SNOOPRESP,m2c,cachestate,I -> cachestate = I }
68 :: m2c?SNOOP,E -> if
69 :: atomic { cachestate == M -> down!SNOOPRESP,m2c,cachestate,I -> cachestate = I }
70 :: atomic { cachestate == E -> down!SNOOPRESP,m2c,cachestate,I -> cachestate = I }
71 :: atomic { cachestate == S -> /* fixme propagate snoop upstream */ /* fixme wait for responses, possibly changing cachestate */ down!SNOOPRESP,m2c,cachestate,I -> cachestate = I }
72 :: atomic { cachestate == I -> /* fixme propagate snoop upstream */ /* fixme wait for responses, possibly changing cachestate */ down!SNOOPRESP,m2c,cachestate,I -> cachestate = I }
73 fi
74 :: m2c?SNOOP,S -> if
75 :: atomic { cachestate == M -> down!SNOOPRESP,m2c,cachestate,I -> cachestate = I }
76 :: atomic { cachestate == E -> down!SNOOPRESP,m2c,cachestate,S -> cachestate = S }
77 :: atomic { cachestate == S -> down!SNOOPRESP,m2c,cachestate,cachestate }
78 :: atomic { cachestate == I -> /* fixme propagate snoop upstream */ /* fixme wait for responses, possibly changing cachestate */ down!SNOOPRESP,m2c,cachestate,downgraded_cachestate -> cachestate = downgraded_cachestate }
79 fi
80 :: atomic { cachestate == M -> down!EVICT,m2c,cachestate,I -> cachestate = I }
81 od
82}
83
84proctype cpu(chan c2m; chan m2c)
85{
86progress:
87 do
88 :: do
89 :: c2m!FETCH,m2c,I,S -> if
90 :: m2c?FETCHDONE,_ -> break
91 :: m2c?NACK,_
92 fi
93 od
94 :: do
95 :: c2m!STORE,m2c,I,M -> if
96 :: m2c?STOREDONE,_ -> break
97 :: m2c?NACK,_
98 fi
99 od
100 od
101}
102
103init
104{
105 // downstream channels
106 chan c2m_cache00 = C2M_T;
107 chan c2m_cache01 = C2M_T;
108 chan c2m_cache10 = C2M_T;
109 chan c2m_dram = C2M_T;
110
111 // upstream channels
112 chan m2c_cpu0 = M2C_T;
113 chan m2c_cpu1 = M2C_T;
114 chan m2c_cache00 = M2C_T;
115 chan m2c_cache01 = M2C_T;
116 chan m2c_cache10 = M2C_T;
117
118 atomic
119 {
120 // construct snoop table
121 m2c_info[0].m2c = m2c_cache00; m2c_info[0].snoops_from = CACHE10;
122 m2c_info[1].m2c = m2c_cache01; m2c_info[1].snoops_from = CACHE10;
123
124 // construct processes
125 run cpu(c2m_cache00, m2c_cpu0);
126 run cpu(c2m_cache01, m2c_cpu1);
127 run cache(c2m_cache00, c2m_cache10, m2c_cache00, CACHE00);
128 run cache(c2m_cache01, c2m_cache10, m2c_cache01, CACHE01);
129 run cache(c2m_cache10, c2m_dram, m2c_cache10, CACHE10);
130 run dram(c2m_dram);
131 }
132}