aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/basic-block-generation.org497
-rw-r--r--docs/scheduler-languages.org682
-rw-r--r--docs/scheduler.org2317
3 files changed, 0 insertions, 3496 deletions
diff --git a/docs/basic-block-generation.org b/docs/basic-block-generation.org
deleted file mode 100644
index 1d78dad..0000000
--- a/docs/basic-block-generation.org
+++ /dev/null
@@ -1,497 +0,0 @@
-#+title: Basic Block Generation
-#+author: Yann Herklotz
-#+email: yann [at] yannherklotz [dot] com
-
-* RTLBlockgen
-:PROPERTIES:
-:header-args:coq: :comments noweb :noweb no-export :padline yes :tangle ../src/hls/RTLBlockgen.v
-:END:
-
-Refers to [[rtlblockgen-equalities][rtlblockgen-equalities]].
-
-#+begin_src coq :comments no :padline no :exports none
-<<license>>
-#+end_src
-
-#+name: rtlblockgen-imports
-#+begin_src coq
-Require compcert.backend.RTL.
-Require Import compcert.common.AST.
-Require Import compcert.lib.Maps.
-Require Import compcert.lib.Integers.
-Require Import compcert.lib.Floats.
-
-Require Import vericert.common.Vericertlib.
-Require Import vericert.hls.RTLBlockInstr.
-Require Import vericert.hls.RTLBlock.
-
-#[local] Open Scope positive.
-#+end_src
-
-#+name: rtlblockgen-equalities-insert
-#+begin_src coq :comments no
-<<rtlblockgen-equalities>>
-#+end_src
-
-#+name: rtlblockgen-main
-#+begin_src coq
-Parameter partition : RTL.function -> Errors.res function.
-
-(** [find_block max nodes index]: Does not need to be sorted, because we use filter and the max fold
- function to find the desired element. *)
-Definition find_block (max: positive) (nodes: list positive) (index: positive) : positive :=
- List.fold_right Pos.min max (List.filter (fun x => (index <=? x)) nodes).
-
-(*Compute find_block (2::94::28::40::19::nil) 40.*)
-
-Definition check_instr (n: positive) (istr: RTL.instruction) (istr': instr) :=
- match istr, istr' with
- | RTL.Inop n', RBnop => (n' + 1 =? n)
- | RTL.Iop op args dst n', RBop None op' args' dst' =>
- ceq operation_eq op op' &&
- ceq list_pos_eq args args' &&
- ceq peq dst dst' && (n' + 1 =? n)
- | RTL.Iload chunk addr args dst n', RBload None chunk' addr' args' dst' =>
- ceq memory_chunk_eq chunk chunk' &&
- ceq addressing_eq addr addr' &&
- ceq list_pos_eq args args' &&
- ceq peq dst dst' &&
- (n' + 1 =? n)
- | RTL.Istore chunk addr args src n', RBstore None chunk' addr' args' src' =>
- ceq memory_chunk_eq chunk chunk' &&
- ceq addressing_eq addr addr' &&
- ceq list_pos_eq args args' &&
- ceq peq src src' &&
- (n' + 1 =? n)
- | _, _ => false
- end.
-
-Definition check_cf_instr_body (istr: RTL.instruction) (istr': instr): bool :=
- match istr, istr' with
- | RTL.Iop op args dst _, RBop None op' args' dst' =>
- ceq operation_eq op op' &&
- ceq list_pos_eq args args' &&
- ceq peq dst dst'
- | RTL.Iload chunk addr args dst _, RBload None chunk' addr' args' dst' =>
- ceq memory_chunk_eq chunk chunk' &&
- ceq addressing_eq addr addr' &&
- ceq list_pos_eq args args' &&
- ceq peq dst dst'
- | RTL.Istore chunk addr args src _, RBstore None chunk' addr' args' src' =>
- ceq memory_chunk_eq chunk chunk' &&
- ceq addressing_eq addr addr' &&
- ceq list_pos_eq args args' &&
- ceq peq src src'
- | RTL.Inop _, RBnop
- | RTL.Icall _ _ _ _ _, RBnop
- | RTL.Itailcall _ _ _, RBnop
- | RTL.Ibuiltin _ _ _ _, RBnop
- | RTL.Icond _ _ _ _, RBnop
- | RTL.Ijumptable _ _, RBnop
- | RTL.Ireturn _, RBnop => true
- | _, _ => false
- end.
-
-Definition check_cf_instr (istr: RTL.instruction) (istr': cf_instr) :=
- match istr, istr' with
- | RTL.Inop n, RBgoto n' => (n =? n')
- | RTL.Iop _ _ _ n, RBgoto n' => (n =? n')
- | RTL.Iload _ _ _ _ n, RBgoto n' => (n =? n')
- | RTL.Istore _ _ _ _ n, RBgoto n' => (n =? n')
- | RTL.Icall sig (inl r) args dst n, RBcall sig' (inl r') args' dst' n' =>
- ceq signature_eq sig sig' &&
- ceq peq r r' &&
- ceq list_pos_eq args args' &&
- ceq peq dst dst' &&
- (n =? n')
- | RTL.Icall sig (inr i) args dst n, RBcall sig' (inr i') args' dst' n' =>
- ceq signature_eq sig sig' &&
- ceq peq i i' &&
- ceq list_pos_eq args args' &&
- ceq peq dst dst' &&
- (n =? n')
- | RTL.Itailcall sig (inl r) args, RBtailcall sig' (inl r') args' =>
- ceq signature_eq sig sig' &&
- ceq peq r r' &&
- ceq list_pos_eq args args'
- | RTL.Itailcall sig (inr r) args, RBtailcall sig' (inr r') args' =>
- ceq signature_eq sig sig' &&
- ceq peq r r' &&
- ceq list_pos_eq args args'
- | RTL.Icond cond args n1 n2, RBcond cond' args' n1' n2' =>
- ceq condition_eq cond cond' &&
- ceq list_pos_eq args args' &&
- ceq peq n1 n1' && ceq peq n2 n2'
- | RTL.Ijumptable r ns, RBjumptable r' ns' =>
- ceq peq r r' && ceq list_pos_eq ns ns'
- | RTL.Ireturn (Some r), RBreturn (Some r') =>
- ceq peq r r'
- | RTL.Ireturn None, RBreturn None => true
- | _, _ => false
- end.
-
-Definition is_cf_instr (n: positive) (i: RTL.instruction) :=
- match i with
- | RTL.Inop n' => negb (n' + 1 =? n)
- | RTL.Iop _ _ _ n' => negb (n' + 1 =? n)
- | RTL.Iload _ _ _ _ n' => negb (n' + 1 =? n)
- | RTL.Istore _ _ _ _ n' => negb (n' + 1 =? n)
- | RTL.Icall _ _ _ _ _ => true
- | RTL.Itailcall _ _ _ => true
- | RTL.Ibuiltin _ _ _ _ => true
- | RTL.Icond _ _ _ _ => true
- | RTL.Ijumptable _ _ => true
- | RTL.Ireturn _ => true
- end.
-
-Definition check_present_blocks (c: code) (n: list positive) (max: positive) (i: positive) (istr: RTL.instruction) :=
- let blockn := find_block max n i in
- match c ! blockn with
- | Some istrs =>
- match List.nth_error istrs.(bb_body) (Pos.to_nat blockn - Pos.to_nat i)%nat with
- | Some istr' =>
- if is_cf_instr i istr
- then check_cf_instr istr istrs.(bb_exit) && check_cf_instr_body istr istr'
- else check_instr i istr istr'
- | None => false
- end
- | None => false
- end.
-
-Definition transl_function (f: RTL.function) :=
- match partition f with
- | Errors.OK f' =>
- let blockids := map fst (PTree.elements f'.(fn_code)) in
- if forall_ptree (check_present_blocks f'.(fn_code) blockids (fold_right Pos.max 1 blockids))
- f.(RTL.fn_code) then
- Errors.OK f'
- else Errors.Error (Errors.msg "check_present_blocks failed")
- | Errors.Error msg => Errors.Error msg
- end.
-
-Definition transl_fundef := transf_partial_fundef transl_function.
-
-Definition transl_program : RTL.program -> Errors.res program :=
- transform_partial_program transl_fundef.
-#+end_src
-
-** Equalities
-
-#+name: rtlblockgen-equalities
-#+begin_src coq :tangle no
-Lemma comparison_eq: forall (x y : comparison), {x = y} + {x <> y}.
-Proof.
- decide equality.
-Defined.
-
-Lemma condition_eq: forall (x y : Op.condition), {x = y} + {x <> y}.
-Proof.
- generalize comparison_eq; intro.
- generalize Int.eq_dec; intro.
- generalize Int64.eq_dec; intro.
- decide equality.
-Defined.
-
-Lemma addressing_eq : forall (x y : Op.addressing), {x = y} + {x <> y}.
-Proof.
- generalize Int.eq_dec; intro.
- generalize AST.ident_eq; intro.
- generalize Z.eq_dec; intro.
- generalize Ptrofs.eq_dec; intro.
- decide equality.
-Defined.
-
-Lemma typ_eq : forall (x y : AST.typ), {x = y} + {x <> y}.
-Proof.
- decide equality.
-Defined.
-
-Lemma operation_eq: forall (x y : Op.operation), {x = y} + {x <> y}.
-Proof.
- generalize Int.eq_dec; intro.
- generalize Int64.eq_dec; intro.
- generalize Float.eq_dec; intro.
- generalize Float32.eq_dec; intro.
- generalize AST.ident_eq; intro.
- generalize condition_eq; intro.
- generalize addressing_eq; intro.
- generalize typ_eq; intro.
- decide equality.
-Defined.
-
-Lemma memory_chunk_eq : forall (x y : AST.memory_chunk), {x = y} + {x <> y}.
-Proof.
- decide equality.
-Defined.
-
-Lemma list_typ_eq: forall (x y : list AST.typ), {x = y} + {x <> y}.
-Proof.
- generalize typ_eq; intro.
- decide equality.
-Defined.
-
-Lemma option_typ_eq : forall (x y : option AST.typ), {x = y} + {x <> y}.
-Proof.
- generalize typ_eq; intro.
- decide equality.
-Defined.
-
-Lemma signature_eq: forall (x y : AST.signature), {x = y} + {x <> y}.
-Proof.
- repeat decide equality.
-Defined.
-
-Lemma list_operation_eq : forall (x y : list Op.operation), {x = y} + {x <> y}.
-Proof.
- generalize operation_eq; intro.
- decide equality.
-Defined.
-
-Lemma list_pos_eq : forall (x y : list positive), {x = y} + {x <> y}.
-Proof.
- generalize Pos.eq_dec; intros.
- decide equality.
-Defined.
-
-Lemma sig_eq : forall (x y : AST.signature), {x = y} + {x <> y}.
-Proof.
- repeat decide equality.
-Defined.
-
-Lemma instr_eq: forall (x y : instr), {x = y} + {x <> y}.
-Proof.
- generalize Pos.eq_dec; intro.
- generalize typ_eq; intro.
- generalize Int.eq_dec; intro.
- generalize memory_chunk_eq; intro.
- generalize addressing_eq; intro.
- generalize operation_eq; intro.
- generalize condition_eq; intro.
- generalize signature_eq; intro.
- generalize list_operation_eq; intro.
- generalize list_pos_eq; intro.
- generalize AST.ident_eq; intro.
- repeat decide equality.
-Defined.
-
-Lemma cf_instr_eq: forall (x y : cf_instr), {x = y} + {x <> y}.
-Proof.
- generalize Pos.eq_dec; intro.
- generalize typ_eq; intro.
- generalize Int.eq_dec; intro.
- generalize Int64.eq_dec; intro.
- generalize Float.eq_dec; intro.
- generalize Float32.eq_dec; intro.
- generalize Ptrofs.eq_dec; intro.
- generalize memory_chunk_eq; intro.
- generalize addressing_eq; intro.
- generalize operation_eq; intro.
- generalize condition_eq; intro.
- generalize signature_eq; intro.
- generalize list_operation_eq; intro.
- generalize list_pos_eq; intro.
- generalize AST.ident_eq; intro.
- repeat decide equality.
-Defined.
-
-Definition ceq {A: Type} (eqd: forall a b: A, {a = b} + {a <> b}) (a b: A): bool :=
- if eqd a b then true else false.
-#+end_src
-
-* RTLBlockgenproof
-:PROPERTIES:
-:header-args:coq: :comments noweb :noweb no-export :padline yes :tangle ../src/hls/RTLBlockgenproof.v
-:END:
-
-#+begin_src coq :comments no :padline no :exports none
-<<license>>
-#+end_src
-
-** Imports
-
-#+name: rtlblockgenproof-imports
-#+begin_src coq
-Require compcert.backend.RTL.
-Require Import compcert.common.AST.
-Require Import compcert.lib.Maps.
-
-Require Import vericert.hls.RTLBlock.
-Require Import vericert.hls.RTLBlockgen.
-#+end_src
-
-** Match states
-
-The ~match_states~ predicate describes which states are equivalent between the two languages, in this
-case ~RTL~ and ~RTLBlock~.
-
-#+name: rtlblockgenproof-match-states
-#+begin_src coq
-Inductive match_states : RTL.state -> RTLBlock.state -> Prop :=
-| match_state :
- forall stk f tf sp pc rs m
- (TF: transl_function f = OK tf),
- match_states (RTL.State stk f sp pc rs m)
- (RTLBlock.State stk tf sp (find_block max n i) rs m).
-#+end_src
-
-** Correctness
-
-#+name: rtlblockgenproof-correctness
-#+begin_src coq
-Section CORRECTNESS.
-
- Context (prog : RTL.program).
- Context (tprog : RTLBlock.program).
-
- Context (TRANSL : match_prog prog tprog).
-
- Theorem transf_program_correct:
- Smallstep.forward_simulation (RTL.semantics prog) (RTLBlock.semantics tprog).
- Proof.
- eapply Smallstep.forward_simulation_plus; eauto with htlproof.
- apply senv_preserved.
-
-End CORRECTNESS.
-#+end_src
-
-* Partition
-:PROPERTIES:
-:header-args:ocaml: :comments noweb :noweb no-export :padline yes :tangle ../src/hls/Partition.ml
-:END:
-
-#+begin_src ocaml :comments no :padline no :exports none
-<<license>>
-#+end_src
-
-#+name: partition-main
-#+begin_src ocaml
-open Printf
-open Clflags
-open Camlcoq
-open Datatypes
-open Coqlib
-open Maps
-open AST
-open Kildall
-open Op
-open RTLBlockInstr
-open RTLBlock
-
-(** Assuming that the nodes of the CFG [code] are numbered in reverse postorder (cf. pass
- [Renumber]), an edge from [n] to [s] is a normal edge if [s < n] and a back-edge otherwise. *)
-let find_edge i n =
- let succ = RTL.successors_instr i in
- let filt = List.filter (fun s -> P.lt n s || P.lt s (P.pred n)) succ in
- ((match filt with [] -> [] | _ -> [n]), filt)
-
-let find_edges c =
- PTree.fold (fun l n i ->
- let f = find_edge i n in
- (List.append (fst f) (fst l), List.append (snd f) (snd l))) c ([], [])
-
-let prepend_instr i = function
- | {bb_body = bb; bb_exit = e} -> {bb_body = (i :: bb); bb_exit = e}
-
-let translate_inst = function
- | RTL.Inop _ -> Some RBnop
- | RTL.Iop (op, ls, dst, _) -> Some (RBop (None, op, ls, dst))
- | RTL.Iload (m, addr, ls, dst, _) -> Some (RBload (None, m, addr, ls, dst))
- | RTL.Istore (m, addr, ls, src, _) -> Some (RBstore (None, m, addr, ls, src))
- | _ -> None
-
-let translate_cfi = function
- | RTL.Icall (s, r, ls, dst, n) -> Some (RBcall (s, r, ls, dst, n))
- | RTL.Itailcall (s, r, ls) -> Some (RBtailcall (s, r, ls))
- | RTL.Ibuiltin (e, ls, r, n) -> Some (RBbuiltin (e, ls, r, n))
- | RTL.Icond (c, ls, dst1, dst2) -> Some (RBcond (c, ls, dst1, dst2))
- | RTL.Ijumptable (r, ls) -> Some (RBjumptable (r, ls))
- | RTL.Ireturn r -> Some (RBreturn r)
- | _ -> None
-
-let rec next_bblock_from_RTL is_start e (c : RTL.code) s i =
- let succ = List.map (fun i -> (i, PTree.get i c)) (RTL.successors_instr i) in
- let trans_inst = (translate_inst i, translate_cfi i) in
- match trans_inst, succ with
- | (None, Some i'), _ ->
- if List.exists (fun x -> x = s) (snd e) && not is_start then
- Errors.OK { bb_body = [RBnop]; bb_exit = RBgoto s }
- else
- Errors.OK { bb_body = [RBnop]; bb_exit = i' }
- | (Some i', None), (s', Some i_n)::[] ->
- if List.exists (fun x -> x = s) (fst e) then
- Errors.OK { bb_body = [i']; bb_exit = RBgoto s' }
- else if List.exists (fun x -> x = s) (snd e) && not is_start then
- Errors.OK { bb_body = [RBnop]; bb_exit = RBgoto s }
- else begin
- match next_bblock_from_RTL false e c s' i_n with
- | Errors.OK bb ->
- Errors.OK (prepend_instr i' bb)
- | Errors.Error msg -> Errors.Error msg
- end
- | _, _ ->
- Errors.Error (Errors.msg (coqstring_of_camlstring "next_bblock_from_RTL went wrong."))
-
-let rec traverseacc f l c =
- match l with
- | [] -> Errors.OK c
- | x::xs ->
- match f x c with
- | Errors.Error msg -> Errors.Error msg
- | Errors.OK x' ->
- match traverseacc f xs x' with
- | Errors.Error msg -> Errors.Error msg
- | Errors.OK xs' -> Errors.OK xs'
-
-let rec translate_all edge c s res =
- let c_bb, translated = res in
- if List.exists (fun x -> P.eq x s) translated then Errors.OK (c_bb, translated) else
- (match PTree.get s c with
- | None -> Errors.Error (Errors.msg (coqstring_of_camlstring "Could not translate all."))
- | Some i ->
- match next_bblock_from_RTL true edge c s i with
- | Errors.Error msg -> Errors.Error msg
- | Errors.OK {bb_body = bb; bb_exit = e} ->
- let succ = List.filter (fun x -> P.lt x s) (successors_instr e) in
- (match traverseacc (translate_all edge c) succ (c_bb, s :: translated) with
- | Errors.Error msg -> Errors.Error msg
- | Errors.OK (c', t') ->
- Errors.OK (PTree.set s {bb_body = bb; bb_exit = e} c', t')))
-
-(* Partition a function and transform it into RTLBlock. *)
-let function_from_RTL f =
- let e = find_edges f.RTL.fn_code in
- match translate_all e f.RTL.fn_code f.RTL.fn_entrypoint (PTree.empty, []) with
- | Errors.Error msg -> Errors.Error msg
- | Errors.OK (c, _) ->
- Errors.OK { fn_sig = f.RTL.fn_sig;
- fn_stacksize = f.RTL.fn_stacksize;
- fn_params = f.RTL.fn_params;
- fn_entrypoint = f.RTL.fn_entrypoint;
- fn_code = c
- }
-
-let partition = function_from_RTL
-#+end_src
-
-* License
-
-#+name: license
-#+begin_src coq :tangle no
-(*
- * Vericert: Verified high-level synthesis.
- * Copyright (C) 2020-2022 Yann Herklotz <yann@yannherklotz.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *)
-#+end_src
diff --git a/docs/scheduler-languages.org b/docs/scheduler-languages.org
deleted file mode 100644
index 02249f8..0000000
--- a/docs/scheduler-languages.org
+++ /dev/null
@@ -1,682 +0,0 @@
-#+title: Scheduler Languages
-#+author: Yann Herklotz
-#+email: yann [at] yannherklotz [dot] com
-
-* RTLBlockInstr
-:PROPERTIES:
-:header-args:coq: :comments noweb :noweb no-export :padline yes :tangle ../src/hls/RTLBlockInstr.v
-:END:
-
-#+begin_src coq :comments no :padline no :exports none
-<<license>>
-#+end_src
-
-#+name: rtlblockinstr-imports
-#+begin_src coq
-Require Import Coq.micromega.Lia.
-
-Require Import compcert.backend.Registers.
-Require Import compcert.common.AST.
-Require Import compcert.common.Events.
-Require Import compcert.common.Globalenvs.
-Require Import compcert.common.Memory.
-Require Import compcert.common.Values.
-Require Import compcert.lib.Integers.
-Require Import compcert.lib.Maps.
-Require Import compcert.verilog.Op.
-
-Require Import Predicate.
-Require Import Vericertlib.
-#+end_src
-
-These instructions are used for ~RTLBlock~ and ~RTLPar~, so that they have consistent instructions,
-which greatly simplifies the proofs, as they will by default have the same instruction syntax and
-semantics. The only changes are therefore at the top-level of the instructions.
-
-** Instruction Definition
-
-First, we define the instructions that can be placed into a basic block, meaning they won't branch.
-The main changes to how instructions are defined in [RTL], is that these instructions don't have a
-next node, as they will be in a basic block, and they also have an optional predicate ([pred_op]).
-
-#+name: rtlblockinstr-instr-def
-#+begin_src coq
-Definition node := positive.
-
-Inductive instr : Type :=
-| RBnop : instr
-| RBop : option pred_op -> operation -> list reg -> reg -> instr
-| RBload : option pred_op -> memory_chunk -> addressing -> list reg -> reg -> instr
-| RBstore : option pred_op -> memory_chunk -> addressing -> list reg -> reg -> instr
-| RBsetpred : option pred_op -> condition -> list reg -> predicate -> instr.
-#+end_src
-
-** Control-Flow Instruction Definition
-
-These are the instructions that count as control-flow, and will be placed at the end of the basic
-blocks.
-
-#+name: rtlblockinstr-cf-instr-def
-#+begin_src coq
-Inductive cf_instr : Type :=
-| RBcall : signature -> reg + ident -> list reg -> reg -> node -> cf_instr
-| RBtailcall : signature -> reg + ident -> list reg -> cf_instr
-| RBbuiltin : external_function -> list (builtin_arg reg) ->
- builtin_res reg -> node -> cf_instr
-| RBcond : condition -> list reg -> node -> node -> cf_instr
-| RBjumptable : reg -> list node -> cf_instr
-| RBreturn : option reg -> cf_instr
-| RBgoto : node -> cf_instr
-| RBpred_cf : pred_op -> cf_instr -> cf_instr -> cf_instr.
-#+end_src
-
-** Helper functions
-
-#+name: rtlblockinstr-helpers
-#+begin_src coq
-Fixpoint successors_instr (i : cf_instr) : list node :=
- match i with
- | RBcall sig ros args res s => s :: nil
- | RBtailcall sig ros args => nil
- | RBbuiltin ef args res s => s :: nil
- | RBcond cond args ifso ifnot => ifso :: ifnot :: nil
- | RBjumptable arg tbl => tbl
- | RBreturn optarg => nil
- | RBgoto n => n :: nil
- | RBpred_cf p c1 c2 => concat (successors_instr c1 :: successors_instr c2 :: nil)
- end.
-
-Definition max_reg_instr (m: positive) (i: instr) :=
- match i with
- | RBnop => m
- | RBop p op args res =>
- fold_left Pos.max args (Pos.max res m)
- | RBload p chunk addr args dst =>
- fold_left Pos.max args (Pos.max dst m)
- | RBstore p chunk addr args src =>
- fold_left Pos.max args (Pos.max src m)
- | RBsetpred p' c args p =>
- fold_left Pos.max args m
- end.
-
-Fixpoint max_reg_cfi (m : positive) (i : cf_instr) :=
- match i with
- | RBcall sig (inl r) args res s =>
- fold_left Pos.max args (Pos.max r (Pos.max res m))
- | RBcall sig (inr id) args res s =>
- fold_left Pos.max args (Pos.max res m)
- | RBtailcall sig (inl r) args =>
- fold_left Pos.max args (Pos.max r m)
- | RBtailcall sig (inr id) args =>
- fold_left Pos.max args m
- | RBbuiltin ef args res s =>
- fold_left Pos.max (params_of_builtin_args args)
- (fold_left Pos.max (params_of_builtin_res res) m)
- | RBcond cond args ifso ifnot => fold_left Pos.max args m
- | RBjumptable arg tbl => Pos.max arg m
- | RBreturn None => m
- | RBreturn (Some arg) => Pos.max arg m
- | RBgoto n => m
- | RBpred_cf p c1 c2 => Pos.max (max_reg_cfi m c1) (max_reg_cfi m c2)
- end.
-
-Definition regset := Regmap.t val.
-Definition predset := PMap.t bool.
-
-Definition eval_predf (pr: predset) (p: pred_op) :=
- sat_predicate p (fun x => pr !! (Pos.of_nat x)).
-
-#[global]
-Instance eval_predf_Proper : Proper (eq ==> equiv ==> eq) eval_predf.
-Proof.
- unfold Proper. simplify. unfold "==>".
- intros.
- unfold sat_equiv in *. intros. unfold eval_predf. subst. apply H0.
-Qed.
-
-#[local] Open Scope pred_op.
-
-Lemma eval_predf_Pand :
- forall ps p p',
- eval_predf ps (p ∧ p') = eval_predf ps p && eval_predf ps p'.
-Proof. unfold eval_predf; split; simplify; auto with bool. Qed.
-
-Lemma eval_predf_Por :
- forall ps p p',
- eval_predf ps (p ∨ p') = eval_predf ps p || eval_predf ps p'.
-Proof. unfold eval_predf; split; simplify; auto with bool. Qed.
-
-Lemma eval_predf_pr_equiv :
- forall p ps ps',
- (forall x, ps !! x = ps' !! x) ->
- eval_predf ps p = eval_predf ps' p.
-Proof.
- induction p; simplify; auto;
- try (unfold eval_predf; simplify; repeat (destruct_match; []); inv Heqp0; rewrite <- H; auto);
- [repeat rewrite eval_predf_Pand|repeat rewrite eval_predf_Por];
- erewrite IHp1; try eassumption; erewrite IHp2; eauto.
-Qed.
-
-Fixpoint init_regs (vl: list val) (rl: list reg) {struct rl} : regset :=
- match rl, vl with
- | r1 :: rs, v1 :: vs => Regmap.set r1 v1 (init_regs vs rs)
- | _, _ => Regmap.init Vundef
- end.
-#+end_src
-
-*** Instruction State
-
-Definition of the instruction state, which contains the following:
-
-- ~is_rs~ :: This is the current state of the registers.
-- ~is_ps~ :: This is the current state of the predicate registers, which is in a separate namespace
- and area compared to the standard registers in [is_rs].
-- ~is_mem~ :: The current state of the memory.
-
-#+name: rtlblockinstr-instr-state
-#+begin_src coq
-Record instr_state := mk_instr_state {
- is_rs: regset;
- is_ps: predset;
- is_mem: mem;
-}.
-#+end_src
-
-** Top-Level Type Definitions
-
-#+name: rtlblockinstr-type-def
-#+begin_src coq
-Section DEFINITION.
-
- Context {bblock_body: Type}.
-
- Record bblock : Type := mk_bblock {
- bb_body: bblock_body;
- bb_exit: cf_instr
- }.
-
- Definition code: Type := PTree.t bblock.
-
- Record function: Type := mkfunction {
- fn_sig: signature;
- fn_params: list reg;
- fn_stacksize: Z;
- fn_code: code;
- fn_entrypoint: node
- }.
-
- Definition fundef := AST.fundef function.
-
- Definition program := AST.program fundef unit.
-
- Definition funsig (fd: fundef) :=
- match fd with
- | Internal f => fn_sig f
- | External ef => ef_sig ef
- end.
-
- Inductive stackframe : Type :=
- | Stackframe:
- forall (res: reg) (**r where to store the result *)
- (f: function) (**r calling function *)
- (sp: val) (**r stack pointer in calling function *)
- (pc: node) (**r program point in calling function *)
- (rs: regset) (**r register state in calling function *)
- (pr: predset), (**r predicate state of the calling function *)
- stackframe.
-#+end_src
-
-*** State definition
-:PROPERTIES:
-:CUSTOM_ID: state
-:END:
-
-Definition of the ~state~ type, which is used by the ~step~ functions.
-
-#+name: rtlblockinstr-state
-#+begin_src coq
- Variant state : Type :=
- | State:
- forall (stack: list stackframe) (**r call stack *)
- (f: function) (**r current function *)
- (sp: val) (**r stack pointer *)
- (pc: node) (**r current program point in [c] *)
- (rs: regset) (**r register state *)
- (pr: predset) (**r predicate register state *)
- (m: mem), (**r memory state *)
- state
- | Callstate:
- forall (stack: list stackframe) (**r call stack *)
- (f: fundef) (**r function to call *)
- (args: list val) (**r arguments to the call *)
- (m: mem), (**r memory state *)
- state
- | Returnstate:
- forall (stack: list stackframe) (**r call stack *)
- (v: val) (**r return value for the call *)
- (m: mem), (**r memory state *)
- state.
-#+end_src
-
-#+name: rtlblockinstr-state
-#+begin_src coq
-End DEFINITION.
-#+end_src
-
-** Semantics
-
-#+name: rtlblockinstr-semantics
-#+begin_src coq
-Section RELSEM.
-
- Context {bblock_body : Type}.
-
- Definition genv := Genv.t (@fundef bblock_body) unit.
-
- Context (ge: genv).
-
- Definition find_function
- (ros: reg + ident) (rs: regset) : option fundef :=
- match ros with
- | inl r => Genv.find_funct ge rs#r
- | inr symb =>
- match Genv.find_symbol ge symb with
- | None => None
- | Some b => Genv.find_funct_ptr ge b
- end
- end.
-
- Inductive eval_pred: option pred_op -> instr_state -> instr_state -> instr_state -> Prop :=
- | eval_pred_true:
- forall i i' p,
- eval_predf (is_ps i) p = true ->
- eval_pred (Some p) i i' i'
- | eval_pred_false:
- forall i i' p,
- eval_predf (is_ps i) p = false ->
- eval_pred (Some p) i i' i
- | eval_pred_none:
- forall i i', eval_pred None i i' i.
-#+end_src
-
-*** Step a single instruction
-:PROPERTIES:
-:CUSTOM_ID: step_instr
-:END:
-
-#+name: rtlblockinstr-step_instr
-#+begin_src coq
- Inductive step_instr: val -> instr_state -> instr -> instr_state -> Prop :=
- | exec_RBnop:
- forall sp ist,
- step_instr sp ist RBnop ist
- | exec_RBop:
- forall op v res args rs m sp p ist pr,
- eval_operation ge sp op rs##args m = Some v ->
- eval_pred p (mk_instr_state rs pr m) (mk_instr_state (rs#res <- v) pr m) ist ->
- step_instr sp (mk_instr_state rs pr m) (RBop p op args res) ist
- | exec_RBload:
- forall addr rs args a chunk m v dst sp p pr ist,
- eval_addressing ge sp addr rs##args = Some a ->
- Mem.loadv chunk m a = Some v ->
- eval_pred p (mk_instr_state rs pr m) (mk_instr_state (rs#dst <- v) pr m) ist ->
- step_instr sp (mk_instr_state rs pr m) (RBload p chunk addr args dst) ist
- | exec_RBstore:
- forall addr rs args a chunk m src m' sp p pr ist,
- eval_addressing ge sp addr rs##args = Some a ->
- Mem.storev chunk m a rs#src = Some m' ->
- eval_pred p (mk_instr_state rs pr m) (mk_instr_state rs pr m') ist ->
- step_instr sp (mk_instr_state rs pr m) (RBstore p chunk addr args src) ist
- | exec_RBsetpred:
- forall sp rs pr m p c b args p' ist,
- Op.eval_condition c rs##args m = Some b ->
- eval_pred p' (mk_instr_state rs pr m) (mk_instr_state rs (pr#p <- b) m) ist ->
- step_instr sp (mk_instr_state rs pr m) (RBsetpred p' c args p) ist.
-#+end_src
-
-*** Step a control-flow instruction
-:PROPERTIES:
-:CUSTOM_ID: step_cf_instr
-:END:
-
-#+name: rtlblockinstr-step_cf_instr
-#+begin_src coq
- Inductive step_cf_instr: state -> cf_instr -> trace -> state -> Prop :=
- | exec_RBcall:
- forall s f sp rs m res fd ros sig args pc pc' pr,
- find_function ros rs = Some fd ->
- funsig fd = sig ->
- step_cf_instr (State s f sp pc rs pr m) (RBcall sig ros args res pc')
- E0 (Callstate (Stackframe res f sp pc' rs pr :: s) fd rs##args m)
- | exec_RBtailcall:
- forall s f stk rs m sig ros args fd m' pc pr,
- find_function ros rs = Some fd ->
- funsig fd = sig ->
- Mem.free m stk 0 f.(fn_stacksize) = Some m' ->
- step_cf_instr (State s f (Vptr stk Ptrofs.zero) pc rs pr m) (RBtailcall sig ros args)
- E0 (Callstate s fd rs##args m')
- | exec_RBbuiltin:
- forall s f sp rs m ef args res pc' vargs t vres m' pc pr,
- eval_builtin_args ge (fun r => rs#r) sp m args vargs ->
- external_call ef ge vargs m t vres m' ->
- step_cf_instr (State s f sp pc rs pr m) (RBbuiltin ef args res pc')
- t (State s f sp pc' (regmap_setres res vres rs) pr m')
- | exec_RBcond:
- forall s f sp rs m cond args ifso ifnot b pc pc' pr,
- eval_condition cond rs##args m = Some b ->
- pc' = (if b then ifso else ifnot) ->
- step_cf_instr (State s f sp pc rs pr m) (RBcond cond args ifso ifnot)
- E0 (State s f sp pc' rs pr m)
- | exec_RBjumptable:
- forall s f sp rs m arg tbl n pc pc' pr,
- rs#arg = Vint n ->
- list_nth_z tbl (Int.unsigned n) = Some pc' ->
- step_cf_instr (State s f sp pc rs pr m) (RBjumptable arg tbl)
- E0 (State s f sp pc' rs pr m)
- | exec_RBreturn:
- forall s f stk rs m or pc m' pr,
- Mem.free m stk 0 f.(fn_stacksize) = Some m' ->
- step_cf_instr (State s f (Vptr stk Ptrofs.zero) pc rs pr m) (RBreturn or)
- E0 (Returnstate s (regmap_optget or Vundef rs) m')
- | exec_RBgoto:
- forall s f sp pc rs pr m pc',
- step_cf_instr (State s f sp pc rs pr m) (RBgoto pc') E0 (State s f sp pc' rs pr m)
- | exec_RBpred_cf:
- forall s f sp pc rs pr m cf1 cf2 st' p t,
- step_cf_instr (State s f sp pc rs pr m) (if eval_predf pr p then cf1 else cf2) t st' ->
- step_cf_instr (State s f sp pc rs pr m) (RBpred_cf p cf1 cf2) t st'.
-#+end_src
-
-#+name: rtlblockinstr-end_RELSEM
-#+begin_src coq
-End RELSEM.
-#+end_src
-
-* RTLBlock
-:PROPERTIES:
-:header-args:coq: :comments noweb :noweb no-export :padline yes :tangle ../src/hls/RTLBlock.v
-:END:
-
-#+begin_src coq :comments no :padline no :exports none
-<<license>>
-#+end_src
-
-#+name: rtlblock-main
-#+begin_src coq
-Require Import compcert.backend.Registers.
-Require Import compcert.common.AST.
-Require Import compcert.common.Events.
-Require Import compcert.common.Globalenvs.
-Require Import compcert.common.Memory.
-Require Import compcert.common.Smallstep.
-Require Import compcert.common.Values.
-Require Import compcert.lib.Coqlib.
-Require Import compcert.lib.Integers.
-Require Import compcert.lib.Maps.
-Require Import compcert.verilog.Op.
-
-Require Import vericert.hls.RTLBlockInstr.
-
-Definition bb := list instr.
-
-Definition bblock := @bblock bb.
-Definition code := @code bb.
-Definition function := @function bb.
-Definition fundef := @fundef bb.
-Definition program := @program bb.
-Definition funsig := @funsig bb.
-Definition stackframe := @stackframe bb.
-Definition state := @state bb.
-
-Definition genv := @genv bb.
-#+end_src
-
-** Semantics
-
-We first describe the semantics by assuming a global program environment with type ~genv~ which was
-declared earlier.
-
-#+name: rtlblock-semantics
-#+begin_src coq
-Section RELSEM.
-
- Context (ge: genv).
-#+end_src
-
-*** Instruction list step
-:PROPERTIES:
-:CUSTOM_ID: step_instr_list
-:END:
-
-The ~step_instr_list~ definition describes the execution of a list of instructions in one big step,
-inductively traversing the list of instructions and applying the ~step_instr~ ([[#step_instr][step_instr]]).
-
-#+name: rtlblock-step_instr_list
-#+begin_src coq
- Inductive step_instr_list: val -> instr_state -> list instr -> instr_state -> Prop :=
- | exec_RBcons:
- forall state i state' state'' instrs sp,
- step_instr ge sp state i state' ->
- step_instr_list sp state' instrs state'' ->
- step_instr_list sp state (i :: instrs) state''
- | exec_RBnil:
- forall state sp,
- step_instr_list sp state nil state.
-#+end_src
-
-*** Top-level step
-:PROPERTIES:
-:CUSTOM_ID: rtlblock-step
-:END:
-
-The step function itself then uses this big step of the list of instructions to then show a
-transition from basic block to basic block.
-
-#+name: rtlblock-step
-#+begin_src coq
- Variant step: state -> trace -> state -> Prop :=
- | exec_bblock:
- forall s f sp pc rs rs' m m' t s' bb pr pr',
- f.(fn_code)!pc = Some bb ->
- step_instr_list sp (mk_instr_state rs pr m) bb.(bb_body) (mk_instr_state rs' pr' m') ->
- step_cf_instr ge (State s f sp pc rs' pr' m') bb.(bb_exit) t s' ->
- step (State s f sp pc rs pr m) t s'
- | exec_function_internal:
- forall s f args m m' stk,
- Mem.alloc m 0 f.(fn_stacksize) = (m', stk) ->
- step (Callstate s (Internal f) args m)
- E0 (State s f
- (Vptr stk Ptrofs.zero)
- f.(fn_entrypoint)
- (init_regs args f.(fn_params))
- (PMap.init false)
- m')
- | exec_function_external:
- forall s ef args res t m m',
- external_call ef ge args m t res m' ->
- step (Callstate s (External ef) args m)
- t (Returnstate s res m')
- | exec_return:
- forall res f sp pc rs s vres m pr,
- step (Returnstate (Stackframe res f sp pc rs pr :: s) vres m)
- E0 (State s f sp pc (rs#res <- vres) pr m).
-#+end_src
-
-#+name: rtlblock-rest
-#+begin_src coq
-End RELSEM.
-
-Inductive initial_state (p: program): state -> Prop :=
-| initial_state_intro: forall b f m0,
- let ge := Genv.globalenv p in
- Genv.init_mem p = Some m0 ->
- Genv.find_symbol ge p.(prog_main) = Some b ->
- Genv.find_funct_ptr ge b = Some f ->
- funsig f = signature_main ->
- initial_state p (Callstate nil f nil m0).
-
-Inductive final_state: state -> int -> Prop :=
-| final_state_intro: forall r m,
- final_state (Returnstate nil (Vint r) m) r.
-
-Definition semantics (p: program) :=
- Semantics step (initial_state p) final_state (Genv.globalenv p).
-#+end_src
-
-* RTLPar
-:PROPERTIES:
-:header-args:coq: :comments noweb :noweb no-export :padline yes :tangle ../src/hls/RTLPar.v
-:END:
-
-#+begin_src coq :comments no :padline no :exports none
-<<license>>
-#+end_src
-
-#+name: rtlpar-main
-#+begin_src coq
-Require Import compcert.backend.Registers.
-Require Import compcert.common.AST.
-Require Import compcert.common.Events.
-Require Import compcert.common.Globalenvs.
-Require Import compcert.common.Memory.
-Require Import compcert.common.Smallstep.
-Require Import compcert.common.Values.
-Require Import compcert.lib.Coqlib.
-Require Import compcert.lib.Integers.
-Require Import compcert.lib.Maps.
-Require Import compcert.verilog.Op.
-
-Require Import vericert.hls.RTLBlockInstr.
-
-Definition bb := list (list (list instr)).
-
-Definition bblock := @bblock bb.
-Definition code := @code bb.
-Definition function := @function bb.
-Definition fundef := @fundef bb.
-Definition program := @program bb.
-Definition funsig := @funsig bb.
-Definition stackframe := @stackframe bb.
-Definition state := @state bb.
-Definition genv := @genv bb.
-
-Section RELSEM.
-
- Context (ge: genv).
-
- Inductive step_instr_list: val -> instr_state -> list instr -> instr_state -> Prop :=
- | exec_RBcons:
- forall state i state' state'' instrs sp,
- step_instr ge sp state i state' ->
- step_instr_list sp state' instrs state'' ->
- step_instr_list sp state (i :: instrs) state''
- | exec_RBnil:
- forall state sp,
- step_instr_list sp state nil state.
-
- Inductive step_instr_seq (sp : val)
- : instr_state -> list (list instr) -> instr_state -> Prop :=
- | exec_instr_seq_cons:
- forall state i state' state'' instrs,
- step_instr_list sp state i state' ->
- step_instr_seq sp state' instrs state'' ->
- step_instr_seq sp state (i :: instrs) state''
- | exec_instr_seq_nil:
- forall state,
- step_instr_seq sp state nil state.
-
- Inductive step_instr_block (sp : val)
- : instr_state -> bb -> instr_state -> Prop :=
- | exec_instr_block_cons:
- forall state i state' state'' instrs,
- step_instr_seq sp state i state' ->
- step_instr_block sp state' instrs state'' ->
- step_instr_block sp state (i :: instrs) state''
- | exec_instr_block_nil:
- forall state,
- step_instr_block sp state nil state.
-
- Inductive step: state -> trace -> state -> Prop :=
- | exec_bblock:
- forall s f sp pc rs rs' m m' t s' bb pr pr',
- f.(fn_code)!pc = Some bb ->
- step_instr_block sp (mk_instr_state rs pr m) bb.(bb_body) (mk_instr_state rs' pr' m') ->
- step_cf_instr ge (State s f sp pc rs' pr' m') bb.(bb_exit) t s' ->
- step (State s f sp pc rs pr m) t s'
- | exec_function_internal:
- forall s f args m m' stk,
- Mem.alloc m 0 f.(fn_stacksize) = (m', stk) ->
- step (Callstate s (Internal f) args m)
- E0 (State s
- f
- (Vptr stk Ptrofs.zero)
- f.(fn_entrypoint)
- (init_regs args f.(fn_params))
- (PMap.init false)
- m')
- | exec_function_external:
- forall s ef args res t m m',
- external_call ef ge args m t res m' ->
- step (Callstate s (External ef) args m)
- t (Returnstate s res m')
- | exec_return:
- forall res f sp pc rs s vres m pr,
- step (Returnstate (Stackframe res f sp pc rs pr :: s) vres m)
- E0 (State s f sp pc (rs#res <- vres) pr m).
-
-End RELSEM.
-
-Inductive initial_state (p: program): state -> Prop :=
- | initial_state_intro: forall b f m0,
- let ge := Genv.globalenv p in
- Genv.init_mem p = Some m0 ->
- Genv.find_symbol ge p.(prog_main) = Some b ->
- Genv.find_funct_ptr ge b = Some f ->
- funsig f = signature_main ->
- initial_state p (Callstate nil f nil m0).
-
-Inductive final_state: state -> int -> Prop :=
- | final_state_intro: forall r m,
- final_state (Returnstate nil (Vint r) m) r.
-
-Definition semantics (p: program) :=
- Semantics step (initial_state p) final_state (Genv.globalenv p).
-
-Definition max_reg_bblock (m : positive) (pc : node) (bb : bblock) :=
- let max_body := fold_left (fun x l => fold_left (fun x' l' => fold_left max_reg_instr l' x') l x) bb.(bb_body) m in
- max_reg_cfi max_body bb.(bb_exit).
-
-Definition max_reg_function (f: function) :=
- Pos.max
- (PTree.fold max_reg_bblock f.(fn_code) 1%positive)
- (fold_left Pos.max f.(fn_params) 1%positive).
-
-Definition max_pc_function (f: function) : positive :=
- PTree.fold (fun m pc i => (Pos.max m
- (pc + match Zlength i.(bb_body)
- with Z.pos p => p | _ => 1 end))%positive)
- f.(fn_code) 1%positive.
-#+end_src
-
-* License
-
-#+name: license
-#+begin_src coq :tangle no
-(*
- * Vericert: Verified high-level synthesis.
- * Copyright (C) 2020-2022 Yann Herklotz <yann@yannherklotz.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *)
-#+end_src
diff --git a/docs/scheduler.org b/docs/scheduler.org
deleted file mode 100644
index c8b00ff..0000000
--- a/docs/scheduler.org
+++ /dev/null
@@ -1,2317 +0,0 @@
-#+title: Basic Block Generation
-#+author: Yann Herklotz
-#+email: yann [at] yannherklotz [dot] com
-
-* Scheduler
-:PROPERTIES:
-:header-args:ocaml: :comments noweb :noweb no-export :padline yes :tangle ../src/hls/Schedule.ml
-:END:
-
-#+begin_src ocaml :comments no :padline no :exports none
-<<license>>
-#+end_src
-
-#+name: scheduler-main
-#+begin_src ocaml
-open Printf
-open Clflags
-open Camlcoq
-open Datatypes
-open Coqlib
-open Maps
-open AST
-open Kildall
-open Op
-open RTLBlockInstr
-open Predicate
-open RTLBlock
-open HTL
-open Verilog
-open HTLgen
-open HTLMonad
-open HTLMonadExtra
-
-module SS = Set.Make(P)
-
-type svtype =
- | BBType of int
- | VarType of int * int
-
-type sv = {
- sv_type: svtype;
- sv_num: int;
-}
-
-let print_sv v =
- match v with
- | { sv_type = BBType bbi; sv_num = n } -> sprintf "bb%d_%d" bbi n
- | { sv_type = VarType (bbi, i); sv_num = n } -> sprintf "var%dn%d_%d" bbi i n
-
-module G = Graph.Persistent.Digraph.ConcreteLabeled(struct
- type t = sv
- let compare = compare
- let equal = (=)
- let hash = Hashtbl.hash
-end)(struct
- type t = int
- let compare = compare
- let hash = Hashtbl.hash
- let equal = (=)
- let default = 0
-end)
-
-module GDot = Graph.Graphviz.Dot(struct
- let graph_attributes _ = []
- let default_vertex_attributes _ = []
- let vertex_name = print_sv
- let vertex_attributes _ = []
- let get_subgraph _ = None
- let default_edge_attributes _ = []
- let edge_attributes _ = []
-
- include G
- end)
-
-module DFG = Graph.Persistent.Digraph.ConcreteLabeled(struct
- type t = int * instr
- let compare = compare
- let equal = (=)
- let hash = Hashtbl.hash
-end)(struct
- type t = int
- let compare = compare
- let hash = Hashtbl.hash
- let equal = (=)
- let default = 0
-end)
-
-module DFGSimp = Graph.Persistent.Graph.Concrete(struct
- type t = int * instr
- let compare = compare
- let equal = (=)
- let hash = Hashtbl.hash
- end)
-
-let convert dfg =
- DFG.fold_vertex (fun v g -> DFGSimp.add_vertex g v) dfg DFGSimp.empty
- |> DFG.fold_edges (fun v1 v2 g -> DFGSimp.add_edge (DFGSimp.add_edge g v1 v2) v2 v1) dfg
-
-let reg r = sprintf "r%d" (P.to_int r)
-let print_pred r = sprintf "p%d" (P.to_int r)
-
-let print_instr = function
- | RBnop -> ""
- | RBload (_, _, _, _, r) -> sprintf "load(%s)" (reg r)
- | RBstore (_, _, _, _, r) -> sprintf "store(%s)" (reg r)
- | RBsetpred (_, _, _, p) -> sprintf "setpred(%s)" (print_pred p)
- | RBop (_, op, args, d) ->
- (match op, args with
- | Omove, _ -> "mov"
- | Ointconst n, _ -> sprintf "%s=%ld" (reg d) (camlint_of_coqint n)
- | Olongconst n, _ -> sprintf "%s=%LdL" (reg d) (camlint64_of_coqint n)
- | Ofloatconst n, _ -> sprintf "%s=%.15F" (reg d) (camlfloat_of_coqfloat n)
- | Osingleconst n, _ -> sprintf "%s=%.15Ff" (reg d) (camlfloat_of_coqfloat32 n)
- | Oindirectsymbol id, _ -> sprintf "%s=&%s" (reg d) (extern_atom id)
- | Ocast8signed, [r1] -> sprintf "%s=int8signed(%s)" (reg d) (reg r1)
- | Ocast8unsigned, [r1] -> sprintf "%s=int8unsigned(%s)" (reg d) (reg r1)
- | Ocast16signed, [r1] -> sprintf "%s=int16signed(%s)" (reg d) (reg r1)
- | Ocast16unsigned, [r1] -> sprintf "%s=int16unsigned(%s)" (reg d) (reg r1)
- | Oneg, [r1] -> sprintf "%s=-%s" (reg d) (reg r1)
- | Osub, [r1;r2] -> sprintf "%s=%s-%s" (reg d) (reg r1) (reg r2)
- | Omul, [r1;r2] -> sprintf "%s=%s*%s" (reg d) (reg r1) (reg r2)
- | Omulimm n, [r1] -> sprintf "%s=%s*%ld" (reg d) (reg r1) (camlint_of_coqint n)
- | Omulhs, [r1;r2] -> sprintf "%s=mulhs(%s,%s)" (reg d) (reg r1) (reg r2)
- | Omulhu, [r1;r2] -> sprintf "%s=mulhu(%s,%s)" (reg d) (reg r1) (reg r2)
- | Odiv, [r1;r2] -> sprintf "%s=%s /s %s" (reg d) (reg r1) (reg r2)
- | Odivu, [r1;r2] -> sprintf "%s=%s /u %s" (reg d) (reg r1) (reg r2)
- | Omod, [r1;r2] -> sprintf "%s=%s %%s %s" (reg d) (reg r1) (reg r2)
- | Omodu, [r1;r2] -> sprintf "%s=%s %%u %s" (reg d) (reg r1) (reg r2)
- | Oand, [r1;r2] -> sprintf "%s=%s & %s" (reg d) (reg r1) (reg r2)
- | Oandimm n, [r1] -> sprintf "%s=%s & %ld" (reg d) (reg r1) (camlint_of_coqint n)
- | Oor, [r1;r2] -> sprintf "%s=%s | %s" (reg d) (reg r1) (reg r2)
- | Oorimm n, [r1] -> sprintf "%s=%s | %ld" (reg d) (reg r1) (camlint_of_coqint n)
- | Oxor, [r1;r2] -> sprintf "%s=%s ^ %s" (reg d) (reg r1) (reg r2)
- | Oxorimm n, [r1] -> sprintf "%s=%s ^ %ld" (reg d) (reg r1) (camlint_of_coqint n)
- | Onot, [r1] -> sprintf "%s=not(%s)" (reg d) (reg r1)
- | Oshl, [r1;r2] -> sprintf "%s=%s << %s" (reg d) (reg r1) (reg r2)
- | Oshlimm n, [r1] -> sprintf "%s=%s << %ld" (reg d) (reg r1) (camlint_of_coqint n)
- | Oshr, [r1;r2] -> sprintf "%s=%s >>s %s" (reg d) (reg r1) (reg r2)
- | Oshrimm n, [r1] -> sprintf "%s=%s >>s %ld" (reg d) (reg r1) (camlint_of_coqint n)
- | Oshrximm n, [r1] -> sprintf "%s=%s >>x %ld" (reg d) (reg r1) (camlint_of_coqint n)
- | Oshru, [r1;r2] -> sprintf "%s=%s >>u %s" (reg d) (reg r1) (reg r2)
- | Oshruimm n, [r1] -> sprintf "%s=%s >>u %ld" (reg d) (reg r1) (camlint_of_coqint n)
- | Ororimm n, [r1] -> sprintf "%s=%s ror %ld" (reg d) (reg r1) (camlint_of_coqint n)
- | Oshldimm n, [r1;r2] -> sprintf "%s=(%s, %s) << %ld" (reg d) (reg r1) (reg r2) (camlint_of_coqint n)
- | Olea addr, args -> sprintf "%s=addr" (reg d)
- | Omakelong, [r1;r2] -> sprintf "%s=makelong(%s,%s)" (reg d) (reg r1) (reg r2)
- | Olowlong, [r1] -> sprintf "%s=lowlong(%s)" (reg d) (reg r1)
- | Ohighlong, [r1] -> sprintf "%s=highlong(%s)" (reg d) (reg r1)
- | Ocast32signed, [r1] -> sprintf "%s=long32signed(%s)" (reg d) (reg r1)
- | Ocast32unsigned, [r1] -> sprintf "%s=long32unsigned(%s)" (reg d) (reg r1)
- | Onegl, [r1] -> sprintf "%s=-l %s" (reg d) (reg r1)
- | Osubl, [r1;r2] -> sprintf "%s=%s -l %s" (reg d) (reg r1) (reg r2)
- | Omull, [r1;r2] -> sprintf "%s=%s *l %s" (reg d) (reg r1) (reg r2)
- | Omullimm n, [r1] -> sprintf "%s=%s *l %Ld" (reg d) (reg r1) (camlint64_of_coqint n)
- | Omullhs, [r1;r2] -> sprintf "%s=mullhs(%s,%s)" (reg d) (reg r1) (reg r2)
- | Omullhu, [r1;r2] -> sprintf "%s=mullhu(%s,%s)" (reg d) (reg r1) (reg r2)
- | Odivl, [r1;r2] -> sprintf "%s=%s /ls %s" (reg d) (reg r1) (reg r2)
- | Odivlu, [r1;r2] -> sprintf "%s=%s /lu %s" (reg d) (reg r1) (reg r2)
- | Omodl, [r1;r2] -> sprintf "%s=%s %%ls %s" (reg d) (reg r1) (reg r2)
- | Omodlu, [r1;r2] -> sprintf "%s=%s %%lu %s" (reg d) (reg r1) (reg r2)
- | Oandl, [r1;r2] -> sprintf "%s=%s &l %s" (reg d) (reg r1) (reg r2)
- | Oandlimm n, [r1] -> sprintf "%s=%s &l %Ld" (reg d) (reg r1) (camlint64_of_coqint n)
- | Oorl, [r1;r2] -> sprintf "%s=%s |l %s" (reg d) (reg r1) (reg r2)
- | Oorlimm n, [r1] -> sprintf "%s=%s |l %Ld" (reg d) (reg r1) (camlint64_of_coqint n)
- | Oxorl, [r1;r2] -> sprintf "%s=%s ^l %s" (reg d) (reg r1) (reg r2)
- | Oxorlimm n, [r1] -> sprintf "%s=%s ^l %Ld" (reg d) (reg r1) (camlint64_of_coqint n)
- | Onotl, [r1] -> sprintf "%s=notl(%s)" (reg d) (reg r1)
- | Oshll, [r1;r2] -> sprintf "%s=%s <<l %s" (reg d) (reg r1) (reg r2)
- | Oshllimm n, [r1] -> sprintf "%s=%s <<l %ld" (reg d) (reg r1) (camlint_of_coqint n)
- | Oshrl, [r1;r2] -> sprintf "%s=%s >>ls %s" (reg d) (reg r1) (reg r2)
- | Oshrlimm n, [r1] -> sprintf "%s=%s >>ls %ld" (reg d) (reg r1) (camlint_of_coqint n)
- | Oshrxlimm n, [r1] -> sprintf "%s=%s >>lx %ld" (reg d) (reg r1) (camlint_of_coqint n)
- | Oshrlu, [r1;r2] -> sprintf "%s=%s >>lu %s" (reg d) (reg r1) (reg r2)
- | Oshrluimm n, [r1] -> sprintf "%s=%s >>lu %ld" (reg d) (reg r1) (camlint_of_coqint n)
- | Ororlimm n, [r1] -> sprintf "%s=%s rorl %ld" (reg d) (reg r1) (camlint_of_coqint n)
- | Oleal addr, args -> sprintf "%s=addr" (reg d)
- | Onegf, [r1] -> sprintf "%s=negf(%s)" (reg d) (reg r1)
- | Oabsf, [r1] -> sprintf "%s=absf(%s)" (reg d) (reg r1)
- | Oaddf, [r1;r2] -> sprintf "%s=%s +f %s" (reg d) (reg r1) (reg r2)
- | Osubf, [r1;r2] -> sprintf "%s=%s -f %s" (reg d) (reg r1) (reg r2)
- | Omulf, [r1;r2] -> sprintf "%s=%s *f %s" (reg d) (reg r1) (reg r2)
- | Odivf, [r1;r2] -> sprintf "%s=%s /f %s" (reg d) (reg r1) (reg r2)
- | Onegfs, [r1] -> sprintf "%s=negfs(%s)" (reg d) (reg r1)
- | Oabsfs, [r1] -> sprintf "%s=absfs(%s)" (reg d) (reg r1)
- | Oaddfs, [r1;r2] -> sprintf "%s=%s +fs %s" (reg d) (reg r1) (reg r2)
- | Osubfs, [r1;r2] -> sprintf "%s=%s -fs %s" (reg d) (reg r1) (reg r2)
- | Omulfs, [r1;r2] -> sprintf "%s=%s *fs %s" (reg d) (reg r1) (reg r2)
- | Odivfs, [r1;r2] -> sprintf "%s=%s /fs %s" (reg d) (reg r1) (reg r2)
- | Osingleoffloat, [r1] -> sprintf "%s=singleoffloat(%s)" (reg d) (reg r1)
- | Ofloatofsingle, [r1] -> sprintf "%s=floatofsingle(%s)" (reg d) (reg r1)
- | Ointoffloat, [r1] -> sprintf "%s=intoffloat(%s)" (reg d) (reg r1)
- | Ofloatofint, [r1] -> sprintf "%s=floatofint(%s)" (reg d) (reg r1)
- | Ointofsingle, [r1] -> sprintf "%s=intofsingle(%s)" (reg d) (reg r1)
- | Osingleofint, [r1] -> sprintf "%s=singleofint(%s)" (reg d) (reg r1)
- | Olongoffloat, [r1] -> sprintf "%s=longoffloat(%s)" (reg d) (reg r1)
- | Ofloatoflong, [r1] -> sprintf "%s=floatoflong(%s)" (reg d) (reg r1)
- | Olongofsingle, [r1] -> sprintf "%s=longofsingle(%s)" (reg d) (reg r1)
- | Osingleoflong, [r1] -> sprintf "%s=singleoflong(%s)" (reg d) (reg r1)
- | Ocmp c, args -> sprintf "%s=cmp" (reg d)
- | Osel (c, ty), r1::r2::args -> sprintf "%s=sel" (reg d)
- | _, _ -> sprintf "N/a")
-
-module DFGDot = Graph.Graphviz.Dot(struct
- let graph_attributes _ = []
- let default_vertex_attributes _ = []
- let vertex_name = function (i, instr) -> sprintf "\"%d:%s\"" i (print_instr instr)
- let vertex_attributes _ = []
- let get_subgraph _ = None
- let default_edge_attributes _ = []
- let edge_attributes _ = []
-
- include DFG
- end)
-
-module DFGDfs = Graph.Traverse.Dfs(DFG)
-
-module IMap = Map.Make (struct
- type t = int
-
- let compare = compare
-end)
-
-let gen_vertex instrs i = (i, List.nth instrs i)
-
-(** The DFG type defines a list of instructions with their data dependencies as [edges], which are
- the pairs of integers that represent the index of the instruction in the [nodes]. The edges
- always point from left to right. *)
-
-let print_list f out_chan a =
- fprintf out_chan "[ ";
- List.iter (fprintf out_chan "%a " f) a;
- fprintf out_chan "]"
-
-let print_tuple out_chan a =
- let l, r = a in
- fprintf out_chan "(%d,%d)" l r
-
-(*let print_dfg out_chan dfg =
- fprintf out_chan "{ nodes = %a, edges = %a }"
- (print_list PrintRTLBlockInstr.print_bblock_body)
- dfg.nodes (print_list print_tuple) dfg.edges*)
-
-let print_dfg = DFGDot.output_graph
-
-let read_process command =
- let buffer_size = 2048 in
- let buffer = Buffer.create buffer_size in
- let string = Bytes.create buffer_size in
- let in_channel = Unix.open_process_in command in
- let chars_read = ref 1 in
- while !chars_read <> 0 do
- chars_read := input in_channel string 0 buffer_size;
- Buffer.add_substring buffer (Bytes.to_string string) 0 !chars_read
- done;
- ignore (Unix.close_process_in in_channel);
- Buffer.contents buffer
-
-let comb_delay = function
- | RBnop -> 0
- | RBop (_, op, _, _) ->
- (match op with
- | Omove -> 0
- | Ointconst _ -> 0
- | Olongconst _ -> 0
- | Ocast8signed -> 0
- | Ocast8unsigned -> 0
- | Ocast16signed -> 0
- | Ocast16unsigned -> 0
- | Oneg -> 0
- | Onot -> 0
- | Oor -> 0
- | Oorimm _ -> 0
- | Oand -> 0
- | Oandimm _ -> 0
- | Oxor -> 0
- | Oxorimm _ -> 0
- | Omul -> 8
- | Omulimm _ -> 8
- | Omulhs -> 8
- | Omulhu -> 8
- | Odiv -> 72
- | Odivu -> 72
- | Omod -> 72
- | Omodu -> 72
- | _ -> 1)
- | _ -> 1
-
-let pipeline_stages = function
- | RBload _ -> 2
- | RBop (_, op, _, _) ->
- (match op with
- | Odiv -> 32
- | Odivu -> 32
- | Omod -> 32
- | Omodu -> 32
- | _ -> 0)
- | _ -> 0
-
-(** Add a dependency if it uses a register that was written to previously. *)
-let add_dep map i tree dfg curr =
- match PTree.get curr tree with
- | None -> dfg
- | Some ip ->
- let ipv = (List.nth map ip) in
- DFG.add_edge_e dfg (ipv, comb_delay (snd (List.nth map i)), List.nth map i)
-
-(** This function calculates the dependencies of each instruction. The nodes correspond to previous
- registers that were allocated and show which instruction caused it.
-
- This function only gathers the RAW constraints, and will therefore only be active for operations
- that modify registers, which is this case only affects loads and operations. *)
-let accumulate_RAW_deps map dfg curr =
- let i, dst_map, graph = dfg in
- let acc_dep_instruction rs dst =
- ( i + 1,
- PTree.set dst i dst_map,
- List.fold_left (add_dep map i dst_map) graph rs
- )
- in
- let acc_dep_instruction_nodst rs =
- ( i + 1,
- dst_map,
- List.fold_left (add_dep map i dst_map) graph rs)
- in
- match curr with
- | RBop (op, _, rs, dst) -> acc_dep_instruction rs dst
- | RBload (op, _mem, _addr, rs, dst) -> acc_dep_instruction rs dst
- | RBsetpred (_op, _mem, rs, _p) -> acc_dep_instruction_nodst rs
- | RBstore (op, _mem, _addr, rs, src) -> acc_dep_instruction_nodst (src :: rs)
- | _ -> (i + 1, dst_map, graph)
-
-(** Finds the next write to the [dst] register. This is a small optimisation so that only one
- dependency is generated for a data dependency. *)
-let rec find_next_dst_write i dst i' curr =
- let check_dst dst' curr' =
- if dst = dst' then Some (i, i')
- else find_next_dst_write i dst (i' + 1) curr'
- in
- match curr with
- | [] -> None
- | RBop (_, _, _, dst') :: curr' -> check_dst dst' curr'
- | RBload (_, _, _, _, dst') :: curr' -> check_dst dst' curr'
- | _ :: curr' -> find_next_dst_write i dst (i' + 1) curr'
-
-let rec find_all_next_dst_read i dst i' curr =
- let check_dst rs curr' =
- if List.exists (fun x -> x = dst) rs
- then (i, i') :: find_all_next_dst_read i dst (i' + 1) curr'
- else find_all_next_dst_read i dst (i' + 1) curr'
- in
- match curr with
- | [] -> []
- | RBop (_, _, rs, _) :: curr' -> check_dst rs curr'
- | RBload (_, _, _, rs, _) :: curr' -> check_dst rs curr'
- | RBstore (_, _, _, rs, src) :: curr' -> check_dst (src :: rs) curr'
- | RBnop :: curr' -> find_all_next_dst_read i dst (i' + 1) curr'
- | RBsetpred (_, _, rs, _) :: curr' -> check_dst rs curr'
-
-let drop i lst =
- let rec drop' i' lst' =
- match lst' with
- | _ :: ls -> if i' = i then ls else drop' (i' + 1) ls
- | [] -> []
- in
- if i = 0 then lst else drop' 1 lst
-
-let take i lst =
- let rec take' i' lst' =
- match lst' with
- | l :: ls -> if i' = i then [ l ] else l :: take' (i' + 1) ls
- | [] -> []
- in
- if i = 0 then [] else take' 1 lst
-
-let rec next_store i = function
- | [] -> None
- | RBstore (_, _, _, _, _) :: _ -> Some i
- | _ :: rst -> next_store (i + 1) rst
-
-let rec next_load i = function
- | [] -> None
- | RBload (_, _, _, _, _) :: _ -> Some i
- | _ :: rst -> next_load (i + 1) rst
-
-let accumulate_RAW_mem_deps instrs dfg curri =
- let i, curr = curri in
- match curr with
- | RBload (_, _, _, _, _) -> (
- match next_store 0 (take i instrs |> List.rev) with
- | None -> dfg
- | Some d -> DFG.add_edge dfg (gen_vertex instrs (i - d - 1)) (gen_vertex instrs i) )
- | _ -> dfg
-
-let accumulate_WAR_mem_deps instrs dfg curri =
- let i, curr = curri in
- match curr with
- | RBstore (_, _, _, _, _) -> (
- match next_load 0 (take i instrs |> List.rev) with
- | None -> dfg
- | Some d -> DFG.add_edge dfg (gen_vertex instrs (i - d - 1)) (gen_vertex instrs i) )
- | _ -> dfg
-
-let accumulate_WAW_mem_deps instrs dfg curri =
- let i, curr = curri in
- match curr with
- | RBstore (_, _, _, _, _) -> (
- match next_store 0 (take i instrs |> List.rev) with
- | None -> dfg
- | Some d -> DFG.add_edge dfg (gen_vertex instrs (i - d - 1)) (gen_vertex instrs i))
- | _ -> dfg
-
-(** Predicate dependencies. *)
-
-let rec in_predicate p p' =
- match p' with
- | Plit p'' -> P.to_int p = P.to_int (snd p'')
- | Pand (p1, p2) -> in_predicate p p1 || in_predicate p p2
- | Por (p1, p2) -> in_predicate p p1 || in_predicate p p2
- | Ptrue -> false
- | Pfalse -> false
-
-let get_predicate = function
- | RBop (p, _, _, _) -> p
- | RBload (p, _, _, _, _) -> p
- | RBstore (p, _, _, _, _) -> p
- | RBsetpred (p, _, _, _) -> p
- | _ -> None
-
-let rec next_setpred p i = function
- | [] -> None
- | RBsetpred (_, _, _, p') :: rst ->
- if in_predicate p' p then
- Some i
- else
- next_setpred p (i + 1) rst
- | _ :: rst -> next_setpred p (i + 1) rst
-
-let rec next_preduse p i instr=
- let next p' rst =
- if in_predicate p p' then
- Some i
- else
- next_preduse p (i + 1) rst
- in
- match instr with
- | [] -> None
- | RBload (Some p', _, _, _, _) :: rst -> next p' rst
- | RBstore (Some p', _, _, _, _) :: rst -> next p' rst
- | RBop (Some p', _, _, _) :: rst -> next p' rst
- | RBsetpred (Some p', _, _, _) :: rst -> next p' rst
- | _ :: rst -> next_load (i + 1) rst
-
-let accumulate_RAW_pred_deps instrs dfg curri =
- let i, curr = curri in
- match get_predicate curr with
- | Some p -> (
- match next_setpred p 0 (take i instrs |> List.rev) with
- | None -> dfg
- | Some d -> DFG.add_edge dfg (gen_vertex instrs (i - d - 1)) (gen_vertex instrs i) )
- | _ -> dfg
-
-let accumulate_WAR_pred_deps instrs dfg curri =
- let i, curr = curri in
- match curr with
- | RBsetpred (_, _, _, p) -> (
- match next_preduse p 0 (take i instrs |> List.rev) with
- | None -> dfg
- | Some d -> DFG.add_edge dfg (gen_vertex instrs (i - d - 1)) (gen_vertex instrs i) )
- | _ -> dfg
-
-let accumulate_WAW_pred_deps instrs dfg curri =
- let i, curr = curri in
- match curr with
- | RBsetpred (_, _, _, p) -> (
- match next_setpred (Plit (true, p)) 0 (take i instrs |> List.rev) with
- | None -> dfg
- | Some d -> DFG.add_edge dfg (gen_vertex instrs (i - d - 1)) (gen_vertex instrs i) )
- | _ -> dfg
-
-(** This function calculates the WAW dependencies, which happen when two writes are ordered one
- after another and therefore have to be kept in that order. This accumulation might be redundant
- if register renaming is done before hand, because then these dependencies can be avoided. *)
-let accumulate_WAW_deps instrs dfg curri =
- let i, curr = curri in
- let dst_dep dst =
- match find_next_dst_write i dst (i + 1) (drop (i + 1) instrs) with
- | Some (a, b) -> DFG.add_edge dfg (gen_vertex instrs a) (gen_vertex instrs b)
- | _ -> dfg
- in
- match curr with
- | RBop (_, _, _, dst) -> dst_dep dst
- | RBload (_, _, _, _, dst) -> dst_dep dst
- | RBstore (_, _, _, _, _) -> (
- match next_store (i + 1) (drop (i + 1) instrs) with
- | None -> dfg
- | Some i' -> DFG.add_edge dfg (gen_vertex instrs i) (gen_vertex instrs i') )
- | _ -> dfg
-
-let accumulate_WAR_deps instrs dfg curri =
- let i, curr = curri in
- let dst_dep dst =
- let dep_list = find_all_next_dst_read i dst 0 (take i instrs |> List.rev)
- |> List.map (function (d, d') -> (i - d' - 1, d))
- in
- List.fold_left (fun g ->
- function (d, d') -> DFG.add_edge g (gen_vertex instrs d) (gen_vertex instrs d')) dfg dep_list
- in
- match curr with
- | RBop (_, _, _, dst) -> dst_dep dst
- | RBload (_, _, _, _, dst) -> dst_dep dst
- | _ -> dfg
-
-let assigned_vars vars = function
- | RBnop -> vars
- | RBop (_, _, _, dst) -> dst :: vars
- | RBload (_, _, _, _, dst) -> dst :: vars
- | RBstore (_, _, _, _, _) -> vars
- | RBsetpred (_, _, _, _) -> vars
-
-let get_pred = function
- | RBnop -> None
- | RBop (op, _, _, _) -> op
- | RBload (op, _, _, _, _) -> op
- | RBstore (op, _, _, _, _) -> op
- | RBsetpred (_, _, _, _) -> None
-
-let independant_pred p p' =
- match sat_pred_simple (Pand (p, p')) with
- | None -> true
- | _ -> false
-
-let check_dependent op1 op2 =
- match op1, op2 with
- | Some p, Some p' -> not (independant_pred p p')
- | _, _ -> true
-
-let remove_unnecessary_deps graph =
- let is_dependent v1 v2 g =
- let (_, instr1) = v1 in
- let (_, instr2) = v2 in
- if check_dependent (get_pred instr1) (get_pred instr2)
- then g
- else DFG.remove_edge g v1 v2
- in
- DFG.fold_edges is_dependent graph graph
-
-(** All the nodes in the DFG have to come after the source of the basic block, and should terminate
- before the sink of the basic block. After that, there should be constraints for data
- dependencies between nodes. *)
-let gather_bb_constraints debug bb =
- let ibody = List.mapi (fun i a -> (i, a)) bb.bb_body in
- let dfg = List.fold_left (fun dfg v -> DFG.add_vertex dfg v) DFG.empty ibody in
- let _, _, dfg' =
- List.fold_left (accumulate_RAW_deps ibody)
- (0, PTree.empty, dfg)
- bb.bb_body
- in
- let dfg'' = List.fold_left (fun dfg f -> List.fold_left (f bb.bb_body) dfg ibody) dfg'
- [ accumulate_WAW_deps;
- accumulate_WAR_deps;
- accumulate_RAW_mem_deps;
- accumulate_WAR_mem_deps;
- accumulate_WAW_mem_deps;
- accumulate_RAW_pred_deps;
- accumulate_WAR_pred_deps;
- accumulate_WAW_pred_deps
- ]
- in
- let dfg''' = remove_unnecessary_deps dfg'' in
- (List.length bb.bb_body, dfg''', successors_instr bb.bb_exit)
-
-let encode_var bbn n i = { sv_type = VarType (bbn, n); sv_num = i }
-let encode_bb bbn i = { sv_type = BBType bbn; sv_num = i }
-
-let add_initial_sv n dfg constr =
- let add_initial_sv' (i, instr) g =
- let pipes = pipeline_stages instr in
- if pipes > 0 then
- List.init pipes (fun i' -> i')
- |> List.fold_left (fun g i' ->
- G.add_edge_e g (encode_var n i i', -1, encode_var n i (i'+1))
- ) g
- else g
- in
- DFG.fold_vertex add_initial_sv' dfg constr
-
-let add_super_nodes n dfg =
- DFG.fold_vertex (function v1 -> fun g ->
- (if DFG.in_degree dfg v1 = 0
- then G.add_edge_e g (encode_bb n 0, 0, encode_var n (fst v1) 0)
- else g) |>
- (fun g' ->
- if DFG.out_degree dfg v1 = 0
- then G.add_edge_e g' (encode_var n (fst v1) (pipeline_stages (snd v1)),
- 0, encode_bb n 1)
- else g')) dfg
-
-let add_data_deps n =
- DFG.fold_edges_e (function ((i1, instr1), _, (i2, _)) -> fun g ->
- let end_sv = pipeline_stages instr1 in
- G.add_edge_e g (encode_var n i1 end_sv, 0, encode_var n i2 0)
- )
-
-let add_ctrl_deps n succs constr =
- List.fold_left (fun g n' ->
- G.add_edge_e g (encode_bb n 1, -1, encode_bb n' 0)
- ) constr succs
-
-module BFDFG = Graph.Path.BellmanFord(DFG)(struct
- include DFG
- type t = int
- let weight = DFG.E.label
- let compare = compare
- let add = (+)
- let zero = 0
- end)
-
-module TopoDFG = Graph.Topological.Make(DFG)
-
-let negate_graph constr =
- DFG.fold_edges_e (function (v1, e, v2) -> fun g ->
- DFG.add_edge_e g (v1, -e, v2)
- ) constr DFG.empty
-
-let add_cycle_constr maxf n dfg constr =
- let negated_dfg = negate_graph dfg in
- let max_initial_del = DFG.fold_vertex (fun v1 g ->
- if DFG.in_degree dfg v1 = 0
- then max g (comb_delay (snd v1))
- else g) dfg 0 in
- let longest_path v = BFDFG.all_shortest_paths negated_dfg v
- |> BFDFG.H.to_seq |> List.of_seq
- |> List.map (function (x, y) -> (x, y - max_initial_del)) in
- let constrained_paths = List.filter (function (_, m) -> - m > maxf) in
- List.fold_left (fun g -> function (v, v', w) ->
- G.add_edge_e g (encode_var n (fst v) 0,
- - (int_of_float (Float.ceil (Float.div (float_of_int w) (float_of_int maxf))) - 1),
- encode_var n (fst v') 0)
- ) constr (DFG.fold_vertex (fun v l ->
- List.append l (longest_path v (*|> (function l -> List.iter (function (a, x) ->
- printf "c: %d %d\n" (fst a) x) l; l)*) |> constrained_paths (* |> (function l -> List.iter (function (a, x) ->
- printf "%d %d\n" (fst a) x) l; l)*)
- |> List.map (function (v', w) -> (v, v', - w)))
- ) dfg [])
-
-type resource =
- | Mem
- | SDiv
- | UDiv
-
-type resources = {
- res_mem: DFG.V.t list;
- res_udiv: DFG.V.t list;
- res_sdiv: DFG.V.t list;
-}
-
-let find_resource = function
- | RBload _ -> Some Mem
- | RBstore _ -> Some Mem
- | RBop (_, op, _, _) ->
- ( match op with
- | Odiv -> Some SDiv
- | Odivu -> Some UDiv
- | Omod -> Some SDiv
- | Omodu -> Some UDiv
- | _ -> None )
- | _ -> None
-
-let add_resource_constr n dfg constr =
- let res = TopoDFG.fold (function (i, instr) ->
- function {res_mem = ml; res_sdiv = sdl; res_udiv = udl} as r ->
- match find_resource instr with
- | Some SDiv -> {r with res_sdiv = (i, instr) :: sdl}
- | Some UDiv -> {r with res_udiv = (i, instr) :: udl}
- | Some Mem -> {r with res_mem = (i, instr) :: ml}
- | None -> r
- ) dfg {res_mem = []; res_sdiv = []; res_udiv = []}
- in
- let get_constraints l g = List.fold_left (fun gv v' ->
- match gv with
- | (g, None) -> (g, Some v')
- | (g, Some v) ->
- (G.add_edge_e g (encode_var n (fst v) 0, -1, encode_var n (fst v') 0), Some v')
- ) (g, None) l |> fst
- in
- get_constraints (List.rev res.res_mem) constr
- |> get_constraints (List.rev res.res_udiv)
- |> get_constraints (List.rev res.res_sdiv)
-
-let gather_cfg_constraints c constr curr =
- let (n, dfg) = curr in
- match PTree.get (P.of_int n) c with
- | None -> assert false
- | Some { bb_exit = ctrl; _ } ->
- add_super_nodes n dfg constr
- |> add_initial_sv n dfg
- |> add_data_deps n dfg
- |> add_ctrl_deps n (successors_instr ctrl
- |> List.map P.to_int
- |> List.filter (fun n' -> n' < n))
- |> add_cycle_constr 8 n dfg
- |> add_resource_constr n dfg
-
-let rec intersperse s = function
- | [] -> []
- | [ a ] -> [ a ]
- | x :: xs -> x :: s :: intersperse s xs
-
-let print_objective constr =
- let vars = G.fold_vertex (fun v1 l ->
- match v1 with
- | { sv_type = VarType _; sv_num = 0 } -> print_sv v1 :: l
- | _ -> l
- ) constr []
- in
- "min: " ^ String.concat "" (intersperse " + " vars) ^ ";\n"
-
-let print_lp constr =
- print_objective constr ^
- (G.fold_edges_e (function (e1, w, e2) -> fun s ->
- s ^ sprintf "%s - %s <= %d;\n" (print_sv e1) (print_sv e2) w
- ) constr "" |>
- G.fold_vertex (fun v1 s ->
- s ^ sprintf "int %s;\n" (print_sv v1)
- ) constr)
-
-let update_schedule v = function Some l -> Some (v :: l) | None -> Some [ v ]
-
-let parse_soln (tree, bbtree) s =
- let r = Str.regexp "var\\([0-9]+\\)n\\([0-9]+\\)_0[ ]+\\([0-9]+\\)" in
- let bb = Str.regexp "bb\\([0-9]+\\)_\\([0-9]+\\)[ ]+\\([0-9]+\\)" in
- let upd s = IMap.update
- (Str.matched_group 1 s |> int_of_string)
- (update_schedule
- ( Str.matched_group 2 s |> int_of_string,
- Str.matched_group 3 s |> int_of_string ))
- in
- if Str.string_match r s 0
- then (upd s tree, bbtree)
- else
- (if Str.string_match bb s 0
- then (tree, upd s bbtree)
- else (tree, bbtree))
-
-let solve_constraints constr =
- let (fn, oc) = Filename.open_temp_file "vericert_" "_lp_solve" in
- fprintf oc "%s\n" (print_lp constr);
- close_out oc;
-
- let res = Str.split (Str.regexp_string "\n") (read_process ("lp_solve " ^ fn))
- |> drop 3
- |> List.fold_left parse_soln (IMap.empty, IMap.empty)
- in
- (*Sys.remove fn;*) res
-
-let subgraph dfg l =
- let dfg' = List.fold_left (fun g v -> DFG.add_vertex g v) DFG.empty l in
- List.fold_left (fun g v ->
- List.fold_left (fun g' v' ->
- let edges = DFG.find_all_edges dfg v v' in
- List.fold_left DFG.add_edge_e g' edges
- ) g l
- ) dfg' l
-
-let rec all_successors dfg v =
- List.concat (List.fold_left (fun l v ->
- all_successors dfg v :: l
- ) [] (DFG.succ dfg v))
-
-let order_instr dfg =
- DFG.fold_vertex (fun v li ->
- if DFG.in_degree dfg v = 0
- then (List.map snd (v :: all_successors dfg v)) :: li
- else li
- ) dfg []
-
-let combine_bb_schedule schedule s =
- let i, st = s in
- IMap.update st (update_schedule i) schedule
-
-(**let add_el dfg i l =
- List.*)
-
-let check_in el =
- List.exists (List.exists ((=) el))
-
-let all_dfs dfg =
- let roots = DFG.fold_vertex (fun v li ->
- if DFG.in_degree dfg v = 0 then v :: li else li
- ) dfg [] in
- let dfg' = DFG.fold_edges (fun v1 v2 g -> DFG.add_edge g v2 v1) dfg dfg in
- List.fold_left (fun a el ->
- if check_in el a then a else
- (DFGDfs.fold_component (fun v l -> v :: l) [] dfg' el) :: a) [] roots
-
-let range s e =
- List.init (e - s) (fun i -> i)
- |> List.map (fun x -> x + s)
-
-(** Should generate the [RTLPar] code based on the input [RTLBlock] description. *)
-let transf_rtlpar c c' schedule =
- let f i bb : RTLPar.bblock =
- match bb with
- | { bb_body = []; bb_exit = c } -> { bb_body = []; bb_exit = c }
- | { bb_body = bb_body'; bb_exit = ctrl_flow } ->
- let dfg = match PTree.get i c' with None -> assert false | Some x -> x in
- let bb_st_e =
- let m = IMap.find (P.to_int i) (snd schedule) in
- (List.assq 0 m, List.assq 1 m) in
- let i_sched = IMap.find (P.to_int i) (fst schedule) in
- let i_sched_tree =
- List.fold_left combine_bb_schedule IMap.empty i_sched
- in
- let body = IMap.to_seq i_sched_tree |> List.of_seq |> List.map snd
- |> List.map (List.map (fun x -> (x, List.nth bb_body' x)))
- in
- let body2 = List.fold_left (fun x b ->
- match IMap.find_opt b i_sched_tree with
- | Some i -> i :: x
- | None -> [] :: x
- ) [] (range (fst bb_st_e) (snd bb_st_e + 1))
- |> List.map (List.map (fun x -> (x, List.nth bb_body' x)))
- |> List.rev
- in
- (*let final_body = List.map (fun x -> subgraph dfg x |> order_instr) body in*)
- let final_body2 = List.map (fun x -> subgraph dfg x
- |> (fun x ->
- all_dfs x
- |> List.map (subgraph x)
- |> List.map (fun y ->
- TopoDFG.fold (fun i l -> snd i :: l) y []
- |> List.rev))) body2
- (*|> (fun x -> TopoDFG.fold (fun i l -> snd i :: l) x [])
- |> List.rev) body2*)
- in
- { bb_body = final_body2;
- bb_exit = ctrl_flow
- }
- in
- PTree.map f c
-
-let schedule entry (c : RTLBlock.bb RTLBlockInstr.code) =
- let debug = true in
- let transf_graph (_, dfg, _) = dfg in
- let c' = PTree.map1 (fun x -> gather_bb_constraints false x |> transf_graph) c in
- (*let _ = if debug then PTree.map (fun r o -> printf "##### %d #####\n%a\n\n" (P.to_int r) print_dfg o) c' else PTree.empty in*)
- let cgraph = PTree.elements c'
- |> List.map (function (x, y) -> (P.to_int x, y))
- |> List.fold_left (gather_cfg_constraints c) G.empty
- in
- let graph = open_out "constr_graph.dot" in
- fprintf graph "%a\n" GDot.output_graph cgraph;
- close_out graph;
- let schedule' = solve_constraints cgraph in
- (**IMap.iter (fun a b -> printf "##### %d #####\n%a\n\n" a (print_list print_tuple) b) schedule';*)
- (**printf "Schedule: %a\n" (fun a x -> IMap.iter (fun d -> fprintf a "%d: %a\n" d (print_list print_tuple)) x) schedule';*)
- transf_rtlpar c c' schedule'
-
-let rec find_reachable_states c e =
- match PTree.get e c with
- | Some { bb_exit = ex; _ } ->
- e :: List.fold_left (fun x a -> List.concat [x; find_reachable_states c a]) []
- (successors_instr ex |> List.filter (fun x -> P.lt x e))
- | None -> assert false
-
-let add_to_tree c nt i =
- match PTree.get i c with
- | Some p -> PTree.set i p nt
- | None -> assert false
-
-let schedule_fn (f : RTLBlock.coq_function) : RTLPar.coq_function =
- let scheduled = schedule f.fn_entrypoint f.fn_code in
- let reachable = find_reachable_states scheduled f.fn_entrypoint
- |> List.to_seq |> SS.of_seq |> SS.to_seq |> List.of_seq in
- { fn_sig = f.fn_sig;
- fn_params = f.fn_params;
- fn_stacksize = f.fn_stacksize;
- fn_code = scheduled (*List.fold_left (add_to_tree scheduled) PTree.empty reachable*);
- fn_entrypoint = f.fn_entrypoint
- }
-#+end_src
-
-* RTLPargen
-:PROPERTIES:
-:header-args:coq: :comments noweb :noweb no-export :padline yes :tangle ../src/hls/RTLPargen.v
-:END:
-
-#+begin_src coq :comments no :padline no :exports none
-<<license>>
-#+end_src
-
-#+name: rtlpargen-main
-#+begin_src coq
-Require Import compcert.backend.Registers.
-Require Import compcert.common.AST.
-Require Import compcert.common.Globalenvs.
-Require Import compcert.common.Memory.
-Require Import compcert.common.Values.
-Require Import compcert.lib.Floats.
-Require Import compcert.lib.Integers.
-Require Import compcert.lib.Maps.
-Require compcert.verilog.Op.
-
-Require Import vericert.common.Vericertlib.
-Require Import vericert.hls.RTLBlock.
-Require Import vericert.hls.RTLPar.
-Require Import vericert.hls.RTLBlockInstr.
-Require Import vericert.hls.Predicate.
-Require Import vericert.hls.Abstr.
-Import NE.NonEmptyNotation.
-
-#[local] Open Scope positive.
-#[local] Open Scope forest.
-#[local] Open Scope pred_op.
-#+end_src
-
-** Abstract Computations
-
-Define the abstract computation using the [update] function, which will set each register to its
-symbolic value. First we need to define a few helper functions to correctly translate the
-predicates.
-
-#+name: rtlpargen-generation
-#+begin_src coq
-Fixpoint list_translation (l : list reg) (f : forest) {struct l} : list pred_expr :=
- match l with
- | nil => nil
- | i :: l => (f # (Reg i)) :: (list_translation l f)
- end.
-
-Fixpoint replicate {A} (n: nat) (l: A) :=
- match n with
- | O => nil
- | S n => l :: replicate n l
- end.
-
-Definition merge''' x y :=
- match x, y with
- | Some p1, Some p2 => Some (Pand p1 p2)
- | Some p, None | None, Some p => Some p
- | None, None => None
- end.
-
-Definition merge'' x :=
- match x with
- | ((a, e), (b, el)) => (merge''' a b, Econs e el)
- end.
-
-Definition map_pred_op {A B} (pf: option pred_op * (A -> B)) (pa: option pred_op * A): option pred_op * B :=
- match pa, pf with
- | (p, a), (p', f) => (merge''' p p', f a)
- end.
-
-Definition predicated_prod {A B: Type} (p1: predicated A) (p2: predicated B) :=
- NE.map (fun x => match x with ((a, b), (c, d)) => (Pand a c, (b, d)) end)
- (NE.non_empty_prod p1 p2).
-
-Definition predicated_map {A B: Type} (f: A -> B) (p: predicated A): predicated B :=
- NE.map (fun x => (fst x, f (snd x))) p.
-
-(*map (fun x => (fst x, Econs (snd x) Enil)) pel*)
-Definition merge' (pel: pred_expr) (tpel: predicated expression_list) :=
- predicated_map (uncurry Econs) (predicated_prod pel tpel).
-
-Fixpoint merge (pel: list pred_expr): predicated expression_list :=
- match pel with
- | nil => NE.singleton (T, Enil)
- | a :: b => merge' a (merge b)
- end.
-
-Definition map_predicated {A B} (pf: predicated (A -> B)) (pa: predicated A): predicated B :=
- predicated_map (fun x => (fst x) (snd x)) (predicated_prod pf pa).
-
-Definition predicated_apply1 {A B} (pf: predicated (A -> B)) (pa: A): predicated B :=
- NE.map (fun x => (fst x, (snd x) pa)) pf.
-
-Definition predicated_apply2 {A B C} (pf: predicated (A -> B -> C)) (pa: A) (pb: B): predicated C :=
- NE.map (fun x => (fst x, (snd x) pa pb)) pf.
-
-Definition predicated_apply3 {A B C D} (pf: predicated (A -> B -> C -> D)) (pa: A) (pb: B) (pc: C): predicated D :=
- NE.map (fun x => (fst x, (snd x) pa pb pc)) pf.
-
-Definition predicated_from_opt {A: Type} (p: option pred_op) (a: A) :=
- match p with
- | Some p' => NE.singleton (p', a)
- | None => NE.singleton (T, a)
- end.
-
-#[local] Open Scope non_empty_scope.
-#[local] Open Scope pred_op.
-
-Fixpoint NEfold_left {A B} (f: A -> B -> A) (l: NE.non_empty B) (a: A) : A :=
- match l with
- | NE.singleton a' => f a a'
- | a' ::| b => NEfold_left f b (f a a')
- end.
-
-Fixpoint NEapp {A} (l m: NE.non_empty A) :=
- match l with
- | NE.singleton a => a ::| m
- | a ::| b => a ::| NEapp b m
- end.
-
-Definition app_predicated' {A: Type} (a b: predicated A) :=
- let negation := ¬ (NEfold_left (fun a b => a ∨ (fst b)) b ⟂) in
- NEapp (NE.map (fun x => (negation ∧ fst x, snd x)) a) b.
-
-Definition app_predicated {A: Type} (p: option pred_op) (a b: predicated A) :=
- match p with
- | Some p' => NEapp (NE.map (fun x => (¬ p' ∧ fst x, snd x)) a)
- (NE.map (fun x => (p' ∧ fst x, snd x)) b)
- | None => b
- end.
-
-Definition pred_ret {A: Type} (a: A) : predicated A :=
- NE.singleton (T, a).
-
-#+end_src
-
-*** Update Function
-:PROPERTIES:
-:CUSTOM_ID: update-function
-:END:
-
-The [update] function will generate a new forest given an existing forest and a new instruction, so
-that it can evaluate a symbolic expression by folding over a list of instructions. The main problem
-is that predicates need to be merged as well, so that:
-
-1. The predicates are *independent*.
-2. The expression assigned to the register should still be correct.
-
-This is done by multiplying the predicates together, and assigning the negation of the expression to
-the other predicates.
-
-#+name: rtlpargen-update-function
-#+begin_src coq
-Definition update (f : forest) (i : instr) : forest :=
- match i with
- | RBnop => f
- | RBop p op rl r =>
- f # (Reg r) <-
- (app_predicated p
- (f # (Reg r))
- (map_predicated (pred_ret (Eop op)) (merge (list_translation rl f))))
- | RBload p chunk addr rl r =>
- f # (Reg r) <-
- (app_predicated p
- (f # (Reg r))
- (map_predicated
- (map_predicated (pred_ret (Eload chunk addr)) (merge (list_translation rl f)))
- (f # Mem)))
- | RBstore p chunk addr rl r =>
- f # Mem <-
- (app_predicated p
- (f # Mem)
- (map_predicated
- (map_predicated
- (predicated_apply2 (map_predicated (pred_ret Estore) (f # (Reg r))) chunk addr)
- (merge (list_translation rl f))) (f # Mem)))
- | RBsetpred p' c args p =>
- f # (Pred p) <-
- (app_predicated p'
- (f # (Pred p))
- (map_predicated (pred_ret (Esetpred c)) (merge (list_translation args f))))
- end.
-#+end_src
-
-Implementing which are necessary to show the correctness of the translation validation by
-showing that there aren't any more effects in the resultant RTLPar code than in the RTLBlock code.
-
-Get a sequence from the basic block.
-
-#+name: rtlpargen-abstract-seq
-#+begin_src coq
-Fixpoint abstract_sequence (f : forest) (b : list instr) : forest :=
- match b with
- | nil => f
- | i :: l => abstract_sequence (update f i) l
- end.
-#+end_src
-
-Check equivalence of control flow instructions. As none of the basic blocks should have been
-moved, none of the labels should be different, meaning the control-flow instructions should match
-exactly.
-
-#+name: rtlpargen-check-functions
-#+begin_src coq
-Definition check_control_flow_instr (c1 c2: cf_instr) : bool :=
- if cf_instr_eq c1 c2 then true else false.
-#+end_src
-
-We define the top-level oracle that will check if two basic blocks are equivalent after a
-scheduling transformation.
-
-#+name: rtlpargen-top-check-functions
-#+begin_src coq
-Definition empty_trees (bb: RTLBlock.bb) (bbt: RTLPar.bb) : bool :=
- match bb with
- | nil =>
- match bbt with
- | nil => true
- | _ => false
- end
- | _ => true
- end.
-
-Definition schedule_oracle (bb: RTLBlock.bblock) (bbt: RTLPar.bblock) : bool :=
- check (abstract_sequence empty (bb_body bb))
- (abstract_sequence empty (concat (concat (bb_body bbt)))) &&
- check_control_flow_instr (bb_exit bb) (bb_exit bbt) &&
- empty_trees (bb_body bb) (bb_body bbt).
-
-Definition check_scheduled_trees := beq2 schedule_oracle.
-
-Ltac solve_scheduled_trees_correct :=
- intros; unfold check_scheduled_trees in *;
- match goal with
- | [ H: context[beq2 _ _ _], x: positive |- _ ] =>
- rewrite beq2_correct in H; specialize (H x)
- end; repeat destruct_match; crush.
-
-Lemma check_scheduled_trees_correct:
- forall f1 f2 x y1,
- check_scheduled_trees f1 f2 = true ->
- PTree.get x f1 = Some y1 ->
- exists y2, PTree.get x f2 = Some y2 /\ schedule_oracle y1 y2 = true.
-Proof. solve_scheduled_trees_correct; eexists; crush. Qed.
-
-Lemma check_scheduled_trees_correct2:
- forall f1 f2 x,
- check_scheduled_trees f1 f2 = true ->
- PTree.get x f1 = None ->
- PTree.get x f2 = None.
-Proof. solve_scheduled_trees_correct. Qed.
-
-#+end_src
-
-** Top-level Functions
-
-#+name: rtlpargen-top-level-functions
-#+begin_src coq
-Parameter schedule : RTLBlock.function -> RTLPar.function.
-
-Definition transl_function (f: RTLBlock.function) : Errors.res RTLPar.function :=
- let tfcode := fn_code (schedule f) in
- if check_scheduled_trees f.(fn_code) tfcode then
- Errors.OK (mkfunction f.(fn_sig)
- f.(fn_params)
- f.(fn_stacksize)
- tfcode
- f.(fn_entrypoint))
- else
- Errors.Error (Errors.msg "RTLPargen: Could not prove the blocks equivalent.").
-
-Definition transl_fundef := transf_partial_fundef transl_function.
-
-Definition transl_program (p : RTLBlock.program) : Errors.res RTLPar.program :=
- transform_partial_program transl_fundef p.
-#+end_src
-
-* RTLPargenproof
-:PROPERTIES:
-:header-args:coq: :comments noweb :noweb no-export :padline yes :tangle ../src/hls/RTLPargenproof.v
-:END:
-
-#+begin_src coq :comments no :padline no :exports none
-<<license>>
-#+end_src
-
-#+name: rtlpargenproof-imports
-#+begin_src coq
-Require Import compcert.backend.Registers.
-Require Import compcert.common.AST.
-Require Import compcert.common.Errors.
-Require Import compcert.common.Linking.
-Require Import compcert.common.Globalenvs.
-Require Import compcert.common.Memory.
-Require Import compcert.common.Values.
-Require Import compcert.lib.Maps.
-
-Require Import vericert.common.Vericertlib.
-Require Import vericert.hls.RTLBlock.
-Require Import vericert.hls.RTLPar.
-Require Import vericert.hls.RTLBlockInstr.
-Require Import vericert.hls.RTLPargen.
-Require Import vericert.hls.Predicate.
-Require Import vericert.hls.Abstr.
-
-#[local] Open Scope positive.
-#[local] Open Scope forest.
-#[local] Open Scope pred_op.
-#+end_src
-
-** RTLBlock to abstract translation
-
-Correctness of translation from RTLBlock to the abstract interpretation language.
-
-#+name: rtlpargenproof-main
-#+begin_src coq
-(*Definition is_regs i := match i with mk_instr_state rs _ => rs end.
-Definition is_mem i := match i with mk_instr_state _ m => m end.
-
-Inductive state_lessdef : instr_state -> instr_state -> Prop :=
- state_lessdef_intro :
- forall rs1 rs2 m1,
- (forall x, rs1 !! x = rs2 !! x) ->
- state_lessdef (mk_instr_state rs1 m1) (mk_instr_state rs2 m1).
-
-Ltac inv_simp :=
- repeat match goal with
- | H: exists _, _ |- _ => inv H
- end; simplify.
-
-*)
-
-Definition check_dest i r' :=
- match i with
- | RBop p op rl r => (r =? r')%positive
- | RBload p chunk addr rl r => (r =? r')%positive
- | _ => false
- end.
-
-Lemma check_dest_dec i r : {check_dest i r = true} + {check_dest i r = false}.
-Proof. destruct (check_dest i r); tauto. Qed.
-
-Fixpoint check_dest_l l r :=
- match l with
- | nil => false
- | a :: b => check_dest a r || check_dest_l b r
- end.
-
-Lemma check_dest_l_forall :
- forall l r,
- check_dest_l l r = false ->
- Forall (fun x => check_dest x r = false) l.
-Proof. induction l; crush. Qed.
-
-Lemma check_dest_l_dec i r : {check_dest_l i r = true} + {check_dest_l i r = false}.
-Proof. destruct (check_dest_l i r); tauto. Qed.
-
-Lemma check_dest_update :
- forall f i r,
- check_dest i r = false ->
- (update f i) # (Reg r) = f # (Reg r).
-Proof.
- destruct i; crush; try apply Pos.eqb_neq in H; apply genmap1; crush.
-Qed.
-
-Lemma check_dest_l_forall2 :
- forall l r,
- Forall (fun x => check_dest x r = false) l ->
- check_dest_l l r = false.
-Proof.
- induction l; crush.
- inv H. apply orb_false_intro; crush.
-Qed.
-
-Lemma check_dest_l_ex2 :
- forall l r,
- (exists a, In a l /\ check_dest a r = true) ->
- check_dest_l l r = true.
-Proof.
- induction l; crush.
- specialize (IHl r). inv H.
- apply orb_true_intro; crush.
- apply orb_true_intro; crush.
- right. apply IHl. exists x. auto.
-Qed.
-
-Lemma check_list_l_false :
- forall l x r,
- check_dest_l (l ++ x :: nil) r = false ->
- check_dest_l l r = false /\ check_dest x r = false.
-Proof.
- simplify.
- apply check_dest_l_forall in H. apply Forall_app in H.
- simplify. apply check_dest_l_forall2; auto.
- apply check_dest_l_forall in H. apply Forall_app in H.
- simplify. inv H1. auto.
-Qed.
-
-Lemma check_dest_l_ex :
- forall l r,
- check_dest_l l r = true ->
- exists a, In a l /\ check_dest a r = true.
-Proof.
- induction l; crush.
- destruct (check_dest a r) eqn:?; try solve [econstructor; crush].
- simplify.
- exploit IHl. apply H. simplify. econstructor. simplify. right. eassumption.
- auto.
-Qed.
-
-Lemma check_list_l_true :
- forall l x r,
- check_dest_l (l ++ x :: nil) r = true ->
- check_dest_l l r = true \/ check_dest x r = true.
-Proof.
- simplify.
- apply check_dest_l_ex in H; simplify.
- apply in_app_or in H. inv H. left.
- apply check_dest_l_ex2. exists x0. auto.
- inv H0; auto.
-Qed.
-
-Lemma check_dest_l_dec2 l r :
- {Forall (fun x => check_dest x r = false) l}
- + {exists a, In a l /\ check_dest a r = true}.
-Proof.
- destruct (check_dest_l_dec l r); [right | left];
- auto using check_dest_l_ex, check_dest_l_forall.
-Qed.
-
-Lemma abstr_comp :
- forall l i f x x0,
- abstract_sequence f (l ++ i :: nil) = x ->
- abstract_sequence f l = x0 ->
- x = update x0 i.
-Proof. induction l; intros; crush; eapply IHl; eauto. Qed.
-
-(*
-
-Lemma gen_list_base:
- forall FF ge sp l rs exps st1,
- (forall x, @sem_value FF ge sp st1 (exps # (Reg x)) (rs !! x)) ->
- sem_val_list ge sp st1 (list_translation l exps) rs ## l.
-Proof.
- induction l.
- intros. simpl. constructor.
- intros. simpl. eapply Scons; eauto.
-Qed.
-
-Lemma check_dest_update2 :
- forall f r rl op p,
- (update f (RBop p op rl r)) # (Reg r) = Eop op (list_translation rl f) (f # Mem).
-Proof. crush; rewrite map2; auto. Qed.
-
-Lemma check_dest_update3 :
- forall f r rl p addr chunk,
- (update f (RBload p chunk addr rl r)) # (Reg r) = Eload chunk addr (list_translation rl f) (f # Mem).
-Proof. crush; rewrite map2; auto. Qed.
-
-Lemma abstract_seq_correct_aux:
- forall FF ge sp i st1 st2 st3 f,
- @step_instr FF ge sp st3 i st2 ->
- sem ge sp st1 f st3 ->
- sem ge sp st1 (update f i) st2.
-Proof.
- intros; inv H; simplify.
- { simplify; eauto. } (*apply match_states_refl. }*)
- { inv H0. inv H6. destruct st1. econstructor. simplify.
- constructor. intros.
- destruct (resource_eq (Reg res) (Reg x)). inv e.
- rewrite map2. econstructor. eassumption. apply gen_list_base; eauto.
- rewrite Regmap.gss. eauto.
- assert (res <> x). { unfold not in *. intros. apply n. rewrite H0. auto. }
- rewrite Regmap.gso by auto.
- rewrite genmap1 by auto. auto.
-
- rewrite genmap1; crush. }
- { inv H0. inv H7. constructor. constructor. intros.
- destruct (Pos.eq_dec dst x); subst.
- rewrite map2. econstructor; eauto.
- apply gen_list_base. auto. rewrite Regmap.gss. auto.
- rewrite genmap1. rewrite Regmap.gso by auto. auto.
- unfold not in *; intros. inv H0. auto.
- rewrite genmap1; crush.
- }
- { inv H0. inv H7. constructor. constructor; intros.
- rewrite genmap1; crush.
- rewrite map2. econstructor; eauto.
- apply gen_list_base; auto.
- }
-Qed.
-
-Lemma regmap_list_equiv :
- forall A (rs1: Regmap.t A) rs2,
- (forall x, rs1 !! x = rs2 !! x) ->
- forall rl, rs1##rl = rs2##rl.
-Proof. induction rl; crush. Qed.
-
-Lemma sem_update_Op :
- forall A ge sp st f st' r l o0 o m rs v,
- @sem A ge sp st f st' ->
- Op.eval_operation ge sp o0 rs ## l m = Some v ->
- match_states st' (mk_instr_state rs m) ->
- exists tst,
- sem ge sp st (update f (RBop o o0 l r)) tst /\ match_states (mk_instr_state (Regmap.set r v rs) m) tst.
-Proof.
- intros. inv H1. simplify.
- destruct st.
- econstructor. simplify.
- { constructor.
- { constructor. intros. destruct (Pos.eq_dec x r); subst.
- { pose proof (H5 r). rewrite map2. pose proof H. inv H. econstructor; eauto.
- { inv H9. eapply gen_list_base; eauto. }
- { instantiate (1 := (Regmap.set r v rs0)). rewrite Regmap.gss. erewrite regmap_list_equiv; eauto. } }
- { rewrite Regmap.gso by auto. rewrite genmap1; crush. inv H. inv H7; eauto. } }
- { inv H. rewrite genmap1; crush. eauto. } }
- { constructor; eauto. intros.
- destruct (Pos.eq_dec r x);
- subst; [repeat rewrite Regmap.gss | repeat rewrite Regmap.gso]; auto. }
-Qed.
-
-Lemma sem_update_load :
- forall A ge sp st f st' r o m a l m0 rs v a0,
- @sem A ge sp st f st' ->
- Op.eval_addressing ge sp a rs ## l = Some a0 ->
- Mem.loadv m m0 a0 = Some v ->
- match_states st' (mk_instr_state rs m0) ->
- exists tst : instr_state,
- sem ge sp st (update f (RBload o m a l r)) tst
- /\ match_states (mk_instr_state (Regmap.set r v rs) m0) tst.
-Proof.
- intros. inv H2. pose proof H. inv H. inv H9.
- destruct st.
- econstructor; simplify.
- { constructor.
- { constructor. intros.
- destruct (Pos.eq_dec x r); subst.
- { rewrite map2. econstructor; eauto. eapply gen_list_base. intros.
- rewrite <- H6. eauto.
- instantiate (1 := (Regmap.set r v rs0)). rewrite Regmap.gss. auto. }
- { rewrite Regmap.gso by auto. rewrite genmap1; crush. } }
- { rewrite genmap1; crush. eauto. } }
- { constructor; auto; intros. destruct (Pos.eq_dec r x);
- subst; [repeat rewrite Regmap.gss | repeat rewrite Regmap.gso]; auto. }
-Qed.
-
-Lemma sem_update_store :
- forall A ge sp a0 m a l r o f st m' rs m0 st',
- @sem A ge sp st f st' ->
- Op.eval_addressing ge sp a rs ## l = Some a0 ->
- Mem.storev m m0 a0 rs !! r = Some m' ->
- match_states st' (mk_instr_state rs m0) ->
- exists tst, sem ge sp st (update f (RBstore o m a l r)) tst
- /\ match_states (mk_instr_state rs m') tst.
-Proof.
- intros. inv H2. pose proof H. inv H. inv H9.
- destruct st.
- econstructor; simplify.
- { econstructor.
- { econstructor; intros. rewrite genmap1; crush. }
- { rewrite map2. econstructor; eauto. eapply gen_list_base. intros. rewrite <- H6.
- eauto. specialize (H6 r). rewrite H6. eauto. } }
- { econstructor; eauto. }
-Qed.
-
-Lemma sem_update :
- forall A ge sp st x st' st'' st''' f,
- sem ge sp st f st' ->
- match_states st' st''' ->
- @step_instr A ge sp st''' x st'' ->
- exists tst, sem ge sp st (update f x) tst /\ match_states st'' tst.
-Proof.
- intros. destruct x; inv H1.
- { econstructor. split.
- apply sem_update_RBnop. eassumption.
- apply match_states_commut. auto. }
- { eapply sem_update_Op; eauto. }
- { eapply sem_update_load; eauto. }
- { eapply sem_update_store; eauto. }
-Qed.
-
-Lemma sem_update2_Op :
- forall A ge sp st f r l o0 o m rs v,
- @sem A ge sp st f (mk_instr_state rs m) ->
- Op.eval_operation ge sp o0 rs ## l m = Some v ->
- sem ge sp st (update f (RBop o o0 l r)) (mk_instr_state (Regmap.set r v rs) m).
-Proof.
- intros. destruct st. constructor.
- inv H. inv H6.
- { constructor; intros. simplify.
- destruct (Pos.eq_dec r x); subst.
- { rewrite map2. econstructor. eauto.
- apply gen_list_base. eauto.
- rewrite Regmap.gss. auto. }
- { rewrite genmap1; crush. rewrite Regmap.gso; auto. } }
- { simplify. rewrite genmap1; crush. inv H. eauto. }
-Qed.
-
-Lemma sem_update2_load :
- forall A ge sp st f r o m a l m0 rs v a0,
- @sem A ge sp st f (mk_instr_state rs m0) ->
- Op.eval_addressing ge sp a rs ## l = Some a0 ->
- Mem.loadv m m0 a0 = Some v ->
- sem ge sp st (update f (RBload o m a l r)) (mk_instr_state (Regmap.set r v rs) m0).
-Proof.
- intros. simplify. inv H. inv H7. constructor.
- { constructor; intros. destruct (Pos.eq_dec r x); subst.
- { rewrite map2. rewrite Regmap.gss. econstructor; eauto.
- apply gen_list_base; eauto. }
- { rewrite genmap1; crush. rewrite Regmap.gso; eauto. }
- }
- { simplify. rewrite genmap1; crush. }
-Qed.
-
-Lemma sem_update2_store :
- forall A ge sp a0 m a l r o f st m' rs m0,
- @sem A ge sp st f (mk_instr_state rs m0) ->
- Op.eval_addressing ge sp a rs ## l = Some a0 ->
- Mem.storev m m0 a0 rs !! r = Some m' ->
- sem ge sp st (update f (RBstore o m a l r)) (mk_instr_state rs m').
-Proof.
- intros. simplify. inv H. inv H7. constructor; simplify.
- { econstructor; intros. rewrite genmap1; crush. }
- { rewrite map2. econstructor; eauto. apply gen_list_base; eauto. }
-Qed.
-
-Lemma sem_update2 :
- forall A ge sp st x st' st'' f,
- sem ge sp st f st' ->
- @step_instr A ge sp st' x st'' ->
- sem ge sp st (update f x) st''.
-Proof.
- intros.
- destruct x; inv H0;
- eauto using sem_update_RBnop, sem_update2_Op, sem_update2_load, sem_update2_store.
-Qed.
-
-Lemma abstr_sem_val_mem :
- forall A B ge tge st tst sp a,
- ge_preserved ge tge ->
- forall v m,
- (@sem_mem A ge sp st a m /\ match_states st tst -> @sem_mem B tge sp tst a m) /\
- (@sem_value A ge sp st a v /\ match_states st tst -> @sem_value B tge sp tst a v).
-Proof.
- intros * H.
- apply expression_ind2 with
-
- (P := fun (e1: expression) =>
- forall v m,
- (@sem_mem A ge sp st e1 m /\ match_states st tst -> @sem_mem B tge sp tst e1 m) /\
- (@sem_value A ge sp st e1 v /\ match_states st tst -> @sem_value B tge sp tst e1 v))
-
- (P0 := fun (e1: expression_list) =>
- forall lv, @sem_val_list A ge sp st e1 lv /\ match_states st tst -> @sem_val_list B tge sp tst e1 lv);
- simplify; intros; simplify.
- { inv H1. inv H2. constructor. }
- { inv H2. inv H1. rewrite H0. constructor. }
- { inv H3. }
- { inv H3. inv H4. econstructor. apply H1; auto. simplify. eauto. constructor. auto. auto.
- apply H0; simplify; eauto. constructor; eauto.
- unfold ge_preserved in *. simplify. rewrite <- H2. auto.
- }
- { inv H3. }
- { inv H3. inv H4. econstructor. apply H1; eauto; simplify; eauto. constructor; eauto.
- apply H0; simplify; eauto. constructor; eauto.
- inv H. rewrite <- H4. eauto.
- auto.
- }
- { inv H4. inv H5. econstructor. apply H0; eauto. simplify; eauto. constructor; eauto.
- apply H2; eauto. simplify; eauto. constructor; eauto.
- apply H1; eauto. simplify; eauto. constructor; eauto.
- inv H. rewrite <- H5. eauto. auto.
- }
- { inv H4. }
- { inv H1. constructor. }
- { inv H3. constructor; auto. apply H0; eauto. apply Mem.empty. }
-Qed.
-
-Lemma abstr_sem_value :
- forall a A B ge tge sp st tst v,
- @sem_value A ge sp st a v ->
- ge_preserved ge tge ->
- match_states st tst ->
- @sem_value B tge sp tst a v.
-Proof. intros; eapply abstr_sem_val_mem; eauto; apply Mem.empty. Qed.
-
-Lemma abstr_sem_mem :
- forall a A B ge tge sp st tst v,
- @sem_mem A ge sp st a v ->
- ge_preserved ge tge ->
- match_states st tst ->
- @sem_mem B tge sp tst a v.
-Proof. intros; eapply abstr_sem_val_mem; eauto. Qed.
-
-Lemma abstr_sem_regset :
- forall a a' A B ge tge sp st tst rs,
- @sem_regset A ge sp st a rs ->
- ge_preserved ge tge ->
- (forall x, a # x = a' # x) ->
- match_states st tst ->
- exists rs', @sem_regset B tge sp tst a' rs' /\ (forall x, rs !! x = rs' !! x).
-Proof.
- inversion 1; intros.
- inv H7.
- econstructor. simplify. econstructor. intros.
- eapply abstr_sem_value; eauto. rewrite <- H6.
- eapply H0. constructor; eauto.
- auto.
-Qed.
-
-Lemma abstr_sem :
- forall a a' A B ge tge sp st tst st',
- @sem A ge sp st a st' ->
- ge_preserved ge tge ->
- (forall x, a # x = a' # x) ->
- match_states st tst ->
- exists tst', @sem B tge sp tst a' tst' /\ match_states st' tst'.
-Proof.
- inversion 1; subst; intros.
- inversion H4; subst.
- exploit abstr_sem_regset; eauto; inv_simp.
- do 3 econstructor; eauto.
- rewrite <- H3.
- eapply abstr_sem_mem; eauto.
-Qed.
-
-Lemma abstract_execution_correct':
- forall A B ge tge sp st' a a' st tst,
- @sem A ge sp st a st' ->
- ge_preserved ge tge ->
- check a a' = true ->
- match_states st tst ->
- exists tst', @sem B tge sp tst a' tst' /\ match_states st' tst'.
-Proof.
- intros;
- pose proof (check_correct a a' H1);
- eapply abstr_sem; eauto.
-Qed.
-
-Lemma states_match :
- forall st1 st2 st3 st4,
- match_states st1 st2 ->
- match_states st2 st3 ->
- match_states st3 st4 ->
- match_states st1 st4.
-Proof.
- intros * H1 H2 H3; destruct st1; destruct st2; destruct st3; destruct st4.
- inv H1. inv H2. inv H3; constructor.
- unfold regs_lessdef in *. intros.
- repeat match goal with
- | H: forall _, _, r : positive |- _ => specialize (H r)
- end.
- congruence.
- auto.
-Qed.
-
-Lemma step_instr_block_same :
- forall ge sp st st',
- step_instr_block ge sp st nil st' ->
- st = st'.
-Proof. inversion 1; auto. Qed.
-
-Lemma step_instr_seq_same :
- forall ge sp st st',
- step_instr_seq ge sp st nil st' ->
- st = st'.
-Proof. inversion 1; auto. Qed.
-
-Lemma sem_update' :
- forall A ge sp st a x st',
- sem ge sp st (update (abstract_sequence empty a) x) st' ->
- exists st'',
- @step_instr A ge sp st'' x st' /\
- sem ge sp st (abstract_sequence empty a) st''.
-Proof.
- Admitted.
-
-Lemma rtlpar_trans_correct :
- forall bb ge sp sem_st' sem_st st,
- sem ge sp sem_st (abstract_sequence empty (concat (concat bb))) sem_st' ->
- match_states sem_st st ->
- exists st', RTLPar.step_instr_block ge sp st bb st'
- /\ match_states sem_st' st'.
-Proof.
- induction bb using rev_ind.
- { repeat econstructor. eapply abstract_interp_empty3 in H.
- inv H. inv H0. constructor; congruence. }
- { simplify. inv H0. repeat rewrite concat_app in H. simplify.
- rewrite app_nil_r in H.
- exploit sem_separate; eauto; inv_simp.
- repeat econstructor. admit. admit.
- }
-Admitted.
-
-(*Lemma abstract_execution_correct_ld:
- forall bb bb' cfi ge tge sp st st' tst,
- RTLBlock.step_instr_list ge sp st bb st' ->
- ge_preserved ge tge ->
- schedule_oracle (mk_bblock bb cfi) (mk_bblock bb' cfi) = true ->
- match_states_ld st tst ->
- exists tst', RTLPar.step_instr_block tge sp tst bb' tst'
- /\ match_states st' tst'.
-Proof.
- intros.*)
-*)
-
-Lemma match_states_list :
- forall A (rs: Regmap.t A) rs',
- (forall r, rs !! r = rs' !! r) ->
- forall l, rs ## l = rs' ## l.
-Proof. induction l; crush. Qed.
-
-Lemma PTree_matches :
- forall A (v: A) res rs rs',
- (forall r, rs !! r = rs' !! r) ->
- forall x, (Regmap.set res v rs) !! x = (Regmap.set res v rs') !! x.
-Proof.
- intros; destruct (Pos.eq_dec x res); subst;
- [ repeat rewrite Regmap.gss by auto
- | repeat rewrite Regmap.gso by auto ]; auto.
-Qed.
-
-Lemma abstract_interp_empty3 :
- forall A ctx st',
- @sem A ctx empty st' -> match_states (ctx_is ctx) st'.
-Proof.
- inversion 1; subst; simplify. destruct ctx.
- destruct ctx_is.
- constructor; intros.
- - inv H0. specialize (H3 x). inv H3. inv H8. reflexivity.
- - inv H1. specialize (H3 x). inv H3. inv H8. reflexivity.
- - inv H2. inv H8. reflexivity.
-Qed.
-
-Lemma step_instr_matches :
- forall A a ge sp st st',
- @step_instr A ge sp st a st' ->
- forall tst,
- match_states st tst ->
- exists tst', step_instr ge sp tst a tst'
- /\ match_states st' tst'.
-Proof.
- induction 1; simplify;
- match goal with H: match_states _ _ |- _ => inv H end;
- try solve [repeat econstructor; try erewrite match_states_list;
- try apply PTree_matches; eauto;
- match goal with
- H: forall _, _ |- context[Mem.storev] => erewrite <- H; eauto
- end].
- - destruct p. match goal with H: eval_pred _ _ _ _ |- _ => inv H end.
- repeat econstructor; try erewrite match_states_list; eauto.
- erewrite <- eval_predf_pr_equiv; eassumption.
- apply PTree_matches; assumption.
- repeat (econstructor; try apply eval_pred_false); eauto. try erewrite match_states_list; eauto.
- erewrite <- eval_predf_pr_equiv; eassumption.
- econstructor; auto.
- match goal with H: eval_pred _ _ _ _ |- _ => inv H end.
- repeat econstructor; try erewrite match_states_list; eauto.
- - destruct p. match goal with H: eval_pred _ _ _ _ |- _ => inv H end.
- repeat econstructor; try erewrite match_states_list; eauto.
- erewrite <- eval_predf_pr_equiv; eassumption.
- apply PTree_matches; assumption.
- repeat (econstructor; try apply eval_pred_false); eauto. try erewrite match_states_list; eauto.
- erewrite <- eval_predf_pr_equiv; eassumption.
- econstructor; auto.
- match goal with H: eval_pred _ _ _ _ |- _ => inv H end.
- repeat econstructor; try erewrite match_states_list; eauto.
- - destruct p. match goal with H: eval_pred _ _ _ _ |- _ => inv H end.
- repeat econstructor; try erewrite match_states_list; eauto.
- match goal with
- H: forall _, _ |- context[Mem.storev] => erewrite <- H; eauto
- end.
- erewrite <- eval_predf_pr_equiv; eassumption.
- repeat (econstructor; try apply eval_pred_false); eauto. try erewrite match_states_list; eauto.
- match goal with
- H: forall _, _ |- context[Mem.storev] => erewrite <- H; eauto
- end.
- erewrite <- eval_predf_pr_equiv; eassumption.
- match goal with H: eval_pred _ _ _ _ |- _ => inv H end.
- repeat econstructor; try erewrite match_states_list; eauto.
- match goal with
- H: forall _, _ |- context[Mem.storev] => erewrite <- H; eauto
- end.
- - admit. Admitted.
-
-Lemma step_instr_list_matches :
- forall a ge sp st st',
- step_instr_list ge sp st a st' ->
- forall tst, match_states st tst ->
- exists tst', step_instr_list ge sp tst a tst'
- /\ match_states st' tst'.
-Proof.
- induction a; intros; inv H;
- try (exploit step_instr_matches; eauto; []; simplify;
- exploit IHa; eauto; []; simplify); repeat econstructor; eauto.
-Qed.
-
-Lemma step_instr_seq_matches :
- forall a ge sp st st',
- step_instr_seq ge sp st a st' ->
- forall tst, match_states st tst ->
- exists tst', step_instr_seq ge sp tst a tst'
- /\ match_states st' tst'.
-Proof.
- induction a; intros; inv H;
- try (exploit step_instr_list_matches; eauto; []; simplify;
- exploit IHa; eauto; []; simplify); repeat econstructor; eauto.
-Qed.
-
-Lemma step_instr_block_matches :
- forall bb ge sp st st',
- step_instr_block ge sp st bb st' ->
- forall tst, match_states st tst ->
- exists tst', step_instr_block ge sp tst bb tst'
- /\ match_states st' tst'.
-Proof.
- induction bb; intros; inv H;
- try (exploit step_instr_seq_matches; eauto; []; simplify;
- exploit IHbb; eauto; []; simplify); repeat econstructor; eauto.
-Qed.
-
-Lemma rtlblock_trans_correct' :
- forall bb ge sp st x st'',
- RTLBlock.step_instr_list ge sp st (bb ++ x :: nil) st'' ->
- exists st', RTLBlock.step_instr_list ge sp st bb st'
- /\ step_instr ge sp st' x st''.
-Proof.
- induction bb.
- crush. exists st.
- split. constructor. inv H. inv H6. auto.
- crush. inv H. exploit IHbb. eassumption. simplify.
- econstructor. split.
- econstructor; eauto. eauto.
-Qed.
-
-Lemma abstract_interp_empty A st : @sem A st empty (ctx_is st).
-Proof. destruct st, ctx_is. simpl. repeat econstructor. Qed.
-
-Lemma abstract_seq :
- forall l f i,
- abstract_sequence f (l ++ i :: nil) = update (abstract_sequence f l) i.
-Proof. induction l; crush. Qed.
-
-Lemma abstract_sequence_update :
- forall l r f,
- check_dest_l l r = false ->
- (abstract_sequence f l) # (Reg r) = f # (Reg r).
-Proof.
- induction l using rev_ind; crush.
- rewrite abstract_seq. rewrite check_dest_update. apply IHl.
- apply check_list_l_false in H. tauto.
- apply check_list_l_false in H. tauto.
-Qed.
-
-(*Lemma sem_separate :
- forall A ctx b a st',
- sem ctx (abstract_sequence empty (a ++ b)) st' ->
- exists st'',
- @sem A ctx (abstract_sequence empty a) st''
- /\ @sem A (mk_ctx st'' (ctx_sp ctx) (ctx_ge ctx)) (abstract_sequence empty b) st'.
-Proof.
- induction b using rev_ind; simplify.
- { econstructor. simplify. rewrite app_nil_r in H. eauto. apply abstract_interp_empty. }
- { simplify. rewrite app_assoc in H. rewrite abstract_seq in H.
- exploit sem_update'; eauto; simplify.
- exploit IHb; eauto; inv_simp.
- econstructor; split; eauto.
- rewrite abstract_seq.
- eapply sem_update2; eauto.
- }
-Qed.*)
-
-Lemma sem_update_RBnop :
- forall A ctx f st',
- @sem A ctx f st' -> sem ctx (update f RBnop) st'.
-Proof. auto. Qed.
-
-Lemma sem_update_Op :
- forall A ge sp ist f st' r l o0 o m rs v ps,
- @sem A (mk_ctx ist sp ge) f st' ->
- eval_predf ps o = true ->
- Op.eval_operation ge sp o0 (rs ## l) m = Some v ->
- match_states st' (mk_instr_state rs ps m) ->
- exists tst,
- sem (mk_ctx ist sp ge) (update f (RBop (Some o) o0 l r)) tst
- /\ match_states (mk_instr_state (Regmap.set r v rs) ps m) tst.
-Proof.
- intros. inv H1. inv H. inv H1. inv H3. simplify.
- econstructor. simplify.
- { constructor; try constructor; intros; try solve [rewrite genmap1; now eauto].
- destruct (Pos.eq_dec x r); subst.
- { rewrite map2. specialize (H1 r). inv H1.
-(*}
- }
- destruct st.
- econstructor. simplify.
- { constructor.
- { constructor. intros. destruct (Pos.eq_dec x r); subst.
- { pose proof (H5 r). rewrite map2. pose proof H. inv H. econstructor; eauto.
- { inv H9. eapply gen_list_base; eauto. }
- { instantiate (1 := (Regmap.set r v rs0)). rewrite Regmap.gss. erewrite regmap_list_equiv; eauto. } }
- { rewrite Regmap.gso by auto. rewrite genmap1; crush. inv H. inv H7; eauto. } }
- { inv H. rewrite genmap1; crush. eauto. } }
- { constructor; eauto. intros.
- destruct (Pos.eq_dec r x);
- subst; [repeat rewrite Regmap.gss | repeat rewrite Regmap.gso]; auto. }
-Qed.*) Admitted.
-
-Lemma sem_update :
- forall A ge sp st x st' st'' st''' f,
- sem (mk_ctx st sp ge) f st' ->
- match_states st' st''' ->
- @step_instr A ge sp st''' x st'' ->
- exists tst, sem (mk_ctx st sp ge) (update f x) tst /\ match_states st'' tst.
-Proof.
- intros. destruct x.
- - inv H1. econstructor. simplify. eauto. symmetry; auto.
- - inv H1. inv H0. econstructor.
- Admitted.
-
-Lemma rtlblock_trans_correct :
- forall bb ge sp st st',
- RTLBlock.step_instr_list ge sp st bb st' ->
- forall tst,
- match_states st tst ->
- exists tst', sem (mk_ctx tst sp ge) (abstract_sequence empty bb) tst'
- /\ match_states st' tst'.
-Proof.
- induction bb using rev_ind; simplify.
- { econstructor. simplify. apply abstract_interp_empty.
- inv H. auto. }
- { apply rtlblock_trans_correct' in H. simplify.
- rewrite abstract_seq.
- exploit IHbb; try eassumption; []; simplify.
- exploit sem_update. apply H1. symmetry; eassumption.
- eauto. simplify. econstructor. split. apply H3.
- auto. }
-Qed.
-
-Lemma abstract_execution_correct:
- forall bb bb' cfi cfi' ge tge sp st st' tst,
- RTLBlock.step_instr_list ge sp st bb st' ->
- ge_preserved ge tge ->
- schedule_oracle (mk_bblock bb cfi) (mk_bblock bb' cfi') = true ->
- match_states st tst ->
- exists tst', RTLPar.step_instr_block tge sp tst bb' tst'
- /\ match_states st' tst'.
-Proof.
- intros.
- unfold schedule_oracle in *. simplify. unfold empty_trees in H4.
- exploit rtlblock_trans_correct; try eassumption; []; simplify.
-(*) exploit abstract_execution_correct';
- try solve [eassumption | apply state_lessdef_match_sem; eassumption].
- apply match_states_commut. eauto. inv_simp.
- exploit rtlpar_trans_correct; try eassumption; []; inv_simp.
- exploit step_instr_block_matches; eauto. apply match_states_commut; eauto. inv_simp.
- repeat match goal with | H: match_states _ _ |- _ => inv H end.
- do 2 econstructor; eauto.
- econstructor; congruence.
-Qed.*)Admitted.
-
-Definition match_prog (prog : RTLBlock.program) (tprog : RTLPar.program) :=
- match_program (fun cu f tf => transl_fundef f = Errors.OK tf) eq prog tprog.
-
-Inductive match_stackframes: RTLBlock.stackframe -> RTLPar.stackframe -> Prop :=
-| match_stackframe:
- forall f tf res sp pc rs rs' ps ps',
- transl_function f = OK tf ->
- (forall x, rs !! x = rs' !! x) ->
- (forall x, ps !! x = ps' !! x) ->
- match_stackframes (Stackframe res f sp pc rs ps)
- (Stackframe res tf sp pc rs' ps').
-
-Inductive match_states: RTLBlock.state -> RTLPar.state -> Prop :=
-| match_state:
- forall sf f sp pc rs rs' m sf' tf ps ps'
- (TRANSL: transl_function f = OK tf)
- (STACKS: list_forall2 match_stackframes sf sf')
- (REG: forall x, rs !! x = rs' !! x)
- (REG: forall x, ps !! x = ps' !! x),
- match_states (State sf f sp pc rs ps m)
- (State sf' tf sp pc rs' ps' m)
-| match_returnstate:
- forall stack stack' v m
- (STACKS: list_forall2 match_stackframes stack stack'),
- match_states (Returnstate stack v m)
- (Returnstate stack' v m)
-| match_callstate:
- forall stack stack' f tf args m
- (TRANSL: transl_fundef f = OK tf)
- (STACKS: list_forall2 match_stackframes stack stack'),
- match_states (Callstate stack f args m)
- (Callstate stack' tf args m).
-
-Section CORRECTNESS.
-
- Context (prog: RTLBlock.program) (tprog : RTLPar.program).
- Context (TRANSL: match_prog prog tprog).
-
- Let ge : RTLBlock.genv := Globalenvs.Genv.globalenv prog.
- Let tge : RTLPar.genv := Globalenvs.Genv.globalenv tprog.
-
- Lemma symbols_preserved:
- forall (s: AST.ident), Genv.find_symbol tge s = Genv.find_symbol ge s.
- Proof using TRANSL. intros. eapply (Genv.find_symbol_match TRANSL). Qed.
- Hint Resolve symbols_preserved : rtlgp.
-
- Lemma function_ptr_translated:
- forall (b: Values.block) (f: RTLBlock.fundef),
- Genv.find_funct_ptr ge b = Some f ->
- exists tf,
- Genv.find_funct_ptr tge b = Some tf /\ transl_fundef f = Errors.OK tf.
- Proof using TRANSL.
- intros. exploit (Genv.find_funct_ptr_match TRANSL); eauto.
- intros (cu & tf & P & Q & R); exists tf; auto.
- Qed.
-
- Lemma functions_translated:
- forall (v: Values.val) (f: RTLBlock.fundef),
- Genv.find_funct ge v = Some f ->
- exists tf,
- Genv.find_funct tge v = Some tf /\ transl_fundef f = Errors.OK tf.
- Proof using TRANSL.
- intros. exploit (Genv.find_funct_match TRANSL); eauto.
- intros (cu & tf & P & Q & R); exists tf; auto.
- Qed.
-
- Lemma senv_preserved:
- Senv.equiv (Genv.to_senv ge) (Genv.to_senv tge).
- Proof (Genv.senv_transf_partial TRANSL).
- Hint Resolve senv_preserved : rtlgp.
-
- Lemma sig_transl_function:
- forall (f: RTLBlock.fundef) (tf: RTLPar.fundef),
- transl_fundef f = OK tf ->
- funsig tf = funsig f.
- Proof using .
- unfold transl_fundef, transf_partial_fundef, transl_function; intros;
- repeat destruct_match; crush;
- match goal with H: OK _ = OK _ |- _ => inv H end; auto.
- Qed.
- Hint Resolve sig_transl_function : rtlgp.
-
- Hint Resolve Val.lessdef_same : rtlgp.
- Hint Resolve regs_lessdef_regs : rtlgp.
-
- Lemma find_function_translated:
- forall ros rs rs' f,
- (forall x, rs !! x = rs' !! x) ->
- find_function ge ros rs = Some f ->
- exists tf, find_function tge ros rs' = Some tf
- /\ transl_fundef f = OK tf.
- Proof using TRANSL.
- Ltac ffts := match goal with
- | [ H: forall _, Val.lessdef _ _, r: Registers.reg |- _ ] =>
- specialize (H r); inv H
- | [ H: Vundef = ?r, H1: Genv.find_funct _ ?r = Some _ |- _ ] =>
- rewrite <- H in H1
- | [ H: Genv.find_funct _ Vundef = Some _ |- _] => solve [inv H]
- | _ => solve [exploit functions_translated; eauto]
- end.
- destruct ros; simplify; try rewrite <- H;
- [| rewrite symbols_preserved; destruct_match;
- try (apply function_ptr_translated); crush ];
- intros;
- repeat ffts.
- Qed.
-
- Lemma schedule_oracle_nil:
- forall bb cfi,
- schedule_oracle {| bb_body := nil; bb_exit := cfi |} bb = true ->
- bb_body bb = nil /\ bb_exit bb = cfi.
- Proof using .
- unfold schedule_oracle, check_control_flow_instr.
- simplify; repeat destruct_match; crush.
- Qed.
-
- Lemma schedule_oracle_nil2:
- forall cfi,
- schedule_oracle {| bb_body := nil; bb_exit := cfi |}
- {| bb_body := nil; bb_exit := cfi |} = true.
- Proof using .
- unfold schedule_oracle, check_control_flow_instr.
- simplify; repeat destruct_match; crush.
- Qed.
-
- Lemma eval_op_eq:
- forall (sp0 : Values.val) (op : Op.operation) (vl : list Values.val) m,
- Op.eval_operation ge sp0 op vl m = Op.eval_operation tge sp0 op vl m.
- Proof using TRANSL.
- intros.
- destruct op; auto; unfold Op.eval_operation, Genv.symbol_address, Op.eval_addressing32;
- [| destruct a; unfold Genv.symbol_address ];
- try rewrite symbols_preserved; auto.
- Qed.
- Hint Resolve eval_op_eq : rtlgp.
-
- Lemma eval_addressing_eq:
- forall sp addr vl,
- Op.eval_addressing ge sp addr vl = Op.eval_addressing tge sp addr vl.
- Proof using TRANSL.
- intros.
- destruct addr;
- unfold Op.eval_addressing, Op.eval_addressing32;
- unfold Genv.symbol_address;
- try rewrite symbols_preserved; auto.
- Qed.
- Hint Resolve eval_addressing_eq : rtlgp.
-
- Lemma ge_preserved_lem:
- ge_preserved ge tge.
- Proof using TRANSL.
- unfold ge_preserved.
- eauto with rtlgp.
- Qed.
- Hint Resolve ge_preserved_lem : rtlgp.
-
- Lemma lessdef_regmap_optget:
- forall or rs rs',
- regs_lessdef rs rs' ->
- Val.lessdef (regmap_optget or Vundef rs) (regmap_optget or Vundef rs').
- Proof using. destruct or; crush. Qed.
- Hint Resolve lessdef_regmap_optget : rtlgp.
-
- Lemma regmap_equiv_lessdef:
- forall rs rs',
- (forall x, rs !! x = rs' !! x) ->
- regs_lessdef rs rs'.
- Proof using.
- intros; unfold regs_lessdef; intros.
- rewrite H. apply Val.lessdef_refl.
- Qed.
- Hint Resolve regmap_equiv_lessdef : rtlgp.
-
- Lemma int_lessdef:
- forall rs rs',
- regs_lessdef rs rs' ->
- (forall arg v,
- rs !! arg = Vint v ->
- rs' !! arg = Vint v).
- Proof using. intros ? ? H; intros; specialize (H arg); inv H; crush. Qed.
- Hint Resolve int_lessdef : rtlgp.
-
- Ltac semantics_simpl :=
- match goal with
- | [ H: match_states _ _ |- _ ] =>
- let H2 := fresh "H" in
- learn H as H2; inv H2
- | [ H: transl_function ?f = OK _ |- _ ] =>
- let H2 := fresh "TRANSL" in
- learn H as H2;
- unfold transl_function in H2;
- destruct (check_scheduled_trees
- (@fn_code RTLBlock.bb f)
- (@fn_code RTLPar.bb (schedule f))) eqn:?;
- [| discriminate ]; inv H2
- | [ H: context[check_scheduled_trees] |- _ ] =>
- let H2 := fresh "CHECK" in
- learn H as H2;
- eapply check_scheduled_trees_correct in H2; [| solve [eauto] ]
- | [ H: schedule_oracle {| bb_body := nil; bb_exit := _ |} ?bb = true |- _ ] =>
- let H2 := fresh "SCHED" in
- learn H as H2;
- apply schedule_oracle_nil in H2
- | [ H: find_function _ _ _ = Some _, H2: forall x, ?rs !! x = ?rs' !! x |- _ ] =>
- learn H; exploit find_function_translated; try apply H2; eauto; inversion 1
- | [ H: Mem.free ?m _ _ _ = Some ?m', H2: Mem.extends ?m ?m'' |- _ ] =>
- learn H; exploit Mem.free_parallel_extends; eauto; intros
- | [ H: Events.eval_builtin_args _ _ _ _ _ _, H2: regs_lessdef ?rs ?rs' |- _ ] =>
- let H3 := fresh "H" in
- learn H; exploit Events.eval_builtin_args_lessdef; [apply H2 | | |];
- eauto with rtlgp; intro H3; learn H3
- | [ H: Events.external_call _ _ _ _ _ _ _ |- _ ] =>
- let H2 := fresh "H" in
- learn H; exploit Events.external_call_mem_extends;
- eauto; intro H2; learn H2
- | [ H: exists _, _ |- _ ] => inv H
- | _ => progress simplify
- end.
-
- Hint Resolve Events.eval_builtin_args_preserved : rtlgp.
- Hint Resolve Events.external_call_symbols_preserved : rtlgp.
- Hint Resolve set_res_lessdef : rtlgp.
- Hint Resolve set_reg_lessdef : rtlgp.
- Hint Resolve Op.eval_condition_lessdef : rtlgp.
-
- Hint Constructors Events.eval_builtin_arg: barg.
-
- Lemma eval_builtin_arg_eq:
- forall A ge a v1 m1 e1 e2 sp,
- (forall x, e1 x = e2 x) ->
- @Events.eval_builtin_arg A ge e1 sp m1 a v1 ->
- Events.eval_builtin_arg ge e2 sp m1 a v1.
-Proof. induction 2; try rewrite H; eauto with barg. Qed.
-
- Lemma eval_builtin_args_eq:
- forall A ge e1 sp m1 e2 al vl1,
- (forall x, e1 x = e2 x) ->
- @Events.eval_builtin_args A ge e1 sp m1 al vl1 ->
- Events.eval_builtin_args ge e2 sp m1 al vl1.
- Proof.
- induction 2.
- - econstructor; split.
- - exploit eval_builtin_arg_eq; eauto. intros.
- destruct IHlist_forall2 as [| y]. constructor; eauto.
- constructor. constructor; auto.
- constructor; eauto.
- Qed.
-
- Lemma step_cf_instr_correct:
- forall cfi t s s',
- step_cf_instr ge s cfi t s' ->
- forall r,
- match_states s r ->
- exists r', step_cf_instr tge r cfi t r' /\ match_states s' r'.
- Proof using TRANSL.
- induction 1; repeat semantics_simpl;
- try solve [repeat (try erewrite match_states_list; eauto; econstructor; eauto with rtlgp)].
- { do 3 (try erewrite match_states_list by eauto; econstructor; eauto with rtlgp).
- eapply eval_builtin_args_eq. eapply REG.
- eapply Events.eval_builtin_args_preserved. eapply symbols_preserved.
- eauto.
- intros.
- unfold regmap_setres. destruct res.
- destruct (Pos.eq_dec x0 x); subst.
- repeat rewrite Regmap.gss; auto.
- repeat rewrite Regmap.gso; auto.
- eapply REG. eapply REG.
- }
- { repeat (try erewrite match_states_list; eauto; econstructor; eauto with rtlgp).
- unfold regmap_optget. destruct or. rewrite REG. constructor; eauto.
- constructor; eauto.
- }
- { exploit IHstep_cf_instr; eauto. simplify.
- repeat (try erewrite match_states_list; eauto; econstructor; eauto with rtlgp).
- erewrite eval_predf_pr_equiv; eauto.
- }
- Qed.
-
- Theorem transl_step_correct :
- forall (S1 : RTLBlock.state) t S2,
- RTLBlock.step ge S1 t S2 ->
- forall (R1 : RTLPar.state),
- match_states S1 R1 ->
- exists R2, Smallstep.plus RTLPar.step tge R1 t R2 /\ match_states S2 R2.
- Proof.
-
- induction 1; repeat semantics_simpl.
-
- { destruct bb; destruct x.
- assert (bb_exit = bb_exit0).
- { unfold schedule_oracle in *. simplify.
- unfold check_control_flow_instr in *.
- destruct_match; crush.
- }
- subst.
-
- exploit abstract_execution_correct; try eassumption. eapply ge_preserved_lem.
- econstructor; eauto.
- simplify. destruct x. inv H7.
-
- exploit step_cf_instr_correct; try eassumption. econstructor; eauto.
- simplify.
-
- econstructor. econstructor. eapply Smallstep.plus_one. econstructor.
- eauto. eauto. simplify. eauto. eauto. }
- { unfold bind in *. inv TRANSL0. clear Learn. inv H0. destruct_match; crush.
- inv H2. unfold transl_function in Heqr. destruct_match; crush.
- inv Heqr.
- repeat econstructor; eauto.
- unfold bind in *. destruct_match; crush. }
- { inv TRANSL0. repeat econstructor; eauto using Events.external_call_symbols_preserved, symbols_preserved, senv_preserved, Events.E0_right. }
- { inv STACKS. inv H2. repeat econstructor; eauto.
- intros. apply PTree_matches; eauto. }
- Qed.
-
- Lemma transl_initial_states:
- forall S,
- RTLBlock.initial_state prog S ->
- exists R, RTLPar.initial_state tprog R /\ match_states S R.
- Proof.
- induction 1.
- exploit function_ptr_translated; eauto. intros [tf [A B]].
- econstructor; split.
- econstructor. apply (Genv.init_mem_transf_partial TRANSL); eauto.
- replace (prog_main tprog) with (prog_main prog). rewrite symbols_preserved; eauto.
- symmetry; eapply match_program_main; eauto.
- eexact A.
- rewrite <- H2. apply sig_transl_function; auto.
- constructor. auto. constructor.
- Qed.
-
- Lemma transl_final_states:
- forall S R r,
- match_states S R -> RTLBlock.final_state S r -> RTLPar.final_state R r.
- Proof.
- intros. inv H0. inv H. inv STACKS. constructor.
- Qed.
-
- Theorem transf_program_correct:
- Smallstep.forward_simulation (RTLBlock.semantics prog) (RTLPar.semantics tprog).
- Proof.
- eapply Smallstep.forward_simulation_plus.
- apply senv_preserved.
- eexact transl_initial_states.
- eexact transl_final_states.
- exact transl_step_correct.
- Qed.
-
-End CORRECTNESS.
-#+end_src
-
-* License
-
-#+name: license
-#+begin_src coq :tangle no
-(*
- * Vericert: Verified high-level synthesis.
- * Copyright (C) 2020-2022 Yann Herklotz <yann@yannherklotz.com>
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- *)
-#+end_src