Section HybridSimulation.
(* Variable (Sems Semt : semantics.Semantics). Variable (hb1 hb2: option nat). (*Variable (Resources : Resources_rec). Variable (MatchCAsm: meminj -> corestate -> mem -> Asm_coop.state -> mem -> Prop).*)
Definition HM1:=HybridMachine hb1 Sems Semt.
Definition HM2:=HybridMachine hb2 Sems Semt.
Notation Sem1:=(ConcurMachineSemantics HM1).
Notation Sem2:=(ConcurMachineSemantics HM2).
Notation C1:= (MachState HybridMachine.Resources
(Sem hb1 Sems Semt) (ThreadPool hb1 Sems Semt)).
Notation C2:= (MachState HybridMachine.Resources
(Sem hb2 Sems Semt) (ThreadPool hb2 Sems Semt)).
Notation G1:= (semG (Sem hb1 Sems Semt)).
Notation G2:= (semG (Sem hb2 Sems Semt)).
Variable ge1:G1.
Variable ge2:G2.
Variable (ge_inv: G1 -> G2 -> Prop). *)
Context (SG TG TID SCH SC TC R1 R2 (*s_thread_type t_thread_type*): Type).
Variable SourceHybridMachine: @ConcurSemantics SG TID SCH (list machine_event) SC mem R1.
Variable TargetHybridMachine: @ConcurSemantics TG TID SCH (list machine_event) TC mem R2.
(* Variable opt_init_mem_source : option Memory.Mem.mem. Variable opt_init_mem_target : option Memory.Mem.mem. *)
(* Inductive inject_address (f : meminj) : address -> address -> Prop := | inj_addr : forall b1 delt b2 ofs, f b1 = Some (b2, ofs) -> inject_address f (b1, ofs) (b2, ofs + delt). *)
Inductive inject_address f: address -> address -> Prop :=
| build_inject_address:
forall b1 b2 ofs1 ofs2 delt,
f b1 = Some (b2, delt) ->
ofs2 = ofs1 + delt ->
inject_address f (b1, ofs1) (b2,ofs2).
Definition inject_delta_content: meminj -> delta_content -> delta_content -> Prop:=
fun f dc1 dc2 =>
True.
(* Same as memories that are injected... but, we should reconsider if we really want sync_events. *)
Inductive inject_sync_event (f : meminj) : sync_event -> sync_event -> Prop :=
| inj_release : forall l1 l2 r1 r2, inject_address f l1 l2 ->
match r1, r2 with
| Some (a1), Some (a2) => inject_delta_content f a1 a2
| None, None => True
| _, _ => False
end ->
inject_sync_event f (release l1 r1) (release l2 r2)
| inj_acquire : forall l1 l2 r1 r2, inject_address f l1 l2 ->
match r1, r2 with
| Some (a1), Some (a2) => inject_delta_content f a1 a2
| None, None => True
| _, _ => False
end ->
inject_sync_event f (acquire l1 r1) (acquire l2 r2)
| inj_mklock : forall l1 l2, inject_address f l1 l2 ->
inject_sync_event f (mklock l1) (mklock l2)
| inj_freelock : forall l1 l2, inject_address f l1 l2 ->
inject_sync_event f (freelock l1) (freelock l2)
| inj_spawn : forall l1 l2 r1 r1' r2 r2', inject_address f l1 l2 ->
match r1, r2 with
| Some a1, Some a2 =>
inject_delta_content f a1 a2
| None, None => True
| _, _ => False
end ->
match r1', r2' with
| Some a1', Some a2' =>
inject_delta_content f a1' a2'
| None, None => True
| _, _ => False
end ->
inject_sync_event f (spawn l1 r1 r1') (spawn l2 r2 r2')
| inj_failacq : forall l1 l2, inject_address f l1 l2 ->
inject_sync_event f (failacq l1) (failacq l2).
Inductive inj_free (f:meminj): block * Z * Z -> block * Z * Z -> Prop:=
| build_inj_free:  forall b1 b2 lo1 lo2 hi1 hi2 delt,
f b1 = Some (b2, delt) ->
lo2 = lo1 + delt ->
hi2 = hi1 + delt ->
inj_free f (b1,lo1,hi1) (b2,lo2,hi2).
Inductive inject_mevent (f : meminj) : machine_event -> machine_event -> Prop :=
| inj_internal : forall n me1 me2, inject_mem_event f me1 me2 ->
inject_mevent f (internal n me1) (internal n me2)
| inj_external : forall n se1 se2, inject_sync_event f se1 se2 ->
inject_mevent f (external n se1) (external n se2).

Lemma inject_incr_trace:
forall (tr1 tr2 : list Events.machine_event) (mu f' : meminj),
inject_incr mu f' ->
List.Forall2 (inject_mevent mu) tr1 tr2 ->
List.Forall2 (inject_mevent f') tr1 tr2.