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 REACH_mono': forall B1 B2 : block -> bool, (forall b : block, B1 b = true -> B2 b = true) -> forall (m : mem) (b : block), REACH m B2 b = false -> REACH m B1 b = false.