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_iter {E A A' B B'}
(R : A -> A' -> Prop)
(S : B -> B' -> Prop)
(t1 : A -> itree (_ +' E) (A + B))
(t2 : A' -> itree (_ +' _ +' E) (A' + B')) :
(forall l l', R l l' -> bisimilar (sum_rel R S) (t1 l) (t2 l')) ->
forall x x', R x x' ->
bisimilar S (KTree.iter t1 x) (KTree.iter t2 x').