Skip to content

Commit 3a23efe

Browse files
authored
[Civl] rename procedures in cache coherence and add more comments (#991)
1 parent 517cdac commit 3a23efe

File tree

1 file changed

+38
-18
lines changed

1 file changed

+38
-18
lines changed

Test/civl/large-samples/cache-coherence.bpl

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ At layer 1, cachePermissions and dirPermissions are introduced allowing dirBusy
7676
to be hidden. At this layer, absMem is also introduced. The main purpose of this layer is to
7777
create atomic actions with suitable mover types. Specifically, we want the following:
7878
- Memory operations (read and write) to be both movers.
79-
- Shared snoop request at cache to be left mover.
79+
- Shared invalidate request at cache to be left mover.
8080
- Response to read request at cache to be left mover.
8181
- Initiation and conclusion of cache and directory operations to be right and left movers, respectively.
8282
@@ -115,6 +115,24 @@ invariant Set_Contains(drp, CachePermission(i, Hash(ma)));
115115
invariant (var line := cache[i][Hash(ma)]; (line->state == Invalid() || line->state == Shared()) && line->ma == ma);
116116

117117
/// Cache
118+
/*
119+
There are 5 top-level operations on the cache.
120+
cache_read and cache_write read and write a cache entry, respectively;
121+
they may nondeterministically choose not to do the operation.
122+
cache_evict_req initiates eviction of a cache line.
123+
cache_read_shd_req and cache_read_exc_req initiate bringing a memory address into the cache
124+
in Shared and Exclusive mode, respectively.
125+
The last three operations make asynchronous calls to corresponding operations on the directory
126+
to achieve their goals.
127+
128+
To specify the protocol, we introduce absMem, a global variable capturing the logical view of
129+
memory at layer 1.
130+
The verification demonstrates that cache_read and cache_read do the appropriate operation
131+
on absMem.
132+
At layer 3, all operations other than cache_read and cache_write disappear by becoming "skip"
133+
since all the concrete state is hidden by layer 2.
134+
*/
135+
118136
yield procedure {:layer 2} cache_read(i: CacheId, ma: MemAddr) returns (result: Option Value)
119137
preserves call YieldInv#2();
120138
refines atomic action {:layer 3} _ {
@@ -188,6 +206,7 @@ refines atomic action {:layer 2} _ {
188206
var line: CacheLine;
189207

190208
if (*) {
209+
// this relaxation allows cache_invalidate_shd#1 to commute to the left of cache_read#1
191210
result := Some(absMem[ma]);
192211
} else if (*) {
193212
result := None();
@@ -335,7 +354,7 @@ refines atomic action {:layer 2} _ {
335354
}
336355

337356
/*
338-
The left mover types of the actions cache_read_resp#1 and cache_snoop_req_shd#1 are critical
357+
The left mover types of the actions cache_read_resp#1 and cache_invalidate_shd#1 are critical
339358
to achieve the correct atomicity for the directory operations.
340359
If the two invocations are hitting different caches, the argument is straightforward.
341360
Otherwise, they are hitting the same cache and their i arguments are the same.
@@ -373,29 +392,30 @@ refines left action {:layer 2} _ {
373392
call {:layer 1} Set_Put(cachePermissions, drp);
374393
}
375394

376-
yield procedure {:layer 1} cache_snoop_req_shd#1(i: CacheId, ma: MemAddr, s: State, {:linear} {:layer 1} dp: Set DirPermission)
395+
yield procedure {:layer 1} cache_invalidate_shd#1(i: CacheId, ma: MemAddr, s: State, {:linear} {:layer 1} dp: Set DirPermission)
377396
refines left action {:layer 2} _ {
378397
var ca: CacheAddr;
379398

380399
assert Set_Contains(dp, DirPermission(i, ma));
381400
assume {:add_to_pool "DirPermission", DirPermission(i, ma)} true;
382401
ca := Hash(ma);
383402
assert (forall j: CacheId :: (var line := cache[j][ca]; line->ma == ma ==> line->state == Invalid() || line->state == Shared()));
403+
// this assertion accompanies the relaxation in cache_read#1 to allow cache_invalidate_shd#1 to commute to the left of cache_read#1
384404
assert cache[i][ca]->value == absMem[ma];
385-
call primitive_cache_snoop_req_shd(i, ma, s);
405+
call primitive_cache_invalidate_shd(i, ma, s);
386406
}
387407
{
388-
call cache_snoop_req_shd#0(i, ma, s);
408+
call cache_invalidate_shd#0(i, ma, s);
389409
}
390410

391-
yield procedure {:layer 1} cache_snoop_req_exc#1(i: CacheId, ma: MemAddr, s: State, {:linear} {:layer 1} dp: Set DirPermission) returns (value: Value)
411+
yield procedure {:layer 1} cache_invalidate_exc#1(i: CacheId, ma: MemAddr, s: State, {:linear} {:layer 1} dp: Set DirPermission) returns (value: Value)
392412
refines atomic action {:layer 2} _ {
393413
assert dp == WholeDirPermission(ma);
394414
assume {:add_to_pool "DirPermission", DirPermission(i0, ma)} true;
395-
call value := primitive_cache_snoop_req_exc(i, ma, s);
415+
call value := primitive_cache_invalidate_exc(i, ma, s);
396416
}
397417
{
398-
call value := cache_snoop_req_exc#0(i, ma, s);
418+
call value := cache_invalidate_exc#0(i, ma, s);
399419
}
400420

401421
// Cache primitives
@@ -512,12 +532,12 @@ refines atomic action {:layer 1} _ {
512532
cacheBusy[i][ca] := false;
513533
}
514534

515-
yield procedure {:layer 0} cache_snoop_req_shd#0(i: CacheId, ma: MemAddr, s: State);
535+
yield procedure {:layer 0} cache_invalidate_shd#0(i: CacheId, ma: MemAddr, s: State);
516536
refines atomic action {:layer 1} _ {
517-
call primitive_cache_snoop_req_shd(i, ma, s);
537+
call primitive_cache_invalidate_shd(i, ma, s);
518538
}
519539

520-
action {:layer 1,2} primitive_cache_snoop_req_shd(i: CacheId, ma: MemAddr, s: State)
540+
action {:layer 1,2} primitive_cache_invalidate_shd(i: CacheId, ma: MemAddr, s: State)
521541
{
522542
var ca: CacheAddr;
523543
var line: CacheLine;
@@ -530,12 +550,12 @@ action {:layer 1,2} primitive_cache_snoop_req_shd(i: CacheId, ma: MemAddr, s: St
530550
cache[i][ca]->state := s;
531551
}
532552

533-
yield procedure {:layer 0} cache_snoop_req_exc#0(i: CacheId, ma: MemAddr, s: State) returns (value: Value);
553+
yield procedure {:layer 0} cache_invalidate_exc#0(i: CacheId, ma: MemAddr, s: State) returns (value: Value);
534554
refines atomic action {:layer 1} _ {
535-
call value := primitive_cache_snoop_req_exc(i, ma, s);
555+
call value := primitive_cache_invalidate_exc(i, ma, s);
536556
}
537557

538-
action {:layer 1,2} primitive_cache_snoop_req_exc(i: CacheId, ma: MemAddr, s: State) returns (value: Value)
558+
action {:layer 1,2} primitive_cache_invalidate_exc(i: CacheId, ma: MemAddr, s: State) returns (value: Value)
539559
{
540560
var ca: CacheAddr;
541561
var line: CacheLine;
@@ -559,7 +579,7 @@ requires call YieldEvict(i, ma, value, drp);
559579
var {:linear} {:layer 1,2} dp: Set DirPermission;
560580

561581
par dirState, dp := dir_req_begin(ma) | YieldInv#1();
562-
// do not change dirState in case this is a stale evict request due to a race condition with a snoop
582+
// do not change dirState in case this is a stale evict request due to a race condition with an invalidate
563583
if (dirState == Owner(i)) {
564584
par write_mem(ma, value, dp) | YieldInv#1();
565585
dirState := Sharers(Set_Empty());
@@ -584,7 +604,7 @@ requires call YieldRead(i, ma, drp);
584604

585605
par dirState, dp := dir_req_begin(ma) | YieldInv#1();
586606
if (dirState is Owner) {
587-
par value := cache_snoop_req_exc#1(dirState->i, ma, Shared(), dp) | YieldInv#1();
607+
par value := cache_invalidate_exc#1(dirState->i, ma, Shared(), dp) | YieldInv#1();
588608
par write_mem(ma, value, dp) | YieldInv#1();
589609
call cache_read_resp#1(i, ma, value, Shared(), drp, dp);
590610
par dir_req_end(ma, Sharers(Set_Add(Set_Add(Set_Empty(), dirState->i), i)), dp) | YieldInv#1();
@@ -610,7 +630,7 @@ requires call YieldRead(i, ma, drp);
610630

611631
par dirState, dp := dir_req_begin(ma) | YieldInv#1();
612632
if (dirState is Owner) {
613-
par value := cache_snoop_req_exc#1(dirState->i, ma, Invalid(), dp) | YieldInv#1();
633+
par value := cache_invalidate_exc#1(dirState->i, ma, Invalid(), dp) | YieldInv#1();
614634
par write_mem(ma, value, dp) | YieldInv#1();
615635
} else {
616636
call {:layer 2} cache_s := Copy(cache);
@@ -629,7 +649,7 @@ requires call YieldRead(i, ma, drp);
629649
victim := Choice(victims->val);
630650
victims := Set_Remove(victims, victim);
631651
par dpOne, dp := get_victim(victim, ma, dp) | YieldInv#1();
632-
par cache_snoop_req_shd#1(victim, ma, Invalid(), dpOne) | YieldInv#1();
652+
par cache_invalidate_shd#1(victim, ma, Invalid(), dpOne) | YieldInv#1();
633653
par dp := put_victim(dpOne, dp) | YieldInv#1();
634654
}
635655
par value := read_mem(ma, dp) | YieldInv#1();

0 commit comments

Comments
 (0)