Section RAB.
Context {A B : Type}.
Context (RAB : A -> B -> Prop).  (* relation on Imp / Asm values *)
Definition state_invariant (a : Imp.env * A) (b : Asm.memory * (Asm.registers * B))  :=
Renv (fst a) (fst b) /\ (RAB (snd a) (snd (snd b))).
Definition bisimilar {E} (t1 : itree (ImpState +' E) A) (t2 : itree (Reg +' Memory +' E) B)  :=
forall g_asm g_imp l,
Renv g_imp g_asm ->
eutt state_invariant
(interp_imp t1 g_imp)
(interp_asm t2 g_asm l).
End RAB.
(** [bisimilar] is compatible with [eutt]. *)
Global Instance eutt_bisimilar  {A B E}  (RAB : A -> B -> Prop):
Proper (eutt eq ==> eutt eq ==> iff) (@bisimilar A B RAB E).

Lemma bisimilar_bind' {A A' B C E} (RAA' : A -> A' -> Prop) (RBC: B -> C -> Prop):
forall (t1 : itree (ImpState +' E) A) (t2 : itree (Reg +' Memory +' E) A') ,
bisimilar RAA' t1 t2 ->
forall (k1 : A -> itree (ImpState +' E) B) (k2 : A' -> itree (Reg +' Memory +' E) C)
(H: forall (a:A) (a':A'), RAA' a a' -> bisimilar RBC (k1 a) (k2 a')),
bisimilar RBC (t1 >>= k1) (t2 >>= k2).