Definition ogetBlock (ov : option val) : block -> bool :=
  match ov with
    | None => fun _:block => false
    | Some v => getBlocks (v::nil)
  end.Inductive match_event : Event.t -> Event.t -> Prop :=
| mk_match_event :
  forall j j' ev1 ev2,
  let args1 := ev1.(args) in
  let args2 := ev2.(args) in
  let rv1 := ev1.(rv) in
  let rv2 := ev2.(rv) in
  let m1 := ev1.(pre_mem) in
  let m1' := ev1.(post_mem) in
  let m2 := ev2.(pre_mem) in
  let m2' := ev2.(post_mem) in
  inject_incr (as_inj j) (as_inj j') ->
  Mem.inject (as_inj j) m1 m2 ->
  Mem.inject (as_inj j') m1' m2' ->
  Forall2 (val_inject (as_inj j)) args1 args2 ->
  oval_inject (as_inj j') rv1 rv2 ->
  match_event ev1 ev2.Inductive match_event : Event.t -> Event.t -> Prop :=
| mk_match_event :
  forall j j' ev1 ev2,
  let args1 := ev1.(args) in
  let args2 := ev2.(args) in
  let rv1 := ev1.(rv) in
  let rv2 := ev2.(rv) in
  let m1 := ev1.(pre_mem) in
  let m1' := ev1.(post_mem) in
  let m2 := ev2.(pre_mem) in
  let m2' := ev2.(post_mem) in
  inject_incr (as_inj j) (as_inj j') ->
  Mem.inject (as_inj j) m1 m2 ->
  Mem.inject (as_inj j') m1' m2' ->
  Forall2 (val_inject (as_inj j)) args1 args2 ->
  oval_inject (as_inj j') rv1 rv2 ->
  match_event ev1 ev2.Inductive match_event : Event.t -> Event.t -> Prop :=
| mk_match_event :
  forall j j' ev1 ev2,
  let args1 := ev1.(args) in
  let args2 := ev2.(args) in
  let rv1 := ev1.(rv) in
  let rv2 := ev2.(rv) in
  let m1 := ev1.(pre_mem) in
  let m1' := ev1.(post_mem) in
  let m2 := ev2.(pre_mem) in
  let m2' := ev2.(post_mem) in
  inject_incr (as_inj j) (as_inj j') ->
  Mem.inject (as_inj j) m1 m2 ->
  Mem.inject (as_inj j') m1' m2' ->
  Forall2 (val_inject (as_inj j)) args1 args2 ->
  oval_inject (as_inj j') rv1 rv2 ->
  match_event ev1 ev2.Inductive match_event : Event.t -> Event.t -> Prop :=
| mk_match_event :
  forall j j' ev1 ev2,
  let args1 := ev1.(args) in
  let args2 := ev2.(args) in
  let rv1 := ev1.(rv) in
  let rv2 := ev2.(rv) in
  let m1 := ev1.(pre_mem) in
  let m1' := ev1.(post_mem) in
  let m2 := ev2.(pre_mem) in
  let m2' := ev2.(post_mem) in
  inject_incr (as_inj j) (as_inj j') ->
  Mem.inject (as_inj j) m1 m2 ->
  Mem.inject (as_inj j') m1' m2' ->
  Forall2 (val_inject (as_inj j)) args1 args2 ->
  oval_inject (as_inj j') rv1 rv2 ->
  match_event ev1 ev2.Inductive match_event : Event.t -> Event.t -> Prop :=
| mk_match_event :
  forall j j' ev1 ev2,
  let args1 := ev1.(args) in
  let args2 := ev2.(args) in
  let rv1 := ev1.(rv) in
  let rv2 := ev2.(rv) in
  let m1 := ev1.(pre_mem) in
  let m1' := ev1.(post_mem) in
  let m2 := ev2.(pre_mem) in
  let m2' := ev2.(post_mem) in
  inject_incr (as_inj j) (as_inj j') ->
  Mem.inject (as_inj j) m1 m2 ->
  Mem.inject (as_inj j') m1' m2' ->
  Forall2 (val_inject (as_inj j)) args1 args2 ->
  oval_inject (as_inj j') rv1 rv2 ->
  match_event ev1 ev2.Inductive match_event : Event.t -> Event.t -> Prop :=
| mk_match_event :
  forall j j' ev1 ev2,
  let args1 := ev1.(args) in
  let args2 := ev2.(args) in
  let rv1 := ev1.(rv) in
  let rv2 := ev2.(rv) in
  let m1 := ev1.(pre_mem) in
  let m1' := ev1.(post_mem) in
  let m2 := ev2.(pre_mem) in
  let m2' := ev2.(post_mem) in
  inject_incr (as_inj j) (as_inj j') ->
  Mem.inject (as_inj j) m1 m2 ->
  Mem.inject (as_inj j') m1' m2' ->
  Forall2 (val_inject (as_inj j)) args1 args2 ->
  oval_inject (as_inj j') rv1 rv2 ->
  match_event ev1 ev2.Inductive match_event : Event.t -> Event.t -> Prop :=
| mk_match_event :
  forall j j' ev1 ev2,
  let args1 := ev1.(args) in
  let args2 := ev2.(args) in
  let rv1 := ev1.(rv) in
  let rv2 := ev2.(rv) in
  let m1 := ev1.(pre_mem) in
  let m1' := ev1.(post_mem) in
  let m2 := ev2.(pre_mem) in
  let m2' := ev2.(post_mem) in
  inject_incr (as_inj j) (as_inj j') ->
  Mem.inject (as_inj j) m1 m2 ->
  Mem.inject (as_inj j') m1' m2' ->
  Forall2 (val_inject (as_inj j)) args1 args2 ->
  oval_inject (as_inj j') rv1 rv2 ->
  match_event ev1 ev2.Inductive match_event : Event.t -> Event.t -> Prop :=
| mk_match_event :
  forall j j' ev1 ev2,
  let args1 := ev1.(args) in
  let args2 := ev2.(args) in
  let rv1 := ev1.(rv) in
  let rv2 := ev2.(rv) in
  let m1 := ev1.(pre_mem) in
  let m1' := ev1.(post_mem) in
  let m2 := ev2.(pre_mem) in
  let m2' := ev2.(post_mem) in
  inject_incr (as_inj j) (as_inj j') ->
  Mem.inject (as_inj j) m1 m2 ->
  Mem.inject (as_inj j') m1' m2' ->
  Forall2 (val_inject (as_inj j)) args1 args2 ->
  oval_inject (as_inj j') rv1 rv2 ->
  match_event ev1 ev2.Inductive match_event : Event.t -> Event.t -> Prop :=
| mk_match_event :
  forall j j' ev1 ev2,
  let args1 := ev1.(args) in
  let args2 := ev2.(args) in
  let rv1 := ev1.(rv) in
  let rv2 := ev2.(rv) in
  let m1 := ev1.(pre_mem) in
  let m1' := ev1.(post_mem) in
  let m2 := ev2.(pre_mem) in
  let m2' := ev2.(post_mem) in
  inject_incr (as_inj j) (as_inj j') ->
  Mem.inject (as_inj j) m1 m2 ->
  Mem.inject (as_inj j') m1' m2' ->
  Forall2 (val_inject (as_inj j)) args1 args2 ->
  oval_inject (as_inj j') rv1 rv2 ->
  match_event ev1 ev2.Inductive match_event : Event.t -> Event.t -> Prop :=
| mk_match_event :
  forall j j' ev1 ev2,
  let args1 := ev1.(args) in
  let args2 := ev2.(args) in
  let rv1 := ev1.(rv) in
  let rv2 := ev2.(rv) in
  let m1 := ev1.(pre_mem) in
  let m1' := ev1.(post_mem) in
  let m2 := ev2.(pre_mem) in
  let m2' := ev2.(post_mem) in
  inject_incr (as_inj j) (as_inj j') ->
  Mem.inject (as_inj j) m1 m2 ->
  Mem.inject (as_inj j') m1' m2' ->
  Forall2 (val_inject (as_inj j)) args1 args2 ->
  oval_inject (as_inj j') rv1 rv2 ->
  match_event ev1 ev2.Inductive match_trace : list Event.t -> list Event.t -> Prop :=
| match_trace_nil : match_trace nil nil
| match_trace_cons :
  forall tr1 tr2 ev1 ev2,
  match_event ev1 ev2 ->
  match_trace tr1 tr2 ->
  match_trace (ev1 :: tr1) (ev2 :: tr2).Inductive match_trace : list Event.t -> list Event.t -> Prop :=
| match_trace_nil : match_trace nil nil
| match_trace_cons :
  forall tr1 tr2 ev1 ev2,
  match_event ev1 ev2 ->
  match_trace tr1 tr2 ->
  match_trace (ev1 :: tr1) (ev2 :: tr2).Inductive match_trace : list Event.t -> list Event.t -> Prop :=
| match_trace_nil : match_trace nil nil
| match_trace_cons :
  forall tr1 tr2 ev1 ev2,
  match_event ev1 ev2 ->
  match_trace tr1 tr2 ->
  match_trace (ev1 :: tr1) (ev2 :: tr2).Notation data := (sim.(SM_simulation.core_data _ _ _ _ _)).Notation ord  := (sim.(SM_simulation.core_ord _ _ _ _ _)).Notation match_state := (sim.(SM_simulation.match_state _ _ _ _ _)).Inductive trace_match_state :
  data -> SM_Injection -> Z*list Event.t*C -> mem ->
                          Z*list Event.t*D -> mem -> Prop :=
| mk_trace_match_state :
  forall j tr z c m ttr d tm cd,
  match_trace tr ttr ->
  match_state cd j c m d tm ->
  trace_match_state cd j (z,tr,c) m (z,ttr,d) tm.Inductive trace_match_state :
  data -> SM_Injection -> Z*list Event.t*C -> mem ->
                          Z*list Event.t*D -> mem -> Prop :=
| mk_trace_match_state :
  forall j tr z c m ttr d tm cd,
  match_trace tr ttr ->
  match_state cd j c m d tm ->
  trace_match_state cd j (z,tr,c) m (z,ttr,d) tm.

Lemma corestep_matchN {c m d tm c' m' cd j n} : corestepN source geS n c m c' m' -> match_state cd j c m d tm -> exists d' tm' cd' j' n', corestepN target geT n' d tm d' tm' /\ match_state cd' j' c' m' d' tm'.