MOESI_hammer: Added full-bit directory support
[gem5.git] / src / mem / protocol / MI_example-cache.sm
1
2 machine(L1Cache, "MI Example L1 Cache")
3 : Sequencer * sequencer,
4 CacheMemory * cacheMemory,
5 int cache_response_latency = 12,
6 int issue_latency = 2
7 {
8
9 // NETWORK BUFFERS
10 MessageBuffer requestFromCache, network="To", virtual_network="2", ordered="true";
11 MessageBuffer responseFromCache, network="To", virtual_network="4", ordered="true";
12
13 MessageBuffer forwardToCache, network="From", virtual_network="3", ordered="true";
14 MessageBuffer responseToCache, network="From", virtual_network="4", ordered="true";
15
16 // STATES
17 enumeration(State, desc="Cache states") {
18 I, desc="Not Present/Invalid";
19 II, desc="Not Present/Invalid, issued PUT";
20 M, desc="Modified";
21 MI, desc="Modified, issued PUT";
22 MII, desc="Modified, issued PUTX, received nack";
23
24 IS, desc="Issued request for LOAD/IFETCH";
25 IM, desc="Issued request for STORE/ATOMIC";
26 }
27
28 // EVENTS
29 enumeration(Event, desc="Cache events") {
30 // From processor
31
32 Load, desc="Load request from processor";
33 Ifetch, desc="Ifetch request from processor";
34 Store, desc="Store request from processor";
35
36 Data, desc="Data from network";
37 Fwd_GETX, desc="Forward from network";
38
39 Inv, desc="Invalidate request from dir";
40
41 Replacement, desc="Replace a block";
42 Writeback_Ack, desc="Ack from the directory for a writeback";
43 Writeback_Nack, desc="Nack from the directory for a writeback";
44 }
45
46 // STRUCTURE DEFINITIONS
47
48 MessageBuffer mandatoryQueue, ordered="false";
49
50 // CacheEntry
51 structure(Entry, desc="...", interface="AbstractCacheEntry") {
52 State CacheState, desc="cache state";
53 bool Dirty, desc="Is the data dirty (different than memory)?";
54 DataBlock DataBlk, desc="Data in the block";
55 }
56
57
58 // TBE fields
59 structure(TBE, desc="...") {
60 State TBEState, desc="Transient state";
61 DataBlock DataBlk, desc="data for the block, required for concurrent writebacks";
62 }
63
64 external_type(TBETable) {
65 TBE lookup(Address);
66 void allocate(Address);
67 void deallocate(Address);
68 bool isPresent(Address);
69 }
70
71
72 // STRUCTURES
73
74 TBETable TBEs, template_hack="<L1Cache_TBE>";
75
76 // PROTOTYPES
77 void set_cache_entry(AbstractCacheEntry a);
78 void unset_cache_entry();
79 void set_tbe(TBE b);
80 void unset_tbe();
81
82 Entry getCacheEntry(Address address), return_by_pointer="yes" {
83 return static_cast(Entry, "pointer", cacheMemory.lookup(address));
84 }
85
86 // FUNCTIONS
87 Event mandatory_request_type_to_event(CacheRequestType type) {
88 if (type == CacheRequestType:LD) {
89 return Event:Load;
90 } else if (type == CacheRequestType:IFETCH) {
91 return Event:Ifetch;
92 } else if ((type == CacheRequestType:ST) || (type == CacheRequestType:ATOMIC)) {
93 return Event:Store;
94 } else {
95 error("Invalid CacheRequestType");
96 }
97 }
98
99 State getState(TBE tbe, Entry cache_entry, Address addr) {
100
101 if (is_valid(tbe)) {
102 return tbe.TBEState;
103 }
104 else if (is_valid(cache_entry)) {
105 return cache_entry.CacheState;
106 }
107 else {
108 return State:I;
109 }
110 }
111
112 void setState(TBE tbe, Entry cache_entry, Address addr, State state) {
113
114 if (is_valid(tbe)) {
115 tbe.TBEState := state;
116 }
117
118 if (is_valid(cache_entry)) {
119 cache_entry.CacheState := state;
120 if (state == State:M) {
121 cache_entry.changePermission(AccessPermission:Read_Write);
122 } else {
123 cache_entry.changePermission(AccessPermission:Invalid);
124 }
125 }
126 }
127
128 GenericMachineType getNondirectHitMachType(MachineID sender) {
129 if (machineIDToMachineType(sender) == MachineType:L1Cache) {
130 //
131 // NOTE direct local hits should not call this
132 //
133 return GenericMachineType:L1Cache_wCC;
134 } else {
135 return ConvertMachToGenericMach(machineIDToMachineType(sender));
136 }
137 }
138
139
140 // NETWORK PORTS
141
142 out_port(requestNetwork_out, RequestMsg, requestFromCache);
143 out_port(responseNetwork_out, ResponseMsg, responseFromCache);
144
145 in_port(forwardRequestNetwork_in, RequestMsg, forwardToCache) {
146 if (forwardRequestNetwork_in.isReady()) {
147 peek(forwardRequestNetwork_in, RequestMsg, block_on="Address") {
148
149 Entry cache_entry := getCacheEntry(in_msg.Address);
150 TBE tbe := TBEs[in_msg.Address];
151
152 if (in_msg.Type == CoherenceRequestType:GETX) {
153 trigger(Event:Fwd_GETX, in_msg.Address, cache_entry, tbe);
154 }
155 else if (in_msg.Type == CoherenceRequestType:WB_ACK) {
156 trigger(Event:Writeback_Ack, in_msg.Address, cache_entry, tbe);
157 }
158 else if (in_msg.Type == CoherenceRequestType:WB_NACK) {
159 trigger(Event:Writeback_Nack, in_msg.Address, cache_entry, tbe);
160 }
161 else if (in_msg.Type == CoherenceRequestType:INV) {
162 trigger(Event:Inv, in_msg.Address, cache_entry, tbe);
163 }
164 else {
165 error("Unexpected message");
166 }
167 }
168 }
169 }
170
171 in_port(responseNetwork_in, ResponseMsg, responseToCache) {
172 if (responseNetwork_in.isReady()) {
173 peek(responseNetwork_in, ResponseMsg, block_on="Address") {
174
175 Entry cache_entry := getCacheEntry(in_msg.Address);
176 TBE tbe := TBEs[in_msg.Address];
177
178 if (in_msg.Type == CoherenceResponseType:DATA) {
179 trigger(Event:Data, in_msg.Address, cache_entry, tbe);
180 }
181 else {
182 error("Unexpected message");
183 }
184 }
185 }
186 }
187
188 // Mandatory Queue
189 in_port(mandatoryQueue_in, CacheMsg, mandatoryQueue, desc="...") {
190 if (mandatoryQueue_in.isReady()) {
191 peek(mandatoryQueue_in, CacheMsg, block_on="LineAddress") {
192
193 Entry cache_entry := getCacheEntry(in_msg.LineAddress);
194 if (is_invalid(cache_entry) &&
195 cacheMemory.cacheAvail(in_msg.LineAddress) == false ) {
196 // make room for the block
197 trigger(Event:Replacement, cacheMemory.cacheProbe(in_msg.LineAddress),
198 getCacheEntry(cacheMemory.cacheProbe(in_msg.LineAddress)),
199 TBEs[cacheMemory.cacheProbe(in_msg.LineAddress)]);
200 }
201 else {
202 trigger(mandatory_request_type_to_event(in_msg.Type), in_msg.LineAddress,
203 cache_entry, TBEs[in_msg.LineAddress]);
204 }
205 }
206 }
207 }
208
209 // ACTIONS
210
211 action(a_issueRequest, "a", desc="Issue a request") {
212 enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) {
213 out_msg.Address := address;
214 out_msg.Type := CoherenceRequestType:GETX;
215 out_msg.Requestor := machineID;
216 out_msg.Destination.add(map_Address_to_Directory(address));
217 out_msg.MessageSize := MessageSizeType:Control;
218 }
219 }
220
221 action(b_issuePUT, "b", desc="Issue a PUT request") {
222 enqueue(requestNetwork_out, RequestMsg, latency=issue_latency) {
223 assert(is_valid(cache_entry));
224 out_msg.Address := address;
225 out_msg.Type := CoherenceRequestType:PUTX;
226 out_msg.Requestor := machineID;
227 out_msg.Destination.add(map_Address_to_Directory(address));
228 out_msg.DataBlk := cache_entry.DataBlk;
229 out_msg.MessageSize := MessageSizeType:Data;
230 }
231 }
232
233
234 action(e_sendData, "e", desc="Send data from cache to requestor") {
235 peek(forwardRequestNetwork_in, RequestMsg) {
236 enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) {
237 assert(is_valid(cache_entry));
238 out_msg.Address := address;
239 out_msg.Type := CoherenceResponseType:DATA;
240 out_msg.Sender := machineID;
241 out_msg.Destination.add(in_msg.Requestor);
242 out_msg.DataBlk := cache_entry.DataBlk;
243 out_msg.MessageSize := MessageSizeType:Response_Data;
244 }
245 }
246 }
247
248 action(ee_sendDataFromTBE, "\e", desc="Send data from TBE to requestor") {
249 peek(forwardRequestNetwork_in, RequestMsg) {
250 enqueue(responseNetwork_out, ResponseMsg, latency=cache_response_latency) {
251 assert(is_valid(tbe));
252 out_msg.Address := address;
253 out_msg.Type := CoherenceResponseType:DATA;
254 out_msg.Sender := machineID;
255 out_msg.Destination.add(in_msg.Requestor);
256 out_msg.DataBlk := tbe.DataBlk;
257 out_msg.MessageSize := MessageSizeType:Response_Data;
258 }
259 }
260 }
261
262 action(i_allocateL1CacheBlock, "i", desc="Allocate a cache block") {
263 if (is_valid(cache_entry)) {
264 } else {
265 set_cache_entry(cacheMemory.allocate(address, new Entry));
266 }
267 }
268
269 action(h_deallocateL1CacheBlock, "h", desc="deallocate a cache block") {
270 if (is_valid(cache_entry)) {
271 cacheMemory.deallocate(address);
272 unset_cache_entry();
273 }
274 }
275
276 action(m_popMandatoryQueue, "m", desc="Pop the mandatory request queue") {
277 mandatoryQueue_in.dequeue();
278 }
279
280 action(n_popResponseQueue, "n", desc="Pop the response queue") {
281 profileMsgDelay(1, responseNetwork_in.dequeue_getDelayCycles());
282 }
283
284 action(o_popForwardedRequestQueue, "o", desc="Pop the forwarded request queue") {
285 profileMsgDelay(2, forwardRequestNetwork_in.dequeue_getDelayCycles());
286 }
287
288 action(p_profileMiss, "p", desc="Profile cache miss") {
289 peek(mandatoryQueue_in, CacheMsg) {
290 cacheMemory.profileMiss(in_msg);
291 }
292 }
293
294 action(r_load_hit, "r", desc="Notify sequencer the load completed.") {
295 assert(is_valid(cache_entry));
296 DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk);
297 sequencer.readCallback(address,
298 GenericMachineType:L1Cache,
299 cache_entry.DataBlk);
300 }
301
302 action(rx_load_hit, "rx", desc="External load completed.") {
303 peek(responseNetwork_in, ResponseMsg) {
304 assert(is_valid(cache_entry));
305 DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk);
306 sequencer.readCallback(address,
307 getNondirectHitMachType(in_msg.Sender),
308 cache_entry.DataBlk);
309 }
310 }
311
312 action(s_store_hit, "s", desc="Notify sequencer that store completed.") {
313 assert(is_valid(cache_entry));
314 DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk);
315 sequencer.writeCallback(address,
316 GenericMachineType:L1Cache,
317 cache_entry.DataBlk);
318 }
319
320 action(sx_store_hit, "sx", desc="External store completed.") {
321 peek(responseNetwork_in, ResponseMsg) {
322 assert(is_valid(cache_entry));
323 DPRINTF(RubySlicc,"%s\n", cache_entry.DataBlk);
324 sequencer.writeCallback(address,
325 getNondirectHitMachType(in_msg.Sender),
326 cache_entry.DataBlk);
327 }
328 }
329
330 action(u_writeDataToCache, "u", desc="Write data to the cache") {
331 peek(responseNetwork_in, ResponseMsg) {
332 assert(is_valid(cache_entry));
333 cache_entry.DataBlk := in_msg.DataBlk;
334 }
335 }
336
337
338 action(v_allocateTBE, "v", desc="Allocate TBE") {
339 TBEs.allocate(address);
340 set_tbe(TBEs[address]);
341 }
342
343
344 action(w_deallocateTBE, "w", desc="Deallocate TBE") {
345 TBEs.deallocate(address);
346 unset_tbe();
347 }
348
349 action(x_copyDataFromCacheToTBE, "x", desc="Copy data from cache to TBE") {
350 assert(is_valid(cache_entry));
351 assert(is_valid(tbe));
352 tbe.DataBlk := cache_entry.DataBlk;
353 }
354
355 action(z_stall, "z", desc="stall") {
356 // do nothing
357 }
358
359 // TRANSITIONS
360
361 transition({IS, IM, MI, II}, {Load, Ifetch, Store, Replacement}) {
362 z_stall;
363 }
364
365 transition({IS, IM}, {Fwd_GETX, Inv}) {
366 z_stall;
367 }
368
369 transition(MI, Inv) {
370 o_popForwardedRequestQueue;
371 }
372
373 transition(M, Store) {
374 s_store_hit;
375 m_popMandatoryQueue;
376 }
377
378 transition(M, {Load, Ifetch}) {
379 r_load_hit;
380 m_popMandatoryQueue;
381 }
382
383 transition(I, Inv) {
384 o_popForwardedRequestQueue;
385 }
386
387 transition(I, Store, IM) {
388 v_allocateTBE;
389 i_allocateL1CacheBlock;
390 a_issueRequest;
391 p_profileMiss;
392 m_popMandatoryQueue;
393 }
394
395 transition(I, {Load, Ifetch}, IS) {
396 v_allocateTBE;
397 i_allocateL1CacheBlock;
398 a_issueRequest;
399 p_profileMiss;
400 m_popMandatoryQueue;
401 }
402
403 transition(IS, Data, M) {
404 u_writeDataToCache;
405 rx_load_hit;
406 w_deallocateTBE;
407 n_popResponseQueue;
408 }
409
410 transition(IM, Data, M) {
411 u_writeDataToCache;
412 sx_store_hit;
413 w_deallocateTBE;
414 n_popResponseQueue;
415 }
416
417 transition(M, Fwd_GETX, I) {
418 e_sendData;
419 o_popForwardedRequestQueue;
420 }
421
422 transition(I, Replacement) {
423 h_deallocateL1CacheBlock;
424 }
425
426 transition(M, {Replacement,Inv}, MI) {
427 v_allocateTBE;
428 b_issuePUT;
429 x_copyDataFromCacheToTBE;
430 h_deallocateL1CacheBlock;
431 }
432
433 transition(MI, Writeback_Ack, I) {
434 w_deallocateTBE;
435 o_popForwardedRequestQueue;
436 }
437
438 transition(MI, Fwd_GETX, II) {
439 ee_sendDataFromTBE;
440 o_popForwardedRequestQueue;
441 }
442
443 transition(MI, Writeback_Nack, MII) {
444 o_popForwardedRequestQueue;
445 }
446
447 transition(MII, Fwd_GETX, I) {
448 ee_sendDataFromTBE;
449 w_deallocateTBE;
450 o_popForwardedRequestQueue;
451 }
452
453 transition(II, Writeback_Nack, I) {
454 w_deallocateTBE;
455 o_popForwardedRequestQueue;
456 }
457 }
458