@@ -623,43 +623,51 @@ preserves call YieldInv#2();
623623requires call YieldRead(i, ma, drp);
624624{
625625 var dirState: DirState;
626- var value: Value;
627626 var {:linear} {:layer 1 ,2 } dp: Set DirPermission;
628- var {:linear} {:layer 1 ,2 } dpOne: Set DirPermission;
629- var victims: Set CacheId;
630- var victim: CacheId;
631- var {:layer 2 } cache_s: [CacheId][CacheAddr]CacheLine;
627+ var value: Value;
632628
633629 par dirState, dp := dir_req_begin(ma) | YieldInv#1 ();
634630 if (dirState is Owner) {
635631 par value := cache_invalidate_exc#1 (dirState-> i, ma, Invalid(), dp) | YieldInv#1 ();
636632 par write_mem(ma, value, dp) | YieldInv#1 ();
637633 } else {
638- call {:layer 2 } cache_s := Copy(cache);
639- victims := dirState-> iset;
640- while (victims ! = Set_Empty())
641- invariant {:yields} {:layer 1 } true ;
642- invariant {:layer 1 } call YieldInv#1 ();
643- invariant {:layer 2 } dp == WholeDirPermission(ma);
644- invariant {:layer 2 } Set_IsSubset(victims, dirState-> iset);
645- invariant {:layer 2 } (forall i: CacheId:: Set_Contains(dirState-> iset, i) || cache[i] == cache_s[i]);
646- invariant {:layer 2 } (forall i: CacheId:: Set_Contains(dirState-> iset, i) ==>
647- if Set_Contains(victims, i)
648- then cache[i] == cache_s[i]
649- else cache[i] == cache_s[i][Hash(ma) := CacheLine(ma, cache_s[i][Hash(ma)]-> value, Invalid())]);
650- {
651- victim := Choice(victims-> val);
652- victims := Set_Remove(victims, victim);
653- par dpOne, dp := get_victim(victim, ma, dp) | YieldInv#1 ();
654- par cache_invalidate_shd#1 (victim, ma, Invalid(), dpOne) | YieldInv#1 ();
655- par dp := put_victim(dpOne, dp) | YieldInv#1 ();
656- }
634+ call dp := invalidate_sharers(ma, dirState-> iset, dp);
657635 par value := read_mem(ma, dp) | YieldInv#1 ();
658636 }
659637 call cache_read_resp#1 (i, ma, value, Exclusive(), drp, dp);
660638 par dir_req_end(ma, Owner(i), dp) | YieldInv#1 ();
661639}
662640
641+ yield left procedure {:layer 2 } invalidate_sharers(ma: MemAddr, victims: Set CacheId, {:linear_in} {:layer 1 ,2 } dp: Set DirPermission)
642+ returns ({:linear} {:layer 1 ,2 } dp': Set DirPermission)
643+ modifies cache;
644+ preserves call YieldInv#1 ();
645+ requires {:layer 2 } Set_IsSubset(Set((lambda x: DirPermission :: Set_Contains(victims, x-> i) && x-> ma == ma)), dp);
646+ requires {:layer 2 } (forall i: CacheId, ca: CacheAddr:: (var line := cache[i][ca];
647+ line-> state == Invalid() ||
648+ (line-> value == absMem[line-> ma] && if line-> state == Shared() then dir[line-> ma] is Sharers else dir[line-> ma] is Owner)));
649+ requires {:layer 2 } (forall i: CacheId:: Set_Contains(victims, i) ==> cache[i][Hash(ma)]-> state == Shared() && cache[i][Hash(ma)]-> ma == ma);
650+ ensures {:layer 2 } (forall i: CacheId:: Set_Contains(victims, i) ==>
651+ cache[i] == old (cache)[i][Hash(ma) := CacheLine(ma, old (cache)[i][Hash(ma)]-> value, Invalid())]);
652+ ensures {:layer 2 } (forall i: CacheId:: Set_Contains(victims, i) || cache[i] == old (cache)[i]);
653+ ensures {:layer 2 } dp == dp';
654+ {
655+ var victim: CacheId;
656+ var victims': Set CacheId;
657+ var {:linear} {:layer 1 ,2 } dpOne: Set DirPermission;
658+
659+ dp' := dp;
660+ if (victims == Set_Empty())
661+ {
662+ return ;
663+ }
664+ victim := Choice(victims-> val);
665+ victims' := Set_Remove(victims, victim);
666+ par dpOne, dp' := get_victim(victim, ma, dp') | YieldInv#1 ();
667+ par cache_invalidate_shd#1 (victim, ma, Invalid(), dpOne) | dp' := invalidate_sharers(ma, victims', dp') | YieldInv#1 ();
668+ par dp' := put_victim(dpOne, dp') | YieldInv#1 ();
669+ }
670+
663671yield procedure {:layer 1 } get_victim(victim: CacheId, ma: MemAddr, {:layer 1 } {:linear_in} dp: Set DirPermission)
664672returns ({:linear} {:layer 1 } dpOne: Set DirPermission, {:linear} {:layer 1 } dp': Set DirPermission)
665673refines both action {:layer 2 } _ {
0 commit comments