Section SpecsCorrect.
Context `{ThreadsConfigurationOps}.
Definition user_trace (ot ot' : ostrace) : trace :=
trace_of_ostrace (strip_common_prefix IOEvent_eq ot ot').
Definition trace_itree_match (z0 z : IO_itree) (ot ot' : ostrace) :=
(* Compute the OS-generated trace of newly added events *)
let ot_new := strip_common_prefix IOEvent_eq ot ot' in
(* Filter out the user-invisible events *)
let t := trace_of_ostrace ot_new in
(* The new itree 'consumed' the OS-generated trace *)
consume_trace z0 z t.
Variable block_to_addr : block -> Z.
Definition mem_to_flatmem (f : flatmem) (m : mem) (b : block) (ofs len : Z) : flatmem :=
let contents := getN (Z.to_nat len) ofs (m.(mem_contents) !! b) in
let addr := block_to_addr b + ofs in
FlatMem.setN contents addr f.
Program Definition flatmem_to_mem (f : flatmem) (m : mem) (b : block) (ofs len : Z) : mem :=
let (cont, acc, nxt, amax, nxt_no, _) := m in
let addr := block_to_addr b + ofs in
let bytes := FlatMem.getN (Z.to_nat len) addr f in
let contents := setN bytes ofs (cont !! b) in
mkmem (PMap.set b contents cont) acc nxt amax nxt_no _.
Next Obligation.
cbn; intros; destruct (Pos.eq_dec b b0) eqn:?; subst.
- rewrite PMap.gss, setN_default; auto.
- rewrite PMap.gso; auto.
Defined.
Record R_sys_getc_correct k z m st st' ret := {
(* New itree is old k applied to result, or same as old itree if nothing to read *)
getc_z' := if 0 <=? Int.signed ret then k (Byte.repr (Int.signed ret)) else z;
(* Post condition holds on new state, itree, and result *)
getc_post_ok : getchar_post' m m ret (k, z) getc_z';
(* The itrees and OS traces agree on the external events *)
getc_itree_trace_ok : trace_itree_match z getc_z' st.(io_log) st'.(io_log);
(* The new trace is valid *)
getc_trace_ok : valid_trace st';
(* The memory is unchanged *)
getc_mem_ok : st.(HP) = st'.(HP)
}.
(* Initial trace is valid *)
(* Pre condition holds *)
(* sys_getc returns some state *)
Record R_sys_putc_correct c k z m st st' ret := {
(* New itree is old k, or same as old itree if send failed *)
putc_z' := if 0 <=? Int.signed ret then k else z;
(* Post condition holds on new state, itree, and result *)
putc_post_ok : putchar_post m m ret (c, k) putc_z';
(* The itrees and OS traces agree on the external events *)
putc_itree_trace_ok : trace_itree_match z putc_z' st.(io_log) st'.(io_log);
(* The new trace is valid *)
(* TODO: have to define valid trace condition for putc *)
putc_trace_ok : valid_trace st';
(* The memory is unchanged *)
putc_mem_ok : st.(HP) = st'.(HP)
}.
(* Initial trace is valid *)
(* Pre condition holds *)
(* c is passed as an argument *)
(* sys_putc returns some state *)
(* TODO: memory *)
Record R_sys_getcs_correct sh buf len k z m st st' ret := {
vals := nil; (* TODO *)
getcs_z' := if 0 <=? Int.signed ret then k vals else z;
(* Post condition holds on new state, itree, and result *)
getcs_post_ok : getchars_post m m ret (sh, buf, len, k) getcs_z';
(* The itrees and OS traces agree on the external events *)
getcs_itree_trace_ok : trace_itree_match z getcs_z' st.(io_log) st'.(io_log);
(* The new trace is valid *)
getcs_trace_ok : valid_trace st';
(* The memory has changed *)
(* TODO *)
(* getcs_mem_ok : st.(HP) = st'.(HP) *)
}.

Lemma sys_getcs_correct sh buf ofs len k z m st st' :
let addr := block_to_addr buf + Ptrofs.unsigned ofs in
valid_trace st ->
getchars_pre m (sh, Vptr buf ofs, len, k) z ->
get_sys_arg1 st = Vint (Int.repr addr) ->
get_sys_arg2 st = Vint (Int.repr len) ->
sys_getcs_spec st = Some st' ->
exists ret,
get_sys_ret st' = Vint ret /\
R_sys_getcs_correct sh (Vptr buf ofs) len k z m st st' ret.