(** *SyncStep simulation*)
(** Proof of the step diagram when the step is a synchronization step. TODO: Split the proof in each diagram. *)
Inductive deltaMap_cases (dmap:delta_map) b ofs:=
| DMAPS df p:  dmap ! b = Some df -> df ofs = Some p -> deltaMap_cases dmap b ofs
| DNONE1 df:  dmap ! b = Some df -> df ofs = None -> deltaMap_cases dmap b ofs
| DNONE2:  dmap ! b = None -> deltaMap_cases dmap b ofs.

(* Specifications: *)
Lemma deltaMap_dec: forall dmap b ofs, deltaMap_cases dmap b ofs.
Lemma permMapsDisjoint2_empty: forall rmap,
permMapsDisjoint2 (empty_map, empty_map) rmap.
Lemma po_None1: forall p, Mem.perm_order'' None p -> p = None.
(* Proof of the step diagram when the step is a synchronization step *)
Lemma sync_step_diagram:
forall (m m':Memory.mem) (U:seq nat) js js' ds i ev
(MATCH: match_st js ds)
(dinv: invariant ds)
(Hi: containsThread js i)
(Hcmpt: mem_compatible js m)
(HschedN: schedPeek U = Some i)
(Htstep:  syncStep true Hi Hcmpt js' m' ev),
exists ds' : dstate, exists ev',
invariant ds' /\ match_st js' ds' /\
syncStep true (MTCH_cnt MATCH Hi) (MTCH_compat _ _ _ MATCH Hcmpt) ds' m' ev'.
(* 'Decaying memory' preserves invariant. Note that the invariant doesnt depend on the "core" c. so we can cahnge it to any c' *)
Lemma step_decay_invariant:
forall (tp : dstate)  (m : Mem.mem) i
(Hi : containsThread tp i) m1 m1' c'
(Hinv: invariant tp)
(Hcompatible: DryHybridMachine.mem_compatible tp m)
(Hrestrict_pmap :restrPermMap ((DryHybridMachine.compat_th _ _ Hcompatible) Hi).1 = m1)
(Hdecay: decay m1 m1'),
invariant
(updThread Hi (Krun c')
(getCurPerm m1', (getThreadR Hi).2)).
Lemma mtch_install_perm:
forall js ds m m' tid (MATCH : match_st js ds)
(Hcmpt : mem_compatible js m) (Htid : containsThread js tid)
(Hperm : install_perm Hcmpt Htid m'),
DryHybridMachine.install_perm _ _ _ (MTCH_compat _ _ _ MATCH Hcmpt) (MTCH_cnt MATCH Htid) m'.
(* Proof of the smallstep diagram *)
Lemma core_diagram':
forall (m : Mem.mem)  (U0 U U': schedule)
(ds : dstate) dtr (js js': jstate) jtr jtr' rmap pmap
(m' : Mem.mem),
match_st js ds ->
invariant ds ->
corestep (JMachineSem U0 rmap) (U, jtr, js) m (U', jtr', js') m' ->
exists (ds' : dstate),
invariant ds' /\
match_st js' ds' /\
exists dtr', corestep (ClightMachineSem U0 pmap) (U, dtr, ds) m (U', dtr ++ dtr', ds') m'.
Lemma core_diagram:
forall (m : Mem.mem)  (U0 U U': schedule) rmap pmap
(ds : dstate) dtr (js js': jstate) jtr jtr'
(m' : Mem.mem),
corestep (JMachineSem U0 rmap) (U, jtr, js) m (U', jtr', js') m' ->
match_st js ds ->
invariant ds ->
exists (ds' : dstate),
invariant ds' /\
match_st js' ds' /\
exists dtr', corestep (ClightMachineSem U0 pmap) (U, dtr, ds) m (U', dtr ++ dtr', ds') m'.
Lemma halted_diagram:
forall U ds js rmap pmap,
fst (fst js) = fst (fst ds) ->
halted (JMachineSem(ge := ge) U rmap) js = halted (ClightMachineSem(ge := ge) U pmap) ds.