diff options
Diffstat (limited to 'src/hls')
-rw-r--r-- | src/hls/ApplyExternctrl.v | 202 | ||||
-rw-r--r-- | src/hls/AssocMap.v | 17 | ||||
-rw-r--r-- | src/hls/HTL.v | 141 | ||||
-rw-r--r-- | src/hls/HTLBlockgen.v | 167 | ||||
-rw-r--r-- | src/hls/HTLPargen.v | 23 | ||||
-rw-r--r-- | src/hls/HTLgen.v | 516 | ||||
-rw-r--r-- | src/hls/HTLgenproof.v | 1214 | ||||
-rw-r--r-- | src/hls/HTLgenspec.v | 921 | ||||
-rw-r--r-- | src/hls/PrintHTL.ml | 69 | ||||
-rw-r--r-- | src/hls/PrintVerilog.mli | 2 | ||||
-rw-r--r-- | src/hls/Renaming.v | 231 | ||||
-rw-r--r-- | src/hls/Verilog.v | 14 | ||||
-rw-r--r-- | src/hls/Veriloggen.v | 202 | ||||
-rw-r--r-- | src/hls/Veriloggenproof.v | 739 |
14 files changed, 2711 insertions, 1747 deletions
diff --git a/src/hls/ApplyExternctrl.v b/src/hls/ApplyExternctrl.v new file mode 100644 index 0000000..b024b9e --- /dev/null +++ b/src/hls/ApplyExternctrl.v @@ -0,0 +1,202 @@ +Require Import compcert.common.Errors. +Require Import compcert.common.AST. + +Require Import vericert.common.Maps. +Require Import vericert.common.Statemonad. +Require Import vericert.common.Vericertlib. +Require Import vericert.hls.AssocMap. +Require Import vericert.hls.HTL. +Require Import vericert.hls.Verilog. + +Import ListNotations. + +Section APPLY_EXTERNCTRL. + Local Open Scope assocmap. + Local Open Scope error_monad_scope. + + Variable prog : HTL.program. + Variable m : HTL.module. + + Let modmap := prog_modmap prog. + + Definition global_clk := + match modmap ! (AST.prog_main prog) with + | None => Error (msg "ApplyExternctrl: No main") + | Some main => OK (HTL.mod_clk main) + end. + + Definition get_mod_signal (othermod : HTL.module) (signal : HTL.controlsignal) := + match signal with + | ctrl_finish => OK (HTL.mod_finish othermod) + | ctrl_return => OK (HTL.mod_return othermod) + | ctrl_start => OK (HTL.mod_start othermod) + | ctrl_reset => OK (HTL.mod_reset othermod) + | ctrl_clk => OK (HTL.mod_clk othermod) + | ctrl_param idx => + match List.nth_error (HTL.mod_params othermod) idx with + | Some r => OK r + | None => Error (msg "Module does not have nth parameter") + end + end. + + Definition reg_apply_externctrl (r : Verilog.reg) : res reg := + match (HTL.mod_externctrl m) ! r with + | None => OK r + | Some (m, signal) => + match modmap ! m with + | None => Error (msg "Veriloggen: Could not find definition for called module") + | Some othermod => get_mod_signal othermod signal + end + end. + + Fixpoint expr_apply_externctrl (expr : Verilog.expr) {struct expr} : res Verilog.expr := + match expr with + | Vlit n => + OK (Vlit n) + | Vvar r => + do r' <- reg_apply_externctrl r; + OK (Vvar r') + | Vvari r e => + do r' <- reg_apply_externctrl r; + do e' <- expr_apply_externctrl e; + OK (Vvari r e) + | Vrange r e1 e2 => + do r' <- reg_apply_externctrl r; + do e1' <- expr_apply_externctrl e1; + do e2' <- expr_apply_externctrl e2; + OK (Vrange r' e1' e2') + | Vinputvar r => + do r' <- reg_apply_externctrl r; + OK (Vinputvar r') + | Vbinop op e1 e2 => + do e1' <- expr_apply_externctrl e1; + do e2' <- expr_apply_externctrl e2; + OK (Vbinop op e1' e2') + | Vunop op e => + do e' <- expr_apply_externctrl e; + OK (Vunop op e') + | Vternary e1 e2 e3 => + do e1' <- expr_apply_externctrl e1; + do e2' <- expr_apply_externctrl e2; + do e3' <- expr_apply_externctrl e3; + OK (Vternary e1' e2' e3') + end. + + Definition mmap_option {A B} (f : A -> res B) (opt : option A) : res (option B) := + match opt with + | None => OK None + | Some a => do a' <- f a; OK (Some a') + end. + + Definition cases_apply_externctrl_ (stmnt_apply_externctrl_ : Verilog.stmnt -> res Verilog.stmnt) := + fix cases_apply_externctrl (cs : list (Verilog.expr * Verilog.stmnt)) := + match cs with + | nil => OK nil + | (c_e, c_s) :: tl => + do c_e' <- expr_apply_externctrl c_e; + do c_s' <- stmnt_apply_externctrl_ c_s; + do tl' <- cases_apply_externctrl tl; + OK ((c_e', c_s') :: tl') + end. + + Fixpoint stmnt_apply_externctrl (stmnt : Verilog.stmnt) {struct stmnt} : res Verilog.stmnt := + match stmnt with + | Vskip => OK Vskip + | Vseq s1 s2 => + do s1' <- stmnt_apply_externctrl s1; + do s2' <- stmnt_apply_externctrl s2; + OK (Vseq s1' s2') + | Vcond e s1 s2 => + do e' <- expr_apply_externctrl e; + do s1' <- stmnt_apply_externctrl s1; + do s2' <- stmnt_apply_externctrl s2; + OK (Vcond e' s1' s2') + | Vcase e cases def => + do e' <- expr_apply_externctrl e; + do cases' <- cases_apply_externctrl_ stmnt_apply_externctrl cases; + do def' <- mmap_option (fun x => stmnt_apply_externctrl x) def; + OK (Vcase e' cases' def') + | Vblock e1 e2 => + do e1' <- expr_apply_externctrl e1; + do e2' <- expr_apply_externctrl e2; + OK (Vblock e1' e2') + | Vnonblock e1 e2 => + do e1' <- expr_apply_externctrl e1; + do e2' <- expr_apply_externctrl e2; + OK (Vnonblock e1' e2') + end. + + (* Unused. Defined for completeness *) + Definition cases_apply_externctrl := cases_apply_externctrl_ stmnt_apply_externctrl. + + Fixpoint xassocmap_apply_externctrl {A} (regmap : list (reg * A)) : res (list (reg * A)) := + match regmap with + | nil => OK nil + | (r, v) :: l => + do r' <- reg_apply_externctrl r; + do l' <- xassocmap_apply_externctrl l; + OK ((r', v) :: l') + end. + + Definition assocmap_apply_externctrl {A} (regmap : AssocMap.t A) : res (AssocMap.t A) := + do l <- xassocmap_apply_externctrl (AssocMap.elements regmap); + OK (AssocMap_Properties.of_list l). + + Definition module_apply_externctrl : res HTL.module := + do mod_start' <- reg_apply_externctrl (HTL.mod_start m); + do mod_reset' <- reg_apply_externctrl (HTL.mod_reset m); + do mod_clk' <- global_clk; + do mod_finish' <- reg_apply_externctrl (HTL.mod_finish m); + do mod_return' <- reg_apply_externctrl (HTL.mod_return m); + do mod_st' <- reg_apply_externctrl (HTL.mod_st m); + do mod_stk' <- reg_apply_externctrl (HTL.mod_stk m); + do mod_params' <- mmap reg_apply_externctrl (HTL.mod_params m); + do mod_controllogic' <- PTree.traverse1 stmnt_apply_externctrl (HTL.mod_controllogic m); + do mod_datapath' <- PTree.traverse1 stmnt_apply_externctrl (HTL.mod_datapath m); + + do mod_scldecls' <- assocmap_apply_externctrl (HTL.mod_scldecls m); + do mod_arrdecls' <- assocmap_apply_externctrl (HTL.mod_arrdecls m); + do mod_externctrl' <- assocmap_apply_externctrl (HTL.mod_externctrl m); + + match zle (Z.pos (max_pc_map mod_datapath')) Integers.Int.max_unsigned, + zle (Z.pos (max_pc_map mod_controllogic')) Integers.Int.max_unsigned with + | left LEDATA, left LECTRL => + OK (HTL.mkmodule + mod_params' + mod_datapath' + mod_controllogic' + (HTL.mod_entrypoint m) + mod_st' + mod_stk' + (HTL.mod_stk_len m) + mod_finish' + mod_return' + mod_start' + mod_reset' + mod_clk' + mod_scldecls' + mod_arrdecls' + mod_externctrl' + (conj (max_pc_wf _ _ LECTRL) (max_pc_wf _ _ LEDATA))) + | _, _ => Error (Errors.msg "More than 2^32 states.") + end. +End APPLY_EXTERNCTRL. + +Definition transf_fundef (prog : HTL.program) := transf_partial_fundef (module_apply_externctrl prog). +Definition transf_program (prog : HTL.program) := transform_partial_program (transf_fundef prog) prog. + +(* Semantics *) + +Definition match_prog : HTL.program -> HTL.program -> Prop := + Linking.match_program (fun ctx f tf => ApplyExternctrl.transf_fundef ctx f = OK tf) eq. + +Lemma transf_program_match : forall p tp, + ApplyExternctrl.transf_program p = OK tp -> match_prog p tp. +Admitted. + +Lemma transf_program_correct : forall p tp, + match_prog p tp -> Smallstep.forward_simulation (HTL.semantics p) (HTL.semantics tp). +Admitted. + +Instance TransfLink : Linking.TransfLink match_prog. +Admitted. diff --git a/src/hls/AssocMap.v b/src/hls/AssocMap.v index 98eda9c..7b9ef9f 100644 --- a/src/hls/AssocMap.v +++ b/src/hls/AssocMap.v @@ -25,6 +25,7 @@ Require Import vericert.hls.ValueInt. Definition reg := positive. Module AssocMap := Maps.PTree. +Module AssocMap_Properties := Maps.PTree_Properties. Module AssocMapExt. Import AssocMap. @@ -229,3 +230,19 @@ Lemma find_get_assocmap : assoc ! r = Some v -> assoc # r = v. Proof. intros. unfold find_assocmap, AssocMapExt.get_default. rewrite H. trivial. Qed. + +Lemma fso : forall m v k1 k2, k1 <> k2 -> (m # k1 <- v) # k2 = m # k2. +Proof. + unfold "_ # _". + unfold AssocMapExt.get_default. + intros. + destruct_match; rewrite AssocMap.gso in Heqo by auto; rewrite Heqo; auto. +Qed. + +Lemma fss : forall m v k, (m # k <- v) # k = v. +Proof. + unfold "_ # _". + unfold AssocMapExt.get_default. + intros. + destruct_match; rewrite AssocMap.gss in Heqo by auto; inv Heqo; crush. +Qed. diff --git a/src/hls/HTL.v b/src/hls/HTL.v index 61ea541..886f86d 100644 --- a/src/hls/HTL.v +++ b/src/hls/HTL.v @@ -31,6 +31,7 @@ Require Import vericert.common.Vericertlib. Require Import vericert.hls.ValueInt. Require Import vericert.hls.AssocMap. Require Import vericert.hls.Array. +Require Import vericert.common.Maps. Require vericert.hls.Verilog. Local Open Scope positive. @@ -45,9 +46,12 @@ Local Open Scope assocmap. Definition reg := positive. Definition node := positive. +Definition ident := positive. -Definition datapath := PTree.t Verilog.stmnt. -Definition controllogic := PTree.t Verilog.stmnt. +Definition datapath_stmnt := Verilog.stmnt. +Definition datapath := PTree.t datapath_stmnt. +Definition control_stmnt := Verilog.stmnt. +Definition controllogic := PTree.t control_stmnt. Definition map_well_formed {A : Type} (m : PTree.t A) : Prop := forall p0 : positive, @@ -72,6 +76,21 @@ Record ram := mk_ram { Definition module_ordering a b c d e f g := a < b < c /\ c < d < e /\ e < f < g. +Inductive controlsignal : Type := + | ctrl_finish : controlsignal + | ctrl_return : controlsignal + | ctrl_start : controlsignal + | ctrl_reset : controlsignal + | ctrl_clk : controlsignal + | ctrl_param (idx : nat) : controlsignal. + +Definition controlsignal_sz (s : controlsignal) : nat := + match s with + | ctrl_param _ => 32 + | ctrl_return => 32 + | _ => 1 + end. + Record module: Type := mkmodule { mod_params : list reg; @@ -88,6 +107,10 @@ Record module: Type := mod_clk : reg; mod_scldecls : AssocMap.t (option Verilog.io * Verilog.scl_decl); mod_arrdecls : AssocMap.t (option Verilog.io * Verilog.arr_decl); + (** Map from registers in this module to control registers in other modules. + These will be mapped to the same verilog register. *) + mod_externctrl : AssocMap.t (ident * controlsignal); + mod_wf : (map_well_formed mod_controllogic /\ map_well_formed mod_datapath); mod_ram : option ram; mod_wf : map_well_formed mod_controllogic /\ map_well_formed mod_datapath; mod_ordering_wf : module_ordering mod_st mod_finish mod_return mod_stk mod_start mod_reset mod_clk; @@ -108,31 +131,59 @@ Fixpoint init_regs (vl : list value) (rl : list reg) {struct rl} := Definition empty_stack (m : module) : Verilog.assocmap_arr := (AssocMap.set m.(mod_stk) (Array.arr_repeat None m.(mod_stk_len)) (AssocMap.empty Verilog.arr)). + +Definition prog_modmap (p : HTL.program) := + PTree_Properties.of_list (Option.map_option + (fun a => match a with + | (ident, (AST.Gfun (AST.Internal f))) => Some (ident, f) + | _ => None + end) + (AST.prog_defs p)). + +Lemma max_pc_wf : + forall T m, Z.pos (max_pc_map m) <= Integers.Int.max_unsigned -> + @map_well_formed T m. +Proof. + unfold map_well_formed. intros. + exploit list_in_map_inv. eassumption. intros [x [A B]]. destruct x. + apply Maps.PTree.elements_complete in B. apply max_pc_map_sound in B. + unfold Ple in B. apply Pos2Z.pos_le_pos in B. subst. + simplify. transitivity (Z.pos (max_pc_map m)); eauto. +Qed. + (** * Operational Semantics *) Definition genv := Globalenvs.Genv.t fundef unit. +Definition find_func {F V} (ge : Globalenvs.Genv.t F V) (symb : AST.ident) : option F := + match Globalenvs.Genv.find_symbol ge symb with + | None => None + | Some b => Globalenvs.Genv.find_funct_ptr ge b + end. + Inductive stackframe : Type := - Stackframe : - forall (res : reg) - (m : module) - (pc : node) - (reg_assoc : Verilog.assocmap_reg) - (arr_assoc : Verilog.assocmap_arr), - stackframe. + Stackframe : forall (mid : ident) + (m : module) + (st : node) + (reg_assoc : Verilog.assocmap_reg) + (arr_assoc : Verilog.assocmap_arr), + stackframe. Inductive state : Type := | State : forall (stack : list stackframe) + (mid : ident) (m : module) (st : node) (reg_assoc : Verilog.assocmap_reg) (arr_assoc : Verilog.assocmap_arr), state | Returnstate : forall (res : list stackframe) + (mid : ident) (** Name of the callee *) (v : value), state | Callstate : forall (stack : list stackframe) + (mid : ident) (m : module) (args : list value), state. @@ -172,7 +223,7 @@ Inductive exec_ram: Inductive step : genv -> state -> Events.trace -> state -> Prop := | step_module : - forall g m st sf ctrl data + forall g mid m st sf ctrl_stmnt data_stmnt asr asa basr1 basa1 nasr1 nasa1 basr2 basa2 nasr2 nasa2 @@ -182,19 +233,19 @@ Inductive step : genv -> state -> Events.trace -> state -> Prop := asr!(mod_reset m) = Some (ZToValue 0) -> asr!(mod_finish m) = Some (ZToValue 0) -> asr!(m.(mod_st)) = Some (posToValue st) -> - m.(mod_controllogic)!st = Some ctrl -> - m.(mod_datapath)!st = Some data -> + m.(mod_controllogic)!st = Some ctrl_stmnt -> + m.(mod_datapath)!st = Some data_stmnt -> Verilog.stmnt_runp f (Verilog.mkassociations asr empty_assocmap) (Verilog.mkassociations asa (empty_stack m)) - ctrl + ctrl_stmnt (Verilog.mkassociations basr1 nasr1) (Verilog.mkassociations basa1 nasa1) -> basr1!(m.(mod_st)) = Some (posToValue st) -> Verilog.stmnt_runp f (Verilog.mkassociations basr1 nasr1) (Verilog.mkassociations basa1 nasa1) - data + data_stmnt (Verilog.mkassociations basr2 nasr2) (Verilog.mkassociations basa2 nasa2) -> exec_ram @@ -206,27 +257,61 @@ Inductive step : genv -> state -> Events.trace -> state -> Prop := asr' = Verilog.merge_regs nasr3 basr3 -> asa' = Verilog.merge_arrs nasa3 basa3 -> asr'!(m.(mod_st)) = Some (posToValue pstval) -> - (Z.pos pstval <= Integers.Int.max_unsigned)%Z -> - step g (State sf m st asr asa) Events.E0 (State sf m pstval asr' asa') + Z.pos pstval <= Integers.Int.max_unsigned -> + step g + (State sf mid m st asr asa) Events.E0 + (State sf mid m pstval asr' asa') | step_finish : - forall g m st asr asa retval sf, + forall g m st asr asa retval sf mid, asr!(m.(mod_finish)) = Some (ZToValue 1) -> asr!(m.(mod_return)) = Some retval -> - step g (State sf m st asr asa) Events.E0 (Returnstate sf retval) + + step g + (State sf mid m st asr asa) Events.E0 + (Returnstate sf mid retval) +| step_initcall : + forall g callerid caller st asr asa sf callee_id callee callee_reset callee_params callee_param_vals, + find_func g callee_id = Some (AST.Internal callee) -> + + caller.(mod_externctrl)!callee_reset = Some (callee_id, ctrl_reset) -> + (forall n param, nth_error callee_params n = Some param -> + caller.(mod_externctrl)!param = Some (callee_id, ctrl_param n)) -> + + (* The fact that this is the only condition on the current state to trigger + a call introduces non-determinism into the semantics. The semantics + permit initiating a call from any state where a reset has been set to 0. + *) + asr!callee_reset = Some (ZToValue 0) -> + callee_param_vals = List.map (fun p => asr#p) callee_params -> + + step g + (State sf callerid caller st asr asa) Events.E0 + (Callstate (Stackframe callerid caller st asr asa :: sf) + callee_id callee callee_param_vals) + | step_call : - forall g m args res, - step g (Callstate res m args) Events.E0 - (State res m m.(mod_entrypoint) + forall g mid m args res, + step g + (Callstate res mid m args) Events.E0 + (State res mid m m.(mod_entrypoint) (AssocMap.set (mod_reset m) (ZToValue 0) (AssocMap.set (mod_finish m) (ZToValue 0) (AssocMap.set (mod_st m) (posToValue m.(mod_entrypoint)) (init_regs args m.(mod_params))))) (empty_stack m)) + | step_return : - forall g m asr asa i r sf pc mst, - mst = mod_st m -> - step g (Returnstate (Stackframe r m pc asr asa :: sf) i) Events.E0 - (State sf m pc ((asr # mst <- (posToValue pc)) # r <- i) asa). + forall g callerid caller asr asa callee_id callee_return callee_finish i sf pc mst, + mst = mod_st caller -> + + caller.(mod_externctrl)!callee_return = Some (callee_id, ctrl_return) -> + caller.(mod_externctrl)!callee_finish = Some (callee_id, ctrl_finish) -> + + step g + (Returnstate (Stackframe callerid caller pc asr asa :: sf) callee_id i) Events.E0 + (State sf callerid caller pc + (asr # mst <- (posToValue pc) # callee_finish <- (ZToValue 1) # callee_return <- i) + asa). Hint Constructors step : htl. Inductive initial_state (p: program): state -> Prop := @@ -235,12 +320,12 @@ Inductive initial_state (p: program): state -> Prop := Globalenvs.Genv.init_mem p = Some m0 -> Globalenvs.Genv.find_symbol ge p.(AST.prog_main) = Some b -> Globalenvs.Genv.find_funct_ptr ge b = Some (AST.Internal m) -> - initial_state p (Callstate nil m nil). + initial_state p (Callstate nil p.(AST.prog_main) m nil). Inductive final_state : state -> Integers.int -> Prop := -| final_state_intro : forall retval retvali, +| final_state_intro : forall retval mid retvali, retvali = valueToInt retval -> - final_state (Returnstate nil retval) retvali. + final_state (Returnstate nil mid retval) retvali. Definition semantics (m : program) := Smallstep.Semantics step (initial_state m) final_state diff --git a/src/hls/HTLBlockgen.v b/src/hls/HTLBlockgen.v index 5f40962..b9fc1d9 100644 --- a/src/hls/HTLBlockgen.v +++ b/src/hls/HTLBlockgen.v @@ -43,8 +43,8 @@ Definition init_state (st : reg) : state := 1%positive (AssocMap.empty (option io * scl_decl)) (AssocMap.empty (option io * arr_decl)) - (AssocMap.empty stmnt) - (AssocMap.empty stmnt). + (AssocMap.empty datapath_stmnt) + (AssocMap.empty control_stmnt). Module HTLState <: State. @@ -87,11 +87,17 @@ Module HTLMonadExtra := Monad.MonadExtra(HTLMonad). Import HTLMonadExtra. Export MonadNotation. -Definition state_goto (st : reg) (n : node) : stmnt := - Vnonblock (Vvar st) (Vlit (posToValue n)). +Definition data_vstmnt : Verilog.stmnt -> HTL.datapath_stmnt := HTLDataVstmnt. +Definition ctrl_vstmnt : Verilog.stmnt -> HTL.control_stmnt := HTLCtrlVstmnt. -Definition state_cond (st : reg) (c : expr) (n1 n2 : node) : stmnt := - Vnonblock (Vvar st) (Vternary c (posToExpr n1) (posToExpr n2)). +Definition state_goto (st : reg) (n : node) : control_stmnt := + ctrl_vstmnt (Vnonblock (Vvar st) (Vlit (posToValue n))). + +Definition state_cond (st : reg) (c : expr) (n1 n2 : node) : control_stmnt := + ctrl_vstmnt (Vnonblock (Vvar st) (Vternary c (posToExpr n1) (posToExpr n2))). + +Definition nonblock (dst : reg) (e : expr) := (Vnonblock (Vvar dst) e). +Definition block (dst : reg) (e : expr) := (Vblock (Vvar dst) e). Definition check_empty_node_datapath: forall (s: state) (n: node), { s.(st_datapath)!n = None } + { True }. @@ -105,25 +111,6 @@ Proof. intros. case (s.(st_controllogic)!n); tauto. Defined. -Lemma add_instr_state_incr : - forall s n n' st, - (st_datapath s)!n = None -> - (st_controllogic s)!n = None -> - st_incr s - (mkstate - s.(st_st) - s.(st_freshreg) - (st_freshstate s) - s.(st_scldecls) - s.(st_arrdecls) - (AssocMap.set n st s.(st_datapath)) - (AssocMap.set n (state_goto s.(st_st) n') s.(st_controllogic))). -Proof. - constructor; intros; - try (simpl; destruct (peq n n0); subst); - auto with htlh. -Qed. - Lemma declare_reg_state_incr : forall i s r sz, st_incr s @@ -148,7 +135,50 @@ Definition declare_reg (i : option io) (r : reg) (sz : nat) : mon unit := s.(st_controllogic)) (declare_reg_state_incr i s r sz). -Definition add_instr (n : node) (n' : node) (st : stmnt) : mon unit := +Lemma create_state_state_incr: + forall s, + st_incr s (mkstate + s.(st_st) + (st_freshreg s) + (Pos.succ (st_freshstate s)) + (st_scldecls s) + (st_arrdecls s) + (st_datapath s) + (st_controllogic s)). +Proof. constructor; simpl; auto with htlh. Qed. + +Definition create_state : mon node := + fun s => let r := s.(st_freshstate) in + OK r (mkstate + s.(st_st) + (st_freshreg s) + (Pos.succ (st_freshstate s)) + (st_scldecls s) + (st_arrdecls s) + (st_datapath s) + (st_controllogic s)) + (create_state_state_incr s). + +Lemma add_instr_state_incr : + forall s n n' st, + (st_datapath s)!n = None -> + (st_controllogic s)!n = None -> + st_incr s + (mkstate + s.(st_st) + s.(st_freshreg) + (st_freshstate s) + s.(st_scldecls) + s.(st_arrdecls) + (AssocMap.set n st s.(st_datapath)) + (AssocMap.set n (state_goto s.(st_st) n') s.(st_controllogic))). +Proof. + constructor; intros; + try (simpl; destruct (peq n n0); subst); + auto with htlh. +Qed. + +Definition add_instr (n : node) (n' : node) (st : datapath_stmnt) : mon unit := fun s => match check_empty_node_datapath s n, check_empty_node_controllogic s n with | left STM, left TRANS => @@ -176,14 +206,33 @@ Lemma add_instr_skip_state_incr : s.(st_scldecls) s.(st_arrdecls) (AssocMap.set n st s.(st_datapath)) - (AssocMap.set n Vskip s.(st_controllogic))). + (AssocMap.set n (ctrl_vstmnt Vskip) s.(st_controllogic))). +Proof. + constructor; intros; + try (simpl; destruct (peq n n0); subst); + auto with htlh. +Qed. + +Lemma add_instr_wait_state_incr : + forall wait_mod s n n' st, + (st_datapath s)!n = None -> + (st_controllogic s)!n = None -> + st_incr s + (mkstate + s.(st_st) + s.(st_freshreg) + (st_freshstate s) + s.(st_scldecls) + s.(st_arrdecls) + (AssocMap.set n st s.(st_datapath)) + (AssocMap.set n (HTLwait wait_mod s.(st_st) (Vlit (posToValue n'))) s.(st_controllogic))). Proof. constructor; intros; try (simpl; destruct (peq n n0); subst); auto with htlh. Qed. -Definition add_instr_skip (n : node) (st : stmnt) : mon unit := +Definition add_instr_wait (wait_mod : ident) (n : node) (n' : node) (st : datapath_stmnt) : mon unit := fun s => match check_empty_node_datapath s n, check_empty_node_controllogic s n with | left STM, left TRANS => @@ -194,7 +243,23 @@ Definition add_instr_skip (n : node) (st : stmnt) : mon unit := s.(st_scldecls) s.(st_arrdecls) (AssocMap.set n st s.(st_datapath)) - (AssocMap.set n Vskip s.(st_controllogic))) + (AssocMap.set n (HTLwait wait_mod s.(st_st) (Vlit (posToValue n'))) s.(st_controllogic))) + (add_instr_wait_state_incr wait_mod s n n' st STM TRANS) + | _, _ => Error (Errors.msg "HTL.add_instr_wait") + end. + +Definition add_instr_skip (n : node) (st : datapath_stmnt) : mon unit := + fun s => + match check_empty_node_datapath s n, check_empty_node_controllogic s n with + | left STM, left TRANS => + OK tt (mkstate + s.(st_st) + s.(st_freshreg) + (st_freshstate s) + s.(st_scldecls) + s.(st_arrdecls) + (AssocMap.set n st s.(st_datapath)) + (AssocMap.set n (ctrl_vstmnt Vskip) s.(st_controllogic))) (add_instr_skip_state_incr s n st STM TRANS) | _, _ => Error (Errors.msg "HTL.add_instr") end. @@ -210,7 +275,7 @@ Lemma add_node_skip_state_incr : (st_freshstate s) s.(st_scldecls) s.(st_arrdecls) - (AssocMap.set n Vskip s.(st_datapath)) + (AssocMap.set n (data_vstmnt Vskip) s.(st_datapath)) (AssocMap.set n st s.(st_controllogic))). Proof. constructor; intros; @@ -218,7 +283,7 @@ Proof. auto with htlh. Qed. -Definition add_node_skip (n : node) (st : stmnt) : mon unit := +Definition add_node_skip (n : node) (st : control_stmnt) : mon unit := fun s => match check_empty_node_datapath s n, check_empty_node_controllogic s n with | left STM, left TRANS => @@ -228,15 +293,12 @@ Definition add_node_skip (n : node) (st : stmnt) : mon unit := (st_freshstate s) s.(st_scldecls) s.(st_arrdecls) - (AssocMap.set n Vskip s.(st_datapath)) + (AssocMap.set n (data_vstmnt Vskip) s.(st_datapath)) (AssocMap.set n st s.(st_controllogic))) (add_node_skip_state_incr s n st STM TRANS) | _, _ => Error (Errors.msg "HTL.add_instr") end. -Definition nonblock (dst : reg) (e : expr) := Vnonblock (Vvar dst) e. -Definition block (dst : reg) (e : expr) := Vblock (Vvar dst) e. - Definition bop (op : binop) (r1 r2 : reg) : expr := Vbinop op (Vvar r1) (Vvar r2). @@ -386,7 +448,7 @@ Lemma add_branch_instr_state_incr: (st_freshstate s) s.(st_scldecls) s.(st_arrdecls) - (AssocMap.set n Vskip (st_datapath s)) + (AssocMap.set n (data_vstmnt Vskip) (st_datapath s)) (AssocMap.set n (state_cond s.(st_st) e n1 n2) (st_controllogic s))). Proof. intros. apply state_incr_intro; simpl; @@ -404,7 +466,7 @@ Definition add_branch_instr (e: expr) (n n1 n2: node) : mon unit := (st_freshstate s) s.(st_scldecls) s.(st_arrdecls) - (AssocMap.set n Vskip (st_datapath s)) + (AssocMap.set n (data_vstmnt Vskip) (st_datapath s)) (AssocMap.set n (state_cond s.(st_st) e n1 n2) (st_controllogic s))) (add_branch_instr_state_incr s e n n1 n2 NSTM NTRANS) | _, _ => Error (Errors.msg "Htlgen: add_branch_instr") @@ -450,26 +512,33 @@ Definition transf_instr (fin rtrn stack: reg) (ni: node * instruction) : mon uni match i with | Inop n' => if Z.leb (Z.pos n') Integers.Int.max_unsigned then - add_instr n n' Vskip + add_instr n n' (data_vstmnt Vskip) else error (Errors.msg "State is larger than 2^32.") | Iop op args dst n' => if Z.leb (Z.pos n') Integers.Int.max_unsigned then do instr <- translate_instr op args; do _ <- declare_reg None dst 32; - add_instr n n' (nonblock dst instr) + add_instr n n' (data_vstmnt (nonblock dst instr)) else error (Errors.msg "State is larger than 2^32.") | Iload mem addr args dst n' => if Z.leb (Z.pos n') Integers.Int.max_unsigned then do src <- translate_arr_access mem addr args stack; do _ <- declare_reg None dst 32; - add_instr n n' (nonblock dst src) + add_instr n n' (data_vstmnt (nonblock dst src)) else error (Errors.msg "State is larger than 2^32.") | Istore mem addr args src n' => if Z.leb (Z.pos n') Integers.Int.max_unsigned then do dst <- translate_arr_access mem addr args stack; - add_instr n n' (Vnonblock dst (Vvar src)) (* TODO: Could juse use add_instr? reg exists. *) + add_instr n n' (data_vstmnt (Vnonblock dst (Vvar src))) (* TODO: Could juse use add_instr? reg exists. *) + else error (Errors.msg "State is larger than 2^32.") + | Icall sig (inl fn) args dst n' => error (Errors.msg "Indirect calls are not implemented.") + | Icall sig (inr fn) args dst n' => + if Z.leb (Z.pos n') Integers.Int.max_unsigned then + do _ <- declare_reg None dst 32; + do join_state <- create_state; + do _ <- add_instr n join_state (HTLfork fn args); + add_instr_wait fn join_state n' (HTLjoin fn dst) else error (Errors.msg "State is larger than 2^32.") - | Icall _ _ _ _ _ => error (Errors.msg "Calls are not implemented.") | Itailcall _ _ _ => error (Errors.msg "Tailcalls are not implemented.") | Ibuiltin _ _ _ _ => error (Errors.msg "Builtin functions not implemented.") | Icond cond args n1 n2 => @@ -484,9 +553,9 @@ Definition transf_instr (fin rtrn stack: reg) (ni: node * instruction) : mon uni | Ireturn r => match r with | Some r' => - add_instr_skip n (Vseq (block fin (Vlit (ZToValue 1%Z))) (block rtrn (Vvar r'))) + add_instr_skip n (data_vstmnt (Vseq (block fin (Vlit (ZToValue 1%Z))) (block rtrn (Vvar r')))) | None => - add_instr_skip n (Vseq (block fin (Vlit (ZToValue 1%Z))) (block rtrn (Vlit (ZToValue 0%Z)))) + add_instr_skip n (data_vstmnt (Vseq (block fin (Vlit (ZToValue 1%Z))) (block rtrn (Vlit (ZToValue 0%Z))))) end end end. @@ -542,11 +611,11 @@ Definition create_arr (i : option io) (sz : nat) (ln : nat) : mon (reg * nat) := Definition stack_correct (sz : Z) : bool := (0 <=? sz) && (sz <? Integers.Ptrofs.modulus) && (Z.modulo sz 4 =? 0). -Definition max_pc_map (m : Maps.PTree.t stmnt) := +Definition max_pc_map {A: Type} (m : Maps.PTree.t A) := PTree.fold (fun m pc i => Pos.max m pc) m 1%positive. Lemma max_pc_map_sound: - forall m pc i, m!pc = Some i -> Ple pc (max_pc_map m). + forall A m pc i, m!pc = Some i -> Ple pc (@max_pc_map A m). Proof. intros until i. unfold max_pc_function. apply PTree_Properties.fold_rec with (P := fun c m => c!pc = Some i -> Ple pc m). @@ -561,8 +630,8 @@ Proof. Qed. Lemma max_pc_wf : - forall m, Z.pos (max_pc_map m) <= Integers.Int.max_unsigned -> - map_well_formed m. + forall T m, Z.pos (max_pc_map m) <= Integers.Int.max_unsigned -> + @map_well_formed T m. Proof. unfold map_well_formed. intros. exploit list_in_map_inv. eassumption. intros [x [A B]]. destruct x. @@ -600,7 +669,7 @@ Definition transf_module (f: function) : mon module := clk current_state.(st_scldecls) current_state.(st_arrdecls) - (conj (max_pc_wf _ LECTRL) (max_pc_wf _ LEDATA))) + (conj (max_pc_wf _ _ LECTRL) (max_pc_wf _ _ LEDATA))) | _, _ => error (Errors.msg "More than 2^32 states.") end else error (Errors.msg "Stack size misalignment."). diff --git a/src/hls/HTLPargen.v b/src/hls/HTLPargen.v index 9e1f156..d292722 100644 --- a/src/hls/HTLPargen.v +++ b/src/hls/HTLPargen.v @@ -57,8 +57,8 @@ Definition init_state (st : reg) : state := 1%positive (AssocMap.empty (option io * scl_decl)) (AssocMap.empty (option io * arr_decl)) - (AssocMap.empty stmnt) - (AssocMap.empty stmnt). + (AssocMap.empty datapath_stmnt) + (AssocMap.empty control_stmnt). Module HTLState <: State. @@ -516,13 +516,13 @@ Definition create_arr (i : option io) (sz : nat) (ln : nat) : mon (reg * nat) := (st_controllogic s)) (create_arr_state_incr s sz ln i). -Definition max_pc_map (m : Maps.PTree.t stmnt) := +Definition max_pc_map {A: Type} (m : Maps.PTree.t A) := PTree.fold (fun m pc i => Pos.max m pc) m 1%positive. Lemma max_pc_map_sound: - forall m pc i, m!pc = Some i -> Ple pc (max_pc_map m). + forall A m pc i, m!pc = Some i -> Ple pc (@max_pc_map A m). Proof. - intros until i. + intros until i. unfold max_pc_function. apply PTree_Properties.fold_rec with (P := fun c m => c!pc = Some i -> Ple pc m). (* extensionality *) intros. apply H0. rewrite H; auto. @@ -530,14 +530,13 @@ Proof. rewrite PTree.gempty. congruence. (* inductive case *) intros. rewrite PTree.gsspec in H2. destruct (peq pc k). - inv H2. unfold Ple, Plt in *. lia. - apply Ple_trans with a. auto. - unfold Ple, Plt in *. lia. + inv H2. xomega. + apply Ple_trans with a. auto. xomega. Qed. Lemma max_pc_wf : - forall m, Z.pos (max_pc_map m) <= Integers.Int.max_unsigned -> - map_well_formed m. + forall T m, Z.pos (max_pc_map m) <= Integers.Int.max_unsigned -> + @map_well_formed T m. Proof. unfold map_well_formed. intros. exploit list_in_map_inv. eassumption. intros [x [A B]]. destruct x. @@ -591,7 +590,8 @@ Definition add_data_instr (n : node) (st : stmnt) : mon unit := (st_freshstate s) s.(st_scldecls) s.(st_arrdecls) - (AssocMap.set n (Vseq (AssocMapExt.get_default _ Vskip n s.(st_datapath)) st) s.(st_datapath)) + (AssocMap.set n (Vseq (AssocMapExt.get_default + _ Vskip n s.(st_datapath)) st) s.(st_datapath)) s.(st_controllogic)) (add_data_instr_state_incr s n st). @@ -655,7 +655,6 @@ Abort. (AssocMap.set n st s.(st_controllogic))) (add_control_instr_force_state_incr s n st). - Fixpoint pred_expr (preg: reg) (p: pred_op) := match p with | Pvar pred => diff --git a/src/hls/HTLgen.v b/src/hls/HTLgen.v index 4d60a24..0b7f3ec 100644 --- a/src/hls/HTLgen.v +++ b/src/hls/HTLgen.v @@ -21,6 +21,7 @@ Require Import Coq.micromega.Lia. Require Import compcert.lib.Maps. Require compcert.common.Errors. +Require Import compcert.lib.Integers. Require compcert.common.Globalenvs. Require compcert.lib.Integers. Require Import compcert.common.AST. @@ -28,6 +29,7 @@ Require Import compcert.backend.RTL. Require Import vericert.common.Statemonad. Require Import vericert.common.Vericertlib. +Require Import vericert.common.Maps. Require Import vericert.hls.AssocMap. Require Import vericert.hls.HTL. Require Import vericert.hls.ValueInt. @@ -45,6 +47,7 @@ Record state: Type := mkstate { st_freshstate: node; st_scldecls: AssocMap.t (option io * scl_decl); st_arrdecls: AssocMap.t (option io * arr_decl); + st_externctrl : AssocMap.t (ident * controlsignal); st_datapath: datapath; st_controllogic: controllogic; }. @@ -55,38 +58,64 @@ Definition init_state (st : reg) : state := 1%positive (AssocMap.empty (option io * scl_decl)) (AssocMap.empty (option io * arr_decl)) - (AssocMap.empty stmnt) - (AssocMap.empty stmnt). + (AssocMap.empty (ident * controlsignal)) + (AssocMap.empty datapath_stmnt) + (AssocMap.empty control_stmnt). + +(** Describes a map that is created incrementally in the monad, i.e. only new + values can be added, not changed or deleted. *) +Definition map_incr {S B} (map : S -> PTree.t B) (s1 s2 : S) := + forall n, s1.(map)!n = None \/ + s2.(map)!n = s1.(map)!n. +Hint Unfold map_incr : htlh. Module HTLState <: State. Definition st := state. Inductive st_incr: state -> state -> Prop := - state_incr_intro: + | state_incr_intro: forall (s1 s2: state), - st_st s1 = st_st s2 -> - Ple s1.(st_freshreg) s2.(st_freshreg) -> - Ple s1.(st_freshstate) s2.(st_freshstate) -> - (forall n, - s1.(st_datapath)!n = None \/ s2.(st_datapath)!n = s1.(st_datapath)!n) -> - (forall n, - s1.(st_controllogic)!n = None - \/ s2.(st_controllogic)!n = s1.(st_controllogic)!n) -> - st_incr s1 s2. + st_st s1 = st_st s2 -> + Ple s1.(st_freshreg) s2.(st_freshreg) -> + Ple s1.(st_freshstate) s2.(st_freshstate) -> + map_incr st_datapath s1 s2 -> + map_incr st_controllogic s1 s2 -> + map_incr st_externctrl s1 s2 -> + (forall n, (st_externctrl s1) ! n = None -> + (exists x, (st_externctrl s2) ! n = Some x) -> + (n >= st_freshreg s1)%positive) -> + st_incr s1 s2. Hint Constructors st_incr : htlh. Definition st_prop := st_incr. Hint Unfold st_prop : htlh. - Lemma st_refl : forall s, st_prop s s. Proof. auto with htlh. Qed. + Lemma st_refl : forall s, st_prop s s. + Proof. split; try solve [ auto with htlh; crush ]. Qed. Lemma st_trans : forall s1 s2 s3, st_prop s1 s2 -> st_prop s2 s3 -> st_prop s1 s3. Proof. - intros. inv H. inv H0. apply state_incr_intro; eauto using Ple_trans; intros; try congruence. - - destruct H4 with n; destruct H8 with n; intuition congruence. - - destruct H5 with n; destruct H9 with n; intuition congruence. + intros * H0 H1. inv H0. inv H1. + split; autounfold with htlh in *; intros; try solve [crush]. + - destruct H4 with n; destruct H10 with n; intuition crush. + - destruct H5 with n; destruct H11 with n; intuition crush. + - destruct H6 with n; destruct H12 with n; intuition crush. + - destruct H6 with n; destruct H12 with n. + + specialize (H13 n ltac:(auto) ltac:(auto)). + crush. + + apply H7; auto. + rewrite <- H16. + auto. + + specialize (H13 n ltac:(auto) ltac:(auto)). + unfold Ple in *. + lia. + + contradict H14. + rewrite H16. + rewrite H15. + rewrite H1. + intuition crush. Qed. End HTLState. @@ -99,12 +128,28 @@ Module HTLMonadExtra := Monad.MonadExtra(HTLMonad). Import HTLMonadExtra. Export MonadNotation. -Definition state_goto (st : reg) (n : node) : stmnt := +Definition bop (op : binop) (r1 r2 : reg) : expr := + Vbinop op (Vvar r1) (Vvar r2). + +Definition boplit (op : binop) (r : reg) (l : Integers.int) : expr := + Vbinop op (Vvar r) (Vlit (intToValue l)). + +Definition boplitz (op: binop) (r: reg) (l: Z) : expr := + Vbinop op (Vvar r) (Vlit (ZToValue l)). + +Definition state_goto (st : reg) (n : node) : control_stmnt := Vnonblock (Vvar st) (Vlit (posToValue n)). -Definition state_cond (st : reg) (c : expr) (n1 n2 : node) : stmnt := +Definition state_cond (st : reg) (c : expr) (n1 n2 : node) : control_stmnt := Vnonblock (Vvar st) (Vternary c (posToExpr n1) (posToExpr n2)). +Definition state_wait (st wait_reg : reg) (n : node) : control_stmnt := + Vcond (boplitz Veq wait_reg 1) (Vnonblock (Vvar st) (posToExpr n)) Vskip. + +Definition nonblock (dst : reg) (e : expr) := (Vnonblock (Vvar dst) e). + +Definition block (dst : reg) (e : expr) := (Vblock (Vvar dst) e). + Definition check_empty_node_datapath: forall (s: state) (n: node), { s.(st_datapath)!n = None } + { True }. Proof. @@ -117,146 +162,140 @@ Proof. intros. case (s.(st_controllogic)!n); tauto. Defined. -Lemma add_instr_state_incr : - forall s n n' st, - (st_datapath s)!n = None -> - (st_controllogic s)!n = None -> - st_incr s - (mkstate - s.(st_st) - s.(st_freshreg) - (st_freshstate s) - s.(st_scldecls) - s.(st_arrdecls) - (AssocMap.set n st s.(st_datapath)) - (AssocMap.set n (state_goto s.(st_st) n') s.(st_controllogic))). +Definition check_unmapped_externctrl: + forall (s: state) (n: reg), { s.(st_externctrl)!n = None } + { True }. Proof. - constructor; intros; - try (simpl; destruct (peq n n0); subst); - auto with htlh. -Qed. + intros. case (s.(st_externctrl)!n); tauto. +Defined. -Lemma declare_reg_state_incr : - forall i s r sz, - st_incr s - (mkstate - s.(st_st) - s.(st_freshreg) - s.(st_freshstate) - (AssocMap.set r (i, VScalar sz) s.(st_scldecls)) - s.(st_arrdecls) - s.(st_datapath) - s.(st_controllogic)). -Proof. auto with htlh. Qed. +(** Used for discharging the st_incr proof in simple operations *) +Local Ltac st_tac := + constructor; autounfold with htlh in *; intros; simpl; auto with htlh; + match goal with + | [ H : (?map ?s) ! ?n = None, n' : positive |- _] => destruct (peq n n') + end; + subst; auto with htlh; intuition crush. Definition declare_reg (i : option io) (r : reg) (sz : nat) : mon unit := fun s => OK tt (mkstate - s.(st_st) - s.(st_freshreg) - s.(st_freshstate) - (AssocMap.set r (i, VScalar sz) s.(st_scldecls)) - s.(st_arrdecls) - s.(st_datapath) - s.(st_controllogic)) - (declare_reg_state_incr i s r sz). - -Definition add_instr (n : node) (n' : node) (st : stmnt) : mon unit := - fun s => - match check_empty_node_datapath s n, check_empty_node_controllogic s n with - | left STM, left TRANS => - OK tt (mkstate + (st_st s) + (st_freshreg s) + (st_freshstate s) + (AssocMap.set r (i, VScalar sz) s.(st_scldecls)) + (st_arrdecls s) + (st_externctrl s) + (st_datapath s) + (st_controllogic s)) ltac:(st_tac). + +Definition create_reg (i : option io) (sz : nat) : mon reg := + fun s => let r := s.(st_freshreg) in + OK r (mkstate + (st_st s) + (Pos.succ r) + (st_freshstate s) + (AssocMap.set s.(st_freshreg) (i, VScalar sz) s.(st_scldecls)) + (st_arrdecls s) + (st_externctrl s) + (st_datapath s) + (st_controllogic s)) ltac:(st_tac). + +Definition map_externctrl (othermod : ident) (ctrl : controlsignal) : mon reg. + refine ( + fun s => match check_unmapped_externctrl s (st_freshreg s) with + | left CTRL => OK (st_freshreg s) (mkstate + (st_st s) + (st_freshreg s) + (st_freshstate s) + (st_scldecls s) + (st_arrdecls s) + (AssocMap.set (st_freshreg s) (othermod, ctrl) (st_externctrl s)) + (st_datapath s) + (st_controllogic s)) _ + | right CTRL => Error (Errors.msg "HTL.map_externctrl") + end). + st_tac. + rewrite PTree.gsspec in *. + destruct_match; crush. +Defined. + +Definition create_state : mon node. + refine (fun s => let r := s.(st_freshstate) in + if Z.leb (Z.pos s.(st_freshstate)) Integers.Int.max_unsigned + then OK r (mkstate + (st_st s) + (st_freshreg s) + (Pos.succ (st_freshstate s)) + (st_scldecls s) + (st_arrdecls s) + (st_externctrl s) + (st_datapath s) + (st_controllogic s)) _ + else Error (Errors.msg "HTL.create_state")). + split; autounfold with htlh; crush. +Defined. + +Lemma create_state_max : forall s s' i x, create_state s = OK x s' i -> Z.pos x <= Int.max_unsigned. +Admitted. + +Definition add_instr (n : node) (n' : node) (st : datapath_stmnt) : mon unit := + fun s => match check_empty_node_datapath s n, check_empty_node_controllogic s n with + | left STM, left TRANS => + OK tt (mkstate s.(st_st) s.(st_freshreg) (st_freshstate s) s.(st_scldecls) s.(st_arrdecls) + (st_externctrl s) (AssocMap.set n st s.(st_datapath)) - (AssocMap.set n (state_goto s.(st_st) n') s.(st_controllogic))) - (add_instr_state_incr s n n' st STM TRANS) - | _, _ => Error (Errors.msg "HTL.add_instr") - end. - -Lemma add_instr_skip_state_incr : - forall s n st, - (st_datapath s)!n = None -> - (st_controllogic s)!n = None -> - st_incr s - (mkstate - s.(st_st) - s.(st_freshreg) - (st_freshstate s) - s.(st_scldecls) - s.(st_arrdecls) - (AssocMap.set n st s.(st_datapath)) - (AssocMap.set n Vskip s.(st_controllogic))). -Proof. - constructor; intros; - try (simpl; destruct (peq n n0); subst); - auto with htlh. -Qed. - -Definition add_instr_skip (n : node) (st : stmnt) : mon unit := - fun s => - match check_empty_node_datapath s n, check_empty_node_controllogic s n with - | left STM, left TRANS => - OK tt (mkstate + (AssocMap.set n (state_goto s.(st_st) n') s.(st_controllogic))) ltac:(st_tac) + | _, _ => Error (Errors.msg "HTL.add_instr") + end. + +Definition add_instr_wait (wait_reg : reg) (n : node) (n' : node) (st : datapath_stmnt) : mon unit := + fun s => match check_empty_node_datapath s n, check_empty_node_controllogic s n with + | left STM, left TRANS => + OK tt (mkstate s.(st_st) s.(st_freshreg) (st_freshstate s) s.(st_scldecls) s.(st_arrdecls) + (st_externctrl s) (AssocMap.set n st s.(st_datapath)) - (AssocMap.set n Vskip s.(st_controllogic))) - (add_instr_skip_state_incr s n st STM TRANS) - | _, _ => Error (Errors.msg "HTL.add_instr") - end. - -Lemma add_node_skip_state_incr : - forall s n st, - (st_datapath s)!n = None -> - (st_controllogic s)!n = None -> - st_incr s - (mkstate - s.(st_st) - s.(st_freshreg) - (st_freshstate s) - s.(st_scldecls) - s.(st_arrdecls) - (AssocMap.set n Vskip s.(st_datapath)) - (AssocMap.set n st s.(st_controllogic))). -Proof. - constructor; intros; - try (simpl; destruct (peq n n0); subst); - auto with htlh. -Qed. - -Definition add_node_skip (n : node) (st : stmnt) : mon unit := - fun s => - match check_empty_node_datapath s n, check_empty_node_controllogic s n with - | left STM, left TRANS => - OK tt (mkstate + (AssocMap.set n (state_wait (st_st s) wait_reg n') s.(st_controllogic))) ltac:(st_tac) + | _, _ => Error (Errors.msg "HTL.add_instr_wait") + end. + +Definition add_instr_skip (n : node) (st : datapath_stmnt) : mon unit := + fun s => match check_empty_node_datapath s n, check_empty_node_controllogic s n with + | left STM, left TRANS => + OK tt (mkstate s.(st_st) s.(st_freshreg) (st_freshstate s) s.(st_scldecls) s.(st_arrdecls) + (st_externctrl s) + (AssocMap.set n st s.(st_datapath)) + (AssocMap.set n Vskip s.(st_controllogic))) ltac:(st_tac) + | _, _ => Error (Errors.msg "HTL.add_instr") + end. + +Definition add_node_skip (n : node) (st : control_stmnt) : mon unit := + fun s => match check_empty_node_datapath s n, check_empty_node_controllogic s n with + | left STM, left TRANS => + OK tt (mkstate + s.(st_st) + s.(st_freshreg) + (st_freshstate s) + s.(st_scldecls) + s.(st_arrdecls) + (st_externctrl s) (AssocMap.set n Vskip s.(st_datapath)) - (AssocMap.set n st s.(st_controllogic))) - (add_node_skip_state_incr s n st STM TRANS) - | _, _ => Error (Errors.msg "HTL.add_instr") - end. - -Definition nonblock (dst : reg) (e : expr) := Vnonblock (Vvar dst) e. -Definition block (dst : reg) (e : expr) := Vblock (Vvar dst) e. - -Definition bop (op : binop) (r1 r2 : reg) : expr := - Vbinop op (Vvar r1) (Vvar r2). - -Definition boplit (op : binop) (r : reg) (l : Integers.int) : expr := - Vbinop op (Vvar r) (Vlit (intToValue l)). - -Definition boplitz (op: binop) (r: reg) (l: Z) : expr := - Vbinop op (Vvar r) (Vlit (ZToValue l)). + (AssocMap.set n st s.(st_controllogic))) ltac:(st_tac) + | _, _ => Error (Errors.msg "HTL.add_instr") + end. Definition translate_comparison (c : Integers.comparison) (args : list reg) : mon expr := match c, args with @@ -370,10 +409,12 @@ Definition translate_instr (op : Op.operation) (args : list reg) : mon expr := | Op.Oshlimm n, r::nil => ret (boplit Vshl r n) | Op.Oshr, r1::r2::nil => ret (bop Vshr r1 r2) | Op.Oshrimm n, r::nil => ret (boplit Vshr r n) - | Op.Oshrximm n, r::nil => - ret (Vternary (Vbinop Vlt (Vvar r) (Vlit (ZToValue 0))) - (Vunop Vneg (Vbinop Vshru (Vunop Vneg (Vvar r)) (Vlit n))) - (Vbinop Vshru (Vvar r) (Vlit n))) + | Op.Oshrximm n, r::nil => ret (Vternary (Vbinop Vlt (Vvar r) (Vlit (ZToValue 0))) + (Vunop Vneg (Vbinop Vshru (Vunop Vneg (Vvar r)) (Vlit n))) + (Vbinop Vshru (Vvar r) (Vlit n))) + (*ret (Vbinop Vdiv (Vvar r) + (Vbinop Vshl (Vlit (ZToValue 1)) + (Vlit (intToValue n))))*) | Op.Oshru, r1::r2::nil => ret (bop Vshru r1 r2) | Op.Oshruimm n, r::nil => ret (boplit Vshru r n) | Op.Ororimm n, r::nil => error (Errors.msg "Htlgen: Instruction not implemented: Ororimm") @@ -388,39 +429,20 @@ Definition translate_instr (op : Op.operation) (args : list reg) : mon expr := | _, _ => error (Errors.msg "Htlgen: Instruction not implemented: other") end. -Lemma add_branch_instr_state_incr: - forall s e n n1 n2, - (st_datapath s) ! n = None -> - (st_controllogic s) ! n = None -> - st_incr s (mkstate - s.(st_st) - (st_freshreg s) - (st_freshstate s) - s.(st_scldecls) - s.(st_arrdecls) - (AssocMap.set n Vskip (st_datapath s)) - (AssocMap.set n (state_cond s.(st_st) e n1 n2) (st_controllogic s))). -Proof. - intros. apply state_incr_intro; simpl; - try (intros; destruct (peq n0 n); subst); - auto with htlh. -Qed. - Definition add_branch_instr (e: expr) (n n1 n2: node) : mon unit := - fun s => - match check_empty_node_datapath s n, check_empty_node_controllogic s n with - | left NSTM, left NTRANS => - OK tt (mkstate + fun s => match check_empty_node_datapath s n, check_empty_node_controllogic s n with + | left NSTM, left NTRANS => + OK tt (mkstate s.(st_st) - (st_freshreg s) - (st_freshstate s) - s.(st_scldecls) - s.(st_arrdecls) - (AssocMap.set n Vskip (st_datapath s)) - (AssocMap.set n (state_cond s.(st_st) e n1 n2) (st_controllogic s))) - (add_branch_instr_state_incr s e n n1 n2 NSTM NTRANS) - | _, _ => Error (Errors.msg "Htlgen: add_branch_instr") - end. + (st_freshreg s) + (st_freshstate s) + s.(st_scldecls) + s.(st_arrdecls) + (st_externctrl s) + (AssocMap.set n Vskip (st_datapath s)) + (AssocMap.set n (state_cond s.(st_st) e n1 n2) (st_controllogic s))) ltac:(st_tac) + | _, _ => Error (Errors.msg "Htlgen: add_branch_instr") + end. Definition translate_arr_access (mem : AST.memory_chunk) (addr : Op.addressing) (args : list reg) (stack : reg) : mon expr := @@ -456,7 +478,47 @@ Definition tbl_to_case_expr (st : reg) (ns : list node) : list (expr * stmnt) := end) (enumerate 0 ns). -Definition transf_instr (fin rtrn stack: reg) (ni: node * instruction) : mon unit := +Fixpoint nonblock_all pairs := + match pairs with + | (dst, src) :: pairs' => Vseq (nonblock dst (Vvar src)) (nonblock_all pairs') + | nil => Vskip + end. + +(** [fork] a datapath statement which sets up the execution of a function *) +Definition fork (rst : reg) (params : list (reg * reg)) : datapath_stmnt := + let reset_mod := Vnonblock (Vvar rst) (posToLit 1) in + let assign_params := nonblock_all params in + Vseq reset_mod assign_params. + +Definition join (fn_rtrn fn_rst fn_dst : reg) : datapath_stmnt := + let set_result := Vnonblock (Vvar fn_dst) (Vvar fn_rtrn) in + let stop_reset := Vnonblock (Vvar fn_rst) (Vlit (ZToValue 0)) in + Vseq stop_reset set_result. + +Definition return_val r := + match r with + | Some r' => Vvar r' + | None => Vlit (ZToValue 0%Z) + end. + +Definition do_return fin rtrn r := + Vseq (block fin (Vlit (ZToValue 1%Z))) + (block rtrn (return_val r)). + +Definition idle fin := nonblock fin (Vlit (ZToValue 0%Z)). + +Fixpoint xmap_externctrl_params (n : nat) (fn : ident) (l : list reg) := + match l with + | nil => ret nil + | arg::args => + do param_reg <- map_externctrl fn (ctrl_param n); + do rest <- xmap_externctrl_params (S n) fn args; + ret ((param_reg, arg) :: rest) + end. + +Definition map_externctrl_params := xmap_externctrl_params 0. + +Definition transf_instr (ge : RTL.genv) (fin rtrn stack: reg) (ni: node * instruction) : mon unit := match ni with (n, i) => match i with @@ -481,7 +543,28 @@ Definition transf_instr (fin rtrn stack: reg) (ni: node * instruction) : mon uni do dst <- translate_arr_access mem addr args stack; add_instr n n' (Vnonblock dst (Vvar src)) (* TODO: Could juse use add_instr? reg exists. *) else error (Errors.msg "State is larger than 2^32.") - | Icall _ _ _ _ _ => error (Errors.msg "Calls are not implemented.") + | Icall sig (inl fn) args dst n' => error (Errors.msg "Indirect calls are not implemented.") + | Icall sig (inr fn) args dst n' => + if Z.leb (Z.pos n') Integers.Int.max_unsigned + then match find_func ge fn with + | Some (AST.Internal _) => + do params <- map_externctrl_params fn args; + + do _ <- declare_reg None dst 32; + do join_state <- create_state; + + do finish_reg <- map_externctrl fn ctrl_finish; + do reset_reg <- map_externctrl fn ctrl_reset; + do return_reg <- map_externctrl fn ctrl_return; + + let fork_instr := fork reset_reg params in + let join_instr := join return_reg reset_reg dst in + + do _ <- add_instr n join_state fork_instr; + add_instr_wait finish_reg join_state n' join_instr + | _ => error (Errors.msg "Call to non-internal function") + end + else error (Errors.msg "State is larger than 2^32.") | Itailcall _ _ _ => error (Errors.msg "Tailcalls are not implemented.") | Ibuiltin _ _ _ _ => error (Errors.msg "Builtin functions not implemented.") | Icond cond args n1 n2 => @@ -494,68 +577,28 @@ Definition transf_instr (fin rtrn stack: reg) (ni: node * instruction) : mon uni add_node_skip n (Vcase (Vvar r) (tbl_to_case_expr s.(st_st) tbl) (Some Vskip))*) error (Errors.msg "Ijumptable: Case statement not supported.") | Ireturn r => - match r with - | Some r' => - add_instr_skip n (Vseq (block fin (Vlit (ZToValue 1%Z))) (block rtrn (Vvar r'))) - | None => - add_instr_skip n (Vseq (block fin (Vlit (ZToValue 1%Z))) (block rtrn (Vlit (ZToValue 0%Z)))) - end + do idle_state <- create_state; + do _ <- add_instr n idle_state (do_return fin rtrn r); + add_instr_skip idle_state (idle fin) end end. -Lemma create_reg_state_incr: - forall s sz i, - st_incr s (mkstate - s.(st_st) - (Pos.succ (st_freshreg s)) - (st_freshstate s) - (AssocMap.set s.(st_freshreg) (i, VScalar sz) s.(st_scldecls)) - s.(st_arrdecls) - (st_datapath s) - (st_controllogic s)). -Proof. constructor; simpl; auto with htlh. Qed. - -Definition create_reg (i : option io) (sz : nat) : mon reg := - fun s => let r := s.(st_freshreg) in - OK r (mkstate - s.(st_st) - (Pos.succ r) - (st_freshstate s) - (AssocMap.set s.(st_freshreg) (i, VScalar sz) s.(st_scldecls)) - (st_arrdecls s) - (st_datapath s) - (st_controllogic s)) - (create_reg_state_incr s sz i). - -Lemma create_arr_state_incr: - forall s sz ln i, - st_incr s (mkstate - s.(st_st) - (Pos.succ (st_freshreg s)) - (st_freshstate s) - s.(st_scldecls) - (AssocMap.set s.(st_freshreg) (i, VArray sz ln) s.(st_arrdecls)) - (st_datapath s) - (st_controllogic s)). -Proof. constructor; simpl; auto with htlh. Qed. - Definition create_arr (i : option io) (sz : nat) (ln : nat) : mon (reg * nat) := fun s => let r := s.(st_freshreg) in - OK (r, ln) (mkstate - s.(st_st) - (Pos.succ r) - (st_freshstate s) - s.(st_scldecls) - (AssocMap.set s.(st_freshreg) (i, VArray sz ln) s.(st_arrdecls)) - (st_datapath s) - (st_controllogic s)) - (create_arr_state_incr s sz ln i). + OK (r, ln) (mkstate + s.(st_st) + (Pos.succ r) + (st_freshstate s) + s.(st_scldecls) + (AssocMap.set s.(st_freshreg) (i, VArray sz ln) s.(st_arrdecls)) + (st_externctrl s) + (st_datapath s) + (st_controllogic s)) ltac:(st_tac). Definition stack_correct (sz : Z) : bool := (0 <=? sz) && (sz <? Integers.Ptrofs.modulus) && (Z.modulo sz 4 =? 0). -Definition max_pc_map (m : Maps.PTree.t stmnt) := - PTree.fold (fun m pc i => Pos.max m pc) m 1%positive. +Definition declare_params params := collectlist (fun r => declare_reg (Some Vinput) r 32) params. Lemma max_pc_map_sound: forall m pc i, m!pc = Some i -> Ple pc (max_pc_map m). @@ -597,14 +640,14 @@ Defined. Definition transf_module (f: function) : mon HTL.module. refine ( if stack_correct f.(fn_stacksize) then + do _ <- declare_params (RTL.fn_params f); do fin <- create_reg (Some Voutput) 1; do rtrn <- create_reg (Some Voutput) 32; do (stack, stack_len) <- create_arr None 32 (Z.to_nat (f.(fn_stacksize) / 4)); - do _ <- collectlist (transf_instr fin rtrn stack) (Maps.PTree.elements f.(RTL.fn_code)); - do _ <- collectlist (fun r => declare_reg (Some Vinput) r 32) f.(RTL.fn_params); do start <- create_reg (Some Vinput) 1; do rst <- create_reg (Some Vinput) 1; do clk <- create_reg (Some Vinput) 1; + do _ <- collectlist (transf_instr ge fin rtrn stack) (Maps.PTree.elements f.(RTL.fn_code)); do current_state <- get; match zle (Z.pos (max_pc_map current_state.(st_datapath))) Integers.Int.max_unsigned, zle (Z.pos (max_pc_map current_state.(st_controllogic))) Integers.Int.max_unsigned, @@ -627,6 +670,7 @@ Definition transf_module (f: function) : mon HTL.module. clk current_state.(st_scldecls) current_state.(st_arrdecls) + current_state.(st_externctrl) None (conj (max_pc_wf _ LECTRL) (max_pc_wf _ LEDATA)) MORD @@ -644,13 +688,23 @@ Definition max_state (f: function) : state := (Pos.succ (RTL.max_pc_function f)) (AssocMap.set st (None, VScalar 32) (st_scldecls (init_state st))) (st_arrdecls (init_state st)) + (st_externctrl (init_state st)) (st_datapath (init_state st)) (st_controllogic (init_state st)). -Definition transl_module (f : function) : Errors.res HTL.module := - run_mon (max_state f) (transf_module f). +Definition prog_funmap (prog : RTL.program) : (PTree.t RTL.fundef) := + AssocMap_Properties.of_list ( + Option.map_option (fun '(ident, def) => match def with + | AST.Gfun f => Some (ident, f) + | _ => None + end) + (AST.prog_defs prog) + ). + +Definition transl_module (prog : RTL.program) (f : function) : Errors.res HTL.module := + run_mon (max_state f) (transf_module (Globalenvs.Genv.globalenv prog) (AST.prog_main prog) f). -Definition transl_fundef := transf_partial_fundef transl_module. +Definition transl_fundef prog := transf_partial_fundef (transl_module prog). Definition main_is_internal (p : RTL.program) : bool := let ge := Globalenvs.Genv.globalenv p in @@ -665,5 +719,5 @@ Definition main_is_internal (p : RTL.program) : bool := Definition transl_program (p : RTL.program) : Errors.res HTL.program := if main_is_internal p - then transform_partial_program transl_fundef p + then transform_partial_program (transl_fundef p) p else Errors.Error (Errors.msg "Main function is not Internal."). diff --git a/src/hls/HTLgenproof.v b/src/hls/HTLgenproof.v index 1aac3b7..c2cbbf8 100644 --- a/src/hls/HTLgenproof.v +++ b/src/hls/HTLgenproof.v @@ -24,10 +24,12 @@ Require Import compcert.common.Globalenvs. Require Import compcert.common.Linking. Require Import compcert.common.Memory. Require Import compcert.lib.Integers. +Require Import compcert.lib.Maps. Require Import vericert.common.IntegerExtra. Require Import vericert.common.Vericertlib. Require Import vericert.common.ZExtra. +Require Import vericert.common.ListExtra. Require Import vericert.hls.Array. Require Import vericert.hls.AssocMap. Require vericert.hls.HTL. @@ -46,6 +48,8 @@ Hint Resolve AssocMap.gso : htlproof. Hint Unfold find_assocmap AssocMapExt.get_default : htlproof. +Hint Constructors val_value_lessdef : htlproof. + Inductive match_assocmaps : RTL.function -> RTL.regset -> assocmap -> Prop := match_assocmap : forall f rs am, (forall r, Ple r (RTL.max_reg_function f) -> @@ -54,12 +58,12 @@ Inductive match_assocmaps : RTL.function -> RTL.regset -> assocmap -> Prop := Hint Constructors match_assocmaps : htlproof. Definition state_st_wf (m : HTL.module) (s : HTL.state) := - forall st asa asr res, - s = HTL.State res m st asa asr -> + forall mid st asa asr res, + s = HTL.State res mid m st asa asr -> asa!(m.(HTL.mod_st)) = Some (posToValue st). Hint Unfold state_st_wf : htlproof. -Inductive match_arrs (m : HTL.module) (f : RTL.function) (sp : Values.val) (mem : mem) : +Inductive match_arrs (m : HTL.module) (f : RTL.function) (sp : Values.val) (mem : Memory.mem) : Verilog.assocmap_arr -> Prop := | match_arr : forall asa stack, asa ! (m.(HTL.mod_stk)) = Some stack /\ @@ -78,6 +82,12 @@ Definition stack_based (v : Values.val) (sp : Values.block) : Prop := | _ => True end. +Definition not_pointer (v : Values.val) : Prop := + match v with + | Values.Vptr _ _ => False + | _ => True + end. + Definition reg_stack_based_pointers (sp : Values.block) (rs : Registers.Regmap.t Values.val) : Prop := forall r, stack_based (Registers.Regmap.get r rs) sp. @@ -98,10 +108,6 @@ Definition stack_bounds (sp : Values.val) (hi : Z) (m : mem) : Prop := Mem.loadv AST.Mint32 m (Values.Val.offset_ptr sp (Integers.Ptrofs.repr ptr )) = None /\ Mem.storev AST.Mint32 m (Values.Val.offset_ptr sp (Integers.Ptrofs.repr ptr )) v = None. -Inductive match_frames : list RTL.stackframe -> list HTL.stackframe -> Prop := -| match_frames_nil : - match_frames nil nil. - Inductive match_constants : HTL.module -> assocmap -> Prop := match_constant : forall m asr, @@ -109,34 +115,72 @@ Inductive match_constants : HTL.module -> assocmap -> Prop := asr!(HTL.mod_finish m) = Some (ZToValue 0) -> match_constants m asr. -Inductive match_states : RTL.state -> HTL.state -> Prop := -| match_state : forall asa asr sf f sp sp' rs mem m st res +(** The caller needs to have externctrl signals for the current module *) +Definition has_externctrl (caller : HTL.module) (current_id : HTL.ident) (ret rst fin : HTL.reg) := + (HTL.mod_externctrl caller)!ret = Some (current_id, HTL.ctrl_return) /\ + (HTL.mod_externctrl caller)!rst = Some (current_id, HTL.ctrl_reset) /\ + (HTL.mod_externctrl caller)!fin = Some (current_id, HTL.ctrl_finish). + +Inductive match_frames (ge : RTL.genv) (current_id : HTL.ident) (mem : Memory.mem) + : (list RTL.stackframe) -> (list HTL.stackframe) -> Prop := +| match_frames_nil : + match_frames ge current_id mem nil nil +| match_frames_cons : + forall dst f sp sp' rs mid m pc st asr asa rtl_tl htl_tl ret rst fin + (MASSOC : match_assocmaps f rs asr) + (TF : tr_module ge f m) + (MARR : match_arrs m f sp mem asa) + (SP : sp = Values.Vptr sp' (Integers.Ptrofs.repr 0)) + (RSBP : reg_stack_based_pointers sp' rs) + (ASBP : arr_stack_based_pointers sp' mem (f.(RTL.fn_stacksize)) sp) + (BOUNDS : stack_bounds sp (f.(RTL.fn_stacksize)) mem) + (CONST : match_constants m asr) + (EXTERN_CALLER : has_externctrl m current_id ret rst fin) + (JOIN_CTRL : (HTL.mod_controllogic m)!st = Some (state_wait (HTL.mod_st m) fin pc)) + (JOIN_DATA : (HTL.mod_datapath m)!st = Some (join ret rst dst)) + (TAILS : match_frames ge mid mem rtl_tl htl_tl) + (DST : Ple dst (RTL.max_reg_function f)) + (PC : (Z.pos pc <= Int.max_unsigned)), + match_frames ge current_id mem + ((RTL.Stackframe dst f sp pc rs) :: rtl_tl) + ((HTL.Stackframe mid m st asr asa) :: htl_tl). + +Inductive match_states (ge : RTL.genv) : RTL.state -> HTL.state -> Prop := +| match_state : forall asa asr sf f sp sp' rs mem mid m st res (MASSOC : match_assocmaps f rs asr) - (TF : tr_module f m) - (WF : state_st_wf m (HTL.State res m st asr asa)) - (MF : match_frames sf res) + (TF : tr_module ge f m) + (WF : state_st_wf m (HTL.State res mid m st asr asa)) + (MF : match_frames ge mid mem sf res) (MARR : match_arrs m f sp mem asa) (SP : sp = Values.Vptr sp' (Integers.Ptrofs.repr 0)) (RSBP : reg_stack_based_pointers sp' rs) (ASBP : arr_stack_based_pointers sp' mem (f.(RTL.fn_stacksize)) sp) (BOUNDS : stack_bounds sp (f.(RTL.fn_stacksize)) mem) (CONST : match_constants m asr), - match_states (RTL.State sf f sp st rs mem) - (HTL.State res m st asr asa) + match_states ge + (RTL.State sf f sp st rs mem) + (HTL.State res mid m st asr asa) | match_returnstate : - forall - v v' stack mem res - (MF : match_frames stack res), - val_value_lessdef v v' -> - match_states (RTL.Returnstate stack v mem) (HTL.Returnstate res v') -| match_initial_call : - forall f m m0 - (TF : tr_module f m), - match_states (RTL.Callstate nil (AST.Internal f) nil m0) (HTL.Callstate nil m nil). + forall v v' rtl_stk htl_stk mem mid + (MF : match_frames ge mid mem rtl_stk htl_stk) + (MV : val_value_lessdef v v') + (NP : not_pointer v), + match_states ge + (RTL.Returnstate rtl_stk v mem) + (HTL.Returnstate htl_stk mid v') +| match_call : + forall f m rtl_args htl_args mid mem rtl_stk htl_stk + (TF : tr_module ge f m) + (MF : match_frames ge mid mem rtl_stk htl_stk) + (NP : Forall not_pointer rtl_args) + (MARGS : list_forall2 val_value_lessdef rtl_args htl_args), + match_states ge + (RTL.Callstate rtl_stk (AST.Internal f) rtl_args mem) + (HTL.Callstate htl_stk mid m htl_args). Hint Constructors match_states : htlproof. Definition match_prog (p: RTL.program) (tp: HTL.program) := - Linking.match_program (fun cu f tf => transl_fundef f = Errors.OK tf) eq p tp /\ + Linking.match_program (fun cu f tf => transl_fundef p f = Errors.OK tf) eq p tp /\ main_is_internal p = true. Instance TransfHTLLink (tr_fun: RTL.program -> Errors.res HTL.program): @@ -158,7 +202,7 @@ Proof. Qed. Definition match_prog' (p: RTL.program) (tp: HTL.program) := - Linking.match_program (fun cu f tf => transl_fundef f = Errors.OK tf) eq p tp. + Linking.match_program (fun cu f tf => transl_fundef p f = Errors.OK tf) eq p tp. Lemma match_prog_matches : forall p tp, match_prog p tp -> match_prog' p tp. @@ -174,6 +218,15 @@ Proof. assumption. Qed. +Lemma regs_lessdef_empty : forall f, match_assocmaps f (Registers.Regmap.init Values.Vundef) empty_assocmap. +Proof. + constructor. intros. + unfold Registers.Regmap.init, "_ !! _", "_ # _", empty_assocmap, AssocMapExt.get_default. + repeat rewrite PTree.gempty. + constructor. +Qed. +Hint Resolve regs_lessdef_empty : htlproof. + Lemma regs_lessdef_add_greater : forall f rs1 rs2 n v, Plt (RTL.max_reg_function f) n -> @@ -296,19 +349,24 @@ Proof. assumption. Qed. +Lemma option_inv : + forall A x y, + @Some A x = Some y -> x = y. +Proof. intros. inversion H. trivial. Qed. + Ltac inv_state := match goal with - MSTATE : match_states _ _ |- _ => + MSTATE : match_states _ _ _ |- _ => inversion MSTATE; match goal with - TF : tr_module _ _ |- _ => + TF : tr_module _ _ _ |- _ => inversion TF; match goal with TC : forall _ _, - Maps.PTree.get _ _ = Some _ -> tr_code _ _ _ _ _ _ _ _ _, + Maps.PTree.get _ _ = Some _ -> tr_code _ _ _ _ _ _ _ _ _ _ _, H : Maps.PTree.get _ _ = Some _ |- _ => apply TC in H; inversion H; - match goal with + try match goal with TI : context[tr_instr] |- _ => inversion TI end @@ -325,6 +383,17 @@ Ltac unfold_func H := | ?f _ _ _ _ = _ => unfold f in H; repeat (unfold_match H) end. +Ltac not_control_reg := + solve [ + unfold Ple, Plt in *; + try multimatch goal with + | [ H : forall r, (exists x, _ ! r = Some x) -> (r > _)%positive + |- context[?r'] + ] => pose proof (H r' ltac:(eauto)) + end; + lia + ]. + Lemma init_reg_assoc_empty : forall f l, match_assocmaps f (RTL.init_regs nil l) (HTL.init_regs nil l). @@ -355,14 +424,51 @@ Section CORRECTNESS. Variable prog : RTL.program. Variable tprog : HTL.program. + Let ge : RTL.genv := Globalenvs.Genv.globalenv prog. + Let tge : HTL.genv := Globalenvs.Genv.globalenv tprog. + Hypothesis TRANSL : match_prog prog tprog. - Lemma TRANSL' : - Linking.match_program (fun cu f tf => transl_fundef f = Errors.OK tf) eq prog tprog. - Proof. intros; apply match_prog_matches; assumption. Qed. + Axiom no_pointer_return : forall (rs : RTL.regset) r s (f : RTL.function) sp pc rs mem f S, + (RTL.fn_code f) ! pc = Some (RTL.Ireturn (Some r)) -> + match_states ge (RTL.State s f sp pc rs mem) S -> + (not_pointer rs !! r). - Let ge : RTL.genv := Globalenvs.Genv.globalenv prog. - Let tge : HTL.genv := Globalenvs.Genv.globalenv tprog. + (** The following are assumed to be guaranteed by an inlining pass previous to + this translation. [ only_main_stores ] should be a direct result of that + inlining. + + [ no_stack_functions ] and [ no_stack_calls ] might be provable as + corollaries of [ only_main_stores ] + *) + Axiom only_main_stores : forall rtl_stk f sp pc pc' rs mem htl_stk mid m asr asa a b c d, + match_states ge (RTL.State rtl_stk f sp pc rs mem) (HTL.State htl_stk mid m pc asr asa) -> + (RTL.fn_code f) ! pc = Some (RTL.Istore a b c d pc') -> + (rtl_stk = nil /\ htl_stk = nil). + + Axiom no_stack_functions : forall f sp rs mem st rtl_stk S, + match_states ge (RTL.State rtl_stk f sp st rs mem) S -> + (RTL.fn_stacksize f) = 0 \/ rtl_stk = nil. + + Axiom no_stack_calls : forall f mem args rtl_stk S, + match_states ge (RTL.Callstate rtl_stk (AST.Internal f) args mem) S -> + (RTL.fn_stacksize f) = 0 \/ rtl_stk = nil. + + (** The following admitted lemmas should be provable *) + Lemma mem_free_zero : forall mem blk, Mem.free mem blk 0 0 = Some mem. + Admitted. + + Lemma mem_alloc_zero : forall mem, exists blk, Mem.alloc mem 0 0 = (mem, blk). + Admitted. + + Lemma match_arrs_empty : forall m f sp mem asa, + match_arrs m f sp mem asa -> + match_arrs m f sp mem (Verilog.merge_arrs (HTL.empty_stack m) asa). + Admitted. + + Lemma TRANSL' : + Linking.match_program (fun cu f tf => transl_fundef prog f = Errors.OK tf) eq prog tprog. + Proof. pose proof match_prog_matches as H. unfold match_prog' in H. auto. Qed. Lemma symbols_preserved: forall (s: AST.ident), Genv.find_symbol tge s = Genv.find_symbol ge s. @@ -372,7 +478,7 @@ Section CORRECTNESS. forall (b: Values.block) (f: RTL.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. + Genv.find_funct_ptr tge b = Some tf /\ transl_fundef prog f = Errors.OK tf. Proof. intros. exploit (Genv.find_funct_ptr_match TRANSL'); eauto. intros (cu & tf & P & Q & R); exists tf; auto. @@ -382,7 +488,7 @@ Section CORRECTNESS. forall (v: Values.val) (f: RTL.fundef), Genv.find_funct ge v = Some f -> exists tf, - Genv.find_funct tge v = Some tf /\ transl_fundef f = Errors.OK tf. + Genv.find_funct tge v = Some tf /\ transl_fundef prog f = Errors.OK tf. Proof. intros. exploit (Genv.find_funct_match TRANSL'); eauto. intros (cu & tf & P & Q & R); exists tf; auto. @@ -592,14 +698,14 @@ Section CORRECTNESS. end. Lemma eval_cond_correct : - forall stk f sp pc rs m res ml st asr asa e b f' s s' args i cond, - match_states (RTL.State stk f sp pc rs m) (HTL.State res ml st asr asa) -> + forall stk f sp pc rs mid m res ml st asr asa e b f' s s' args i cond, + match_states ge (RTL.State stk f sp pc rs m) (HTL.State res mid ml st asr asa) -> (forall v, In v args -> Ple v (RTL.max_reg_function f)) -> Op.eval_condition cond (map (fun r : positive => Registers.Regmap.get r rs) args) m = Some b -> translate_condition cond args s = OK e s' i -> Verilog.expr_runp f' asr asa e (boolToValue b). Proof. - intros stk f sp pc rs m res ml st asr asa e b f' s s' args i cond MSTATE MAX_FUN EVAL TR_INSTR. + intros * MSTATE MAX_FUN EVAL TR_INSTR. pose proof MSTATE as MSTATE_2. inv MSTATE. inv MASSOC. unfold translate_condition, translate_comparison, translate_comparisonu, translate_comparison_imm, @@ -723,21 +829,21 @@ Section CORRECTNESS. Qed. Lemma eval_cond_correct' : - forall e stk f sp pc rs m res ml st asr asa v f' s s' args i cond, - match_states (RTL.State stk f sp pc rs m) (HTL.State res ml st asr asa) -> + forall e stk f sp pc rs m res mid ml st asr asa v f' s s' args i cond, + match_states ge (RTL.State stk f sp pc rs m) (HTL.State res mid ml st asr asa) -> (forall v, In v args -> Ple v (RTL.max_reg_function f)) -> Values.Val.of_optbool None = v -> translate_condition cond args s = OK e s' i -> exists v', Verilog.expr_runp f' asr asa e v' /\ val_value_lessdef v v'. - intros e stk f sp pc rs m res ml st asr asa v f' s s' args i cond MSTATE MAX_FUN EVAL TR_INSTR. + intros * MSTATE MAX_FUN EVAL TR_INSTR. unfold translate_condition, translate_comparison, translate_comparisonu, translate_comparison_imm, translate_comparison_immu, bop, boplit in *. repeat unfold_match TR_INSTR; inv TR_INSTR; repeat econstructor. Qed. Lemma eval_correct_Oshrximm : - forall s sp rs m v e asr asa f f' stk s' i pc res0 pc' args res ml st n, - match_states (RTL.State stk f sp pc rs m) (HTL.State res ml st asr asa) -> + forall s sp rs m v e asr asa f f' stk s' i pc res0 pc' args res mid ml st n, + match_states ge (RTL.State stk f sp pc rs m) (HTL.State res mid ml st asr asa) -> (RTL.fn_code f) ! pc = Some (RTL.Iop (Op.Oshrximm n) args res0 pc') -> Op.eval_operation ge sp (Op.Oshrximm n) (List.map (fun r : BinNums.positive => @@ -745,13 +851,10 @@ Section CORRECTNESS. translate_instr (Op.Oshrximm n) args s = OK e s' i -> exists v', Verilog.expr_runp f' asr asa e v' /\ val_value_lessdef v v'. Proof. - intros s sp rs m v e asr asa f f' stk s' i pc pc' res0 args res ml st n MSTATE INSTR EVAL TR_INSTR. + intros * MSTATE INSTR EVAL TR_INSTR. pose proof MSTATE as MSTATE_2. inv MSTATE. inv MASSOC. unfold translate_instr in TR_INSTR; repeat (unfold_match TR_INSTR); inv TR_INSTR; unfold Op.eval_operation in EVAL; repeat (unfold_match EVAL); inv EVAL. - (*repeat (simplify; eval_correct_tac; unfold valueToInt in * ). - destruct (Z_lt_ge_dec (Int.signed i0) 0). - econstructor.*) unfold Values.Val.shrx in *. destruct v0; try discriminate. destruct (Int.ltu n (Int.repr 31)) eqn:?; try discriminate. @@ -801,15 +904,15 @@ Section CORRECTNESS. Qed. Lemma eval_correct : - forall s sp op rs m v e asr asa f f' stk s' i pc res0 pc' args res ml st, - match_states (RTL.State stk f sp pc rs m) (HTL.State res ml st asr asa) -> + forall s sp op rs m v e asr asa f f' stk s' i pc res0 pc' args res mid ml st , + match_states ge (RTL.State stk f sp pc rs m) (HTL.State res mid ml st asr asa) -> (RTL.fn_code f) ! pc = Some (RTL.Iop op args res0 pc') -> Op.eval_operation ge sp op (List.map (fun r : BinNums.positive => Registers.Regmap.get r rs) args) m = Some v -> translate_instr op args s = OK e s' i -> exists v', Verilog.expr_runp f' asr asa e v' /\ val_value_lessdef v v'. Proof. - intros s sp op rs m v e asr asa f f' stk s' i pc pc' res0 args res ml st MSTATE INSTR EVAL TR_INSTR. + intros * MSTATE INSTR EVAL TR_INSTR. pose proof MSTATE as MSTATE_2. inv MSTATE. inv MASSOC. unfold translate_instr in TR_INSTR; repeat (unfold_match TR_INSTR); inv TR_INSTR; unfold Op.eval_operation in EVAL; repeat (unfold_match EVAL); inv EVAL; @@ -836,8 +939,6 @@ Section CORRECTNESS. - rewrite Heqb in Heqb0. discriminate. - rewrite H0 in Heqb. rewrite H1 in Heqb. discriminate. - rewrite Heqb in Heqb0. discriminate. - (*- unfold Int.ror. unfold Int.or. unfold Int.shru, Int.shl, Int.sub. unfold intToValue. unfold Int.modu, - repeat (rewrite Int.unsigned_repr). auto.*) - assert (Int.unsigned n <= 30). { unfold Int.ltu in *. destruct (zlt (Int.unsigned n) (Int.unsigned (Int.repr 31))); try discriminate. rewrite Int.unsigned_repr in l by (simplify; lia). @@ -1021,10 +1122,10 @@ Section CORRECTNESS. *) Definition transl_instr_prop (instr : RTL.instruction) : Prop := - forall m asr asa fin rtrn st stmt trans res, + forall mid m asr asa fin rtrn st stmt trans res, tr_instr fin rtrn st (m.(HTL.mod_stk)) instr stmt trans -> exists asr' asa', - HTL.step tge (HTL.State res m st asr asa) Events.E0 (HTL.State res m st asr' asa'). + HTL.step tge (HTL.State res mid m st asr asa) Events.E0 (HTL.State res mid m st asr' asa'). Opaque combine. @@ -1077,31 +1178,25 @@ Section CORRECTNESS. (rs : RTL.regset) (m : mem) (pc' : RTL.node), (RTL.fn_code f) ! pc = Some (RTL.Inop pc') -> forall R1 : HTL.state, - match_states (RTL.State s f sp pc rs m) R1 -> + match_states ge (RTL.State s f sp pc rs m) R1 -> exists R2 : HTL.state, - Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ match_states (RTL.State s f sp pc' rs m) R2. + Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ match_states ge (RTL.State s f sp pc' rs m) R2. Proof. - intros s f sp pc rs m pc' H R1 MSTATE. + intros * H R1 MSTATE. inv_state. unfold match_prog in TRANSL. - econstructor. + eexists. split. - apply Smallstep.plus_one. - eapply HTL.step_module; eauto. - inv CONST; assumption. - inv CONST; assumption. - (* processing of state *) - econstructor. - crush. - econstructor. - econstructor. - econstructor. - - all: invert MARR; big_tac. - - inv CONST; constructor; simplify; rewrite AssocMap.gso; auto; lia. - + - apply Smallstep.plus_one. + eapply HTL.step_module; eauto. + + inv CONST; assumption. + + inv CONST; assumption. + + repeat constructor. + + repeat constructor. + + big_tac. + - inv CONST. inv MARR. simplify. big_tac. + constructor; rewrite AssocMap.gso; crush. Unshelve. exact tt. Qed. Hint Resolve transl_inop_correct : htlproof. @@ -1113,50 +1208,486 @@ Section CORRECTNESS. (RTL.fn_code f) ! pc = Some (RTL.Iop op args res0 pc') -> Op.eval_operation ge sp op (map (fun r : positive => Registers.Regmap.get r rs) args) m = Some v -> forall R1 : HTL.state, - match_states (RTL.State s f sp pc rs m) R1 -> + match_states ge (RTL.State s f sp pc rs m) R1 -> exists R2 : HTL.state, Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ - match_states (RTL.State s f sp pc' (Registers.Regmap.set res0 v rs) m) R2. + match_states ge (RTL.State s f sp pc' (Registers.Regmap.set res0 v rs) m) R2. Proof. - intros s f sp pc rs m op args res0 pc' v H H0 R1 MSTATE. + intros * H H0 R1 MSTATE. inv_state. inv MARR. exploit eval_correct; eauto. intros. inversion H1. inversion H2. - econstructor. split. + eexists. split. apply Smallstep.plus_one. eapply HTL.step_module; eauto. - inv CONST. assumption. - inv CONST. assumption. - econstructor; simpl; trivial. - constructor; trivial. - econstructor; simpl; eauto. - simpl. econstructor. econstructor. - apply H5. simplify. + - inv CONST. assumption. + - inv CONST. assumption. + - repeat econstructor. + - repeat econstructor. intuition eauto. + - big_tac. + assert (Ple res0 (RTL.max_reg_function f)) + by eauto using RTL.max_reg_function_def. + xomega. + - big_tac. + + apply regs_lessdef_add_match. assumption. + apply regs_lessdef_add_greater. unfold Plt; lia. assumption. + + assert (HPle: Ple res0 (RTL.max_reg_function f)) + by (eapply RTL.max_reg_function_def; eauto; simpl; auto). + unfold Ple in HPle; lia. + + eapply op_stack_based; eauto. + + inv CONST. constructor; simplify. + * rewrite AssocMap.gso. rewrite AssocMap.gso. + assumption. lia. + assert (HPle: Ple res0 (RTL.max_reg_function f)) + by (eapply RTL.max_reg_function_def; eauto; simpl; auto). + unfold Ple in HPle. lia. + * rewrite AssocMap.gso. rewrite AssocMap.gso. + assumption. lia. + assert (HPle: Ple res0 (RTL.max_reg_function f)) + by (eapply RTL.max_reg_function_def; eauto; simpl; auto). + unfold Ple in HPle. lia. + Unshelve. exact tt. + Qed. + Hint Resolve transl_iop_correct : htlproof. - all: big_tac. + Lemma match_args : forall rtl_args htl_args params f, + list_forall2 val_value_lessdef rtl_args htl_args -> + match_assocmaps f (RTL.init_regs rtl_args params) (HTL.init_regs htl_args params). + Proof. + induction rtl_args; intros * H; inv H. + - destruct params; eauto with htlproof. + - destruct params; eauto using regs_lessdef_add_match with htlproof. + Qed. - assert (HPle: Ple res0 (RTL.max_reg_function f)) - by (eapply RTL.max_reg_function_def; eauto; simpl; auto). + Lemma stack_based_set : forall sp r v rs, + stack_based v sp -> + reg_stack_based_pointers sp rs -> + reg_stack_based_pointers sp (Registers.Regmap.set r v rs). + Proof. + unfold reg_stack_based_pointers, Registers.Regmap.set, "_ !! _". + intros * ? ? r0. + simpl. + destruct (peq r r0); subst. + - rewrite AssocMap.gss; auto. + - rewrite AssocMap.gso; auto. + Qed. - unfold Ple in HPle. lia. - apply regs_lessdef_add_match. assumption. - apply regs_lessdef_add_greater. unfold Plt; lia. assumption. - assert (HPle: Ple res0 (RTL.max_reg_function f)) - by (eapply RTL.max_reg_function_def; eauto; simpl; auto). - unfold Ple in HPle; lia. - eapply op_stack_based; eauto. - inv CONST. constructor; simplify. rewrite AssocMap.gso. rewrite AssocMap.gso. - assumption. lia. - assert (HPle: Ple res0 (RTL.max_reg_function f)) - by (eapply RTL.max_reg_function_def; eauto; simpl; auto). - unfold Ple in HPle. lia. - rewrite AssocMap.gso. rewrite AssocMap.gso. - assumption. lia. - assert (HPle: Ple res0 (RTL.max_reg_function f)) - by (eapply RTL.max_reg_function_def; eauto; simpl; auto). - unfold Ple in HPle. lia. - Unshelve. exact tt. + Lemma stack_based_non_pointers : forall args params stk, + Forall not_pointer args -> + reg_stack_based_pointers stk (RTL.init_regs args params). + Proof. + unfold reg_stack_based_pointers. + induction args; intros * NP *. + + destruct params; + simpl; + unfold "_ !! _"; + rewrite PTree.gempty; + crush. + + destruct params; simpl. + * unfold "_ !! _". rewrite PTree.gempty. crush. + * inv NP. + apply stack_based_set; + [ destruct a; crush + | unfold reg_stack_based_pointers; auto + ]. Qed. - Hint Resolve transl_iop_correct : htlproof. + + Lemma transl_callstate_correct: + forall (s : list RTL.stackframe) (f : RTL.function) (args : list Values.val) + (m : mem) (m' : Mem.mem') (stk : Values.block), + Mem.alloc m 0 (RTL.fn_stacksize f) = (m', stk) -> + forall R1 : HTL.state, + match_states ge (RTL.Callstate s (AST.Internal f) args m) R1 -> + exists R2 : HTL.state, + Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ + match_states ge + (RTL.State s f (Values.Vptr stk Integers.Ptrofs.zero) (RTL.fn_entrypoint f) + (RTL.init_regs args (RTL.fn_params f)) m') R2. + Proof. + intros * ? * MSTATE. + inversion MSTATE. + inversion TF. + simplify. + eexists. split. + apply Smallstep.plus_one. + solve [constructor]. + + simplify. + econstructor; try solve [big_tac]. + - repeat apply regs_lessdef_add_greater; try not_control_reg. + eauto using match_args. + - edestruct no_stack_calls; eauto. + + replace (RTL.fn_stacksize f) with 0 in * + by assumption. + replace m' with m + by (destruct (mem_alloc_zero m); crush). + assumption. + + subst. inv MF. constructor. + - big_tac. + admit. + - eauto using stack_based_non_pointers. + - (* Stack based stack pointer *) + unfold arr_stack_based_pointers; intros. + admit. + - (* Stack bounds *) + admit. + - constructor; simplify. + + rewrite AssocMap.gss; crush. + + rewrite AssocMap.gso by not_control_reg. + rewrite AssocMap.gss. crush. + Admitted. + Hint Resolve transl_callstate_correct : htlproof. + + Lemma only_internal_calls : forall fd fn rs, + RTL.find_function ge (inr fn) rs = Some fd -> + (exists f : RTL.function, HTL.find_func ge fn = Some (AST.Internal f)) -> + (exists f, fd = AST.Internal f). + Proof. + intros * ? [? ?]. + unfold HTL.find_func in *. + unfold RTL.find_function in *. + destruct (Genv.find_symbol ge fn); try discriminate. + exists x. crush. + Qed. + + Fixpoint assign_all acc (rs : list reg) (vals : list value) := + match rs, vals with + | r::rs', val::vals' => assign_all (acc # r <- val) rs' vals' + | _, _ => acc + end. + + Notation "a ## b '<-' c" := (assign_all a b c) (at level 1, b at next level) : assocmap. + + Lemma assign_all_nil : forall a rs, a ## rs <- nil = a. + Proof. destruct rs; crush. Qed. + + Lemma assign_all_out : forall rs vs a r, (forall v, ~ In (r, v) (List.combine rs vs)) -> (a ## rs <- vs) ! r = a ! r. + Proof. + induction rs; intros * H. + - trivial. + - destruct vs. + + rewrite assign_all_nil. + trivial. + + simpl. + rewrite IHrs. + rewrite AssocMap.gso. + crush. + * simpl (List.combine _ _) in *. + specialize (H v). + rewrite not_in_cons in H. + inv H. + crush. + * intros v0. + specialize (H v0). + simpl (List.combine _ _) in *. + rewrite not_in_cons in H. + crush. + Qed. + + Lemma nonblock_all_exec : forall from_regs to_regs f basr nasr basa nasa, + Verilog.stmnt_runp + f + {| Verilog.assoc_blocking := basr; Verilog.assoc_nonblocking := nasr |} + {| Verilog.assoc_blocking := basa; Verilog.assoc_nonblocking := nasa |} + (nonblock_all (List.combine to_regs from_regs)) + {| Verilog.assoc_blocking := basr; Verilog.assoc_nonblocking := nasr ## to_regs <- (basr##from_regs) |} + {| Verilog.assoc_blocking := basa; Verilog.assoc_nonblocking := nasa |}. + Proof. + induction from_regs; intros. + - rewrite combine_nil, assign_all_nil. + constructor. + - destruct to_regs; try solve [ constructor ]. + simpl. + econstructor. + + repeat econstructor. + + eapply IHfrom_regs. + Qed. + + Lemma fork_exec : forall f basr nasr basa nasa rst to_regs from_regs, + Verilog.stmnt_runp + f + {| Verilog.assoc_blocking := basr; Verilog.assoc_nonblocking := nasr |} + {| Verilog.assoc_blocking := basa; Verilog.assoc_nonblocking := nasa |} + (fork rst (List.combine to_regs from_regs)) + {| Verilog.assoc_blocking := basr; Verilog.assoc_nonblocking := (nasr # rst <- (ZToValue 1)) ## to_regs <- (basr##from_regs) |} + {| Verilog.assoc_blocking := basa; Verilog.assoc_nonblocking := nasa |}. + Proof. + intros. + unfold fork. + econstructor. + - repeat econstructor. + - unfold Verilog.nonblock_reg; simpl. + eapply nonblock_all_exec. + Qed. + + Lemma transl_find : forall fn f, + HTL.find_func ge fn = Some (AST.Internal f) -> + match_prog prog tprog -> + (exists f', HTL.find_func tge fn = Some (AST.Internal f')). + Proof. + intros. + unfold HTL.find_func in *. + rewrite symbols_preserved. + destruct (Genv.find_symbol ge fn); try discriminate. + destruct (function_ptr_translated _ _ H) as [? [? ?]]. + replace (Genv.find_funct_ptr tge b). + inversion H2. + destruct (transl_module prog f); try discriminate. + inversion H4. + exists m. crush. + Qed. + + Lemma param_mapping_correct : + forall fn (args : list reg) fn_params (externctrl : AssocMap.t (HTL.ident * HTL.controlsignal)), + length args = length fn_params -> + (forall n arg, nth_error args n = Some arg -> + exists r, List.nth_error fn_params n = Some r /\ + externctrl ! r = Some (fn, HTL.ctrl_param n)) -> + (forall n param, nth_error fn_params n = Some param -> + externctrl!param = Some (fn, HTL.ctrl_param n)). + Proof. + intros * Hlen Htr * Hfn_params. + + assert (H : exists arg, nth_error args n = Some arg). { + apply length_nth_error. + apply nth_error_length in Hfn_params. + lia. + } + destruct H as [ arg H ]. + edestruct (Htr _ _ H) as [? [? ?]]. + + enough (Some x = Some param) by crush. + congruence. + Qed. + + Lemma transl_icall_correct: + forall (s : list RTL.stackframe) (f : RTL.function) (sp : Values.val) + (pc : positive) (rs : RTL.regset) (m : mem) sig fn fd args dst pc', + (RTL.fn_code f) ! pc = Some (RTL.Icall sig fn args dst pc') -> + RTL.find_function ge fn rs = Some fd -> + forall R1 : HTL.state, + match_states ge (RTL.State s f sp pc rs m) R1 -> + exists R2 : HTL.state, + Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ + match_states ge (RTL.Callstate (RTL.Stackframe dst f sp pc' rs :: s) fd + (List.map (fun r => Registers.Regmap.get r rs) args) m) + R2. + Proof. + intros * H Hfunc * MSTATE. + inv_state. + edestruct (only_internal_calls fd); eauto; subst fd. + inv CONST. + simplify. + destruct (transl_find _ _ ltac:(eauto) TRANSL). + eexists. split. + - eapply Smallstep.plus_three; simpl in *. + + eapply HTL.step_module; simpl. + * auto. + * auto. + * eauto. + * eauto. + * eauto. + * repeat econstructor; eauto. + * repeat econstructor; eauto. + * eapply fork_exec. + * trivial. + * trivial. + * eapply AssocMapExt.merge_correct_1. + rewrite assign_all_out. + -- big_tac. + not_control_reg. + -- intros ? Hneg. + apply List.in_combine_l in Hneg. + insterU H6. + insterU H19. + (* All of x4 are in externctrl (by H6), but st1 is not because it is a control register *) + admit. + * eauto. + + eapply HTL.step_module; trivial. + * simpl. + apply AssocMapExt.merge_correct_2; auto. + rewrite assign_all_out by admit. + rewrite AssocMap.gso by not_control_reg. + rewrite AssocMap.gso by lia. + apply AssocMap.gempty. + * simpl. + apply AssocMapExt.merge_correct_2; auto. + rewrite assign_all_out by admit. + rewrite AssocMap.gso by not_control_reg. + rewrite AssocMap.gso by lia. + apply AssocMap.gempty. + * simpl. + apply AssocMapExt.merge_correct_1; auto. + rewrite assign_all_out by admit. + rewrite AssocMap.gso by not_control_reg. + apply AssocMap.gss. + * eauto. + * eauto. + * unfold state_wait. + eapply Verilog.stmnt_runp_Vcond_false. + -- simpl. econstructor; econstructor; simpl. + replace (Verilog.merge_regs ((empty_assocmap # st1 <- (posToValue x0)) # x1 <- (ZToValue 1)) ## x4 <- (asr ## args) asr) # x3 + with (ZToValue 0) by admit. + trivial. + -- auto. + -- econstructor. + * simpl. + apply AssocMapExt.merge_correct_1; auto. + rewrite assign_all_out by admit. + rewrite AssocMap.gso by not_control_reg. + apply AssocMap.gss. + * repeat econstructor. + * simpl. + apply AssocMapExt.merge_correct_2. + big_tac. + apply AssocMap.gempty. + not_control_reg. + assert (Ple dst (RTL.max_reg_function f)) + by eauto using RTL.max_reg_function_def. + xomega. + apply AssocMapExt.merge_correct_1. + rewrite assign_all_out by admit. + rewrite AssocMap.gso by not_control_reg. + apply AssocMap.gss. + * admit. + + eapply HTL.step_initcall. + * eassumption. + * eassumption. + * eauto using param_mapping_correct. + * big_tac. + assert (dst <= (RTL.max_reg_function f))%positive + by (eapply RTL.max_reg_function_def; eauto). + not_control_reg. + * simpl; trivial. + + eauto with htlproof. + - econstructor; try solve [repeat econstructor; eauto with htlproof ]. + + admit. + + (* Match stackframes *) admit. + + (* Argument values match *) admit. + Admitted. + Hint Resolve transl_icall_correct : htlproof. + Close Scope rtl. + + Lemma return_val_exec_spec : forall f or asr asa, + Verilog.expr_runp f asr asa (return_val or) + (match or with + | Some r => asr#r + | None => ZToValue 0 + end). + Proof. destruct or; repeat econstructor. Qed. + + Lemma transl_ireturn_correct: + forall (s : list RTL.stackframe) (f : RTL.function) (stk : Values.block) + (pc : positive) (rs : RTL.regset) (m : mem) (or : option Registers.reg) + (m' : mem), + (RTL.fn_code f) ! pc = Some (RTL.Ireturn or) -> + Mem.free m stk 0 (RTL.fn_stacksize f) = Some m' -> + forall R1 : HTL.state, + match_states ge (RTL.State s f (Values.Vptr stk Integers.Ptrofs.zero) pc rs m) R1 -> + exists R2 : HTL.state, + Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ + match_states ge (RTL.Returnstate s (Registers.regmap_optget or Values.Vundef rs) m') R2. + Proof. + intros * H H0 * MSTATE. + inv_state. + inv CONST. simplify. + eexists. split. + - eapply Smallstep.plus_two. + + eapply HTL.step_module; try solve [ repeat econstructor; eauto ]. + * repeat econstructor. apply return_val_exec_spec. + * big_tac. + * inversion wf. + eapply H10. + eapply AssocMapExt.elements_iff. + eauto. + + eapply HTL.step_finish; big_tac. + + eauto with htlproof. + - constructor; eauto with htlproof. + + edestruct no_stack_functions; eauto. + * replace (RTL.fn_stacksize f) in *. + replace m' with m by + (pose proof (mem_free_zero m ltac:(auto)); crush). + assumption. + * subst. inv MF. constructor. + + destruct or. + * rewrite fso. (* Return value is not fin *) + { + big_tac. + inv MASSOC. + apply H10. + eapply RTL.max_reg_function_use. + simpl; eauto. + simpl; eauto. + } + assert (Ple r (RTL.max_reg_function f)) + by (eapply RTL.max_reg_function_use; eauto; crush). + xomega. + * simpl. eauto with htlproof. + + destruct or; simpl; eauto using no_pointer_return. + Unshelve. try exact tt; eauto. + Qed. + Hint Resolve transl_ireturn_correct : htlproof. + + Lemma transl_returnstate_correct: + forall (res0 : Registers.reg) (f : RTL.function) (sp : Values.val) (pc : RTL.node) + (rs : RTL.regset) (s : list RTL.stackframe) (vres : Values.val) (m : mem) + (R1 : HTL.state), + match_states ge (RTL.Returnstate (RTL.Stackframe res0 f sp pc rs :: s) vres m) R1 -> + exists R2 : HTL.state, + Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ + match_states ge (RTL.State s f sp pc (Registers.Regmap.set res0 vres rs) m) R2. + Proof. + intros * MSTATE. + inv MSTATE. + inversion MF. + inversion EXTERN_CALLER. + simplify. + eexists; split. + - eapply Smallstep.plus_two. + + (* Return to caller *) + repeat econstructor; eauto. + + (* Join *) + inv CONST. + econstructor; eauto. + * big_tac; inv TF; simplify; not_control_reg. + * big_tac; inv TF; simplify; not_control_reg. + * big_tac; inv TF; simplify; not_control_reg. + * (* control logic *) + repeat econstructor. big_tac. simpl. + rewrite fso by crush. + rewrite fss. crush. + * big_tac; inv TF; simplify; not_control_reg. + * repeat econstructor. + * big_tac; inv TF; simplify; not_control_reg. + + trivial. + - simpl. + eapply match_state; simpl; eauto. + + big_tac. + inv TF. simplify. + eapply regs_lessdef_add_match. rewrite fss; eauto. + repeat eapply regs_lessdef_add_greater; eauto; not_control_reg. + + unfold state_st_wf. + intros * Hwf. + inv Hwf. + inv TF. + big_tac. + not_control_reg. + + auto using match_arrs_empty. + + eapply stack_based_set; eauto. + unfold not_pointer in *. + destruct vres; crush. + + (* match_constants *) + inv CONST. + inv TF. + big_tac. + constructor. + * simplify. + rewrite AssocMap.fss. + repeat rewrite AssocMap.gso; auto; not_control_reg. + * simplify. + repeat rewrite AssocMap.gso; auto; not_control_reg. + Unshelve. all: try exact tt; eauto. + Qed. + Hint Resolve transl_returnstate_correct : htlproof. Ltac tac := repeat match goal with @@ -1239,7 +1770,6 @@ Section CORRECTNESS. } rewrite <- H. auto. - Qed. Lemma offset_expr_ok_3 : @@ -1257,13 +1787,15 @@ Section CORRECTNESS. Op.eval_addressing ge sp addr (map (fun r : positive => Registers.Regmap.get r rs) args) = Some a -> Mem.loadv chunk m a = Some v -> forall R1 : HTL.state, - match_states (RTL.State s f sp pc rs m) R1 -> + match_states ge (RTL.State s f sp pc rs m) R1 -> exists R2 : HTL.state, Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ - match_states (RTL.State s f sp pc' (Registers.Regmap.set dst v rs) m) R2. + match_states ge (RTL.State s f sp pc' (Registers.Regmap.set dst v rs) m) R2. Proof. intros s f sp pc rs m chunk addr args dst pc' a v H H0 H1 R1 MSTATE. - inv_state. inv_arr_access. + inv_state. + + inv_arr_access. + (** Preamble *) invert MARR. inv CONST. crush. @@ -1336,28 +1868,29 @@ Section CORRECTNESS. inversion NORMALISE_BOUND as [ NORMALISE_BOUND_LOW NORMALISE_BOUND_HIGH ]; clear NORMALISE_BOUND. + (** Start of proof proper *) eexists. split. eapply Smallstep.plus_one. eapply HTL.step_module; eauto. - econstructor. econstructor. econstructor. crush. + econstructor. econstructor. econstructor. econstructor. crush. econstructor. econstructor. econstructor. crush. econstructor. econstructor. econstructor. econstructor. econstructor. econstructor. - econstructor. econstructor. + econstructor. all: big_tac. 1: { - assert (HPle : Ple dst (RTL.max_reg_function f)). - eapply RTL.max_reg_function_def. eassumption. auto. - apply ZExtra.Pge_not_eq. apply ZExtra.Ple_Plt_Succ. assumption. + assert (HPle : (dst <= (RTL.max_reg_function f))%positive) + by (eapply RTL.max_reg_function_def; eauto). + lia. } 2: { - assert (HPle : Ple dst (RTL.max_reg_function f)). - eapply RTL.max_reg_function_def. eassumption. auto. - apply ZExtra.Pge_not_eq. apply ZExtra.Ple_Plt_Succ. assumption. + assert (HPle : (dst <= (RTL.max_reg_function f))%positive) + by (eapply RTL.max_reg_function_def; eauto). + lia. } (** Match assocmaps *) @@ -1377,7 +1910,10 @@ Section CORRECTNESS. specialize (ASBP (Integers.Ptrofs.unsigned (Integers.Ptrofs.divu OFFSET (Integers.Ptrofs.repr 4)))). exploit ASBP; big_tac. - rewrite NORMALISE in H14. rewrite HeqOFFSET in H14. rewrite H1 in H14. assumption. + match goal with + | [ H: context[stack_based] |- _ ] => rewrite NORMALISE in H; rewrite HeqOFFSET in H; rewrite H1 in H + end. + assumption. constructor; simplify. rewrite AssocMap.gso. rewrite AssocMap.gso. assumption. lia. assert (HPle: Ple dst (RTL.max_reg_function f)) @@ -1417,7 +1953,7 @@ Section CORRECTNESS. apply H11 in HPler1. invert HPler0; invert HPler1; try congruence. rewrite EQr0 in H13. - rewrite EQr1 in H14. + rewrite EQr1 in H22. invert H13. invert H14. clear H0. clear H8. clear H11. @@ -1432,7 +1968,8 @@ Section CORRECTNESS. (** Modular preservation proof *) assert (Integers.Ptrofs.unsigned OFFSET mod 4 = 0) as MOD_PRESERVE. { apply Mem.load_valid_access in H1. unfold Mem.valid_access in *. simplify. - apply Zdivide_mod. assumption. } + apply Zdivide_mod. unfold valueToPtr in *. unfold uvalueToZ in *. unfold Ptrofs.of_int in *. unfold valueToInt in *. + inversion H22. subst. assumption. } (** Read bounds proof *) assert (Integers.Ptrofs.unsigned OFFSET < f.(RTL.fn_stacksize)) as READ_BOUND_HIGH. @@ -1474,21 +2011,27 @@ Section CORRECTNESS. eexists. split. eapply Smallstep.plus_one. eapply HTL.step_module; eauto. - econstructor. econstructor. econstructor. crush. + econstructor. econstructor. econstructor. econstructor. econstructor. crush. econstructor. econstructor. econstructor. crush. econstructor. econstructor. econstructor. econstructor. econstructor. econstructor. econstructor. econstructor. econstructor. auto. econstructor. - econstructor. econstructor. econstructor. econstructor. + econstructor. econstructor. econstructor. all: big_tac. - 1: { assert (HPle : Ple dst (RTL.max_reg_function f)). - eapply RTL.max_reg_function_def. eassumption. auto. - apply ZExtra.Pge_not_eq. apply ZExtra.Ple_Plt_Succ. assumption. } + 1: { + assert (HPle : Ple dst (RTL.max_reg_function f)) + by (eapply RTL.max_reg_function_def; eauto). + rewrite Pcompare_eq_Gt in *. + xomega. + } - 2: { assert (HPle : Ple dst (RTL.max_reg_function f)). - eapply RTL.max_reg_function_def. eassumption. auto. - apply ZExtra.Pge_not_eq. apply ZExtra.Ple_Plt_Succ. assumption. } + 2: { + assert (HPle : Ple dst (RTL.max_reg_function f)) + by (eapply RTL.max_reg_function_def; eauto). + rewrite Pcompare_eq_Gt in *. + xomega. + } (** Match assocmaps *) apply regs_lessdef_add_match; big_tac. @@ -1502,23 +2045,30 @@ Section CORRECTNESS. (Integers.Ptrofs.repr 4)))). exploit H9; big_tac. + (* This should have been solved somewhere above here *) + match goal with + | [ |- match_assocmaps _ _ _ ] => admit + end. + (** RSBP preservation *) unfold arr_stack_based_pointers in ASBP. specialize (ASBP (Integers.Ptrofs.unsigned (Integers.Ptrofs.divu OFFSET (Integers.Ptrofs.repr 4)))). exploit ASBP; big_tac. - rewrite NORMALISE in H14. rewrite HeqOFFSET in H14. rewrite H1 in H14. assumption. + rewrite NORMALISE in H14. rewrite HeqOFFSET in H14. + inversion H22. replace (asr # r1) in *. rewrite H1 in *. assumption. + rewrite Pcompare_eq_Gt in *. constructor; simplify. rewrite AssocMap.gso. rewrite AssocMap.gso. assumption. lia. assert (HPle: Ple dst (RTL.max_reg_function f)) - by (eapply RTL.max_reg_function_def; eauto; simpl; auto). - unfold Ple in HPle. lia. + by (eapply RTL.max_reg_function_def; eauto). + xomega. rewrite AssocMap.gso. rewrite AssocMap.gso. assumption. lia. assert (HPle: Ple dst (RTL.max_reg_function f)) by (eapply RTL.max_reg_function_def; eauto; simpl; auto). - unfold Ple in HPle. lia. + xomega. + invert MARR. inv CONST. crush. @@ -1533,7 +2083,7 @@ Section CORRECTNESS. rewrite ZERO in H1. clear ZERO. rewrite Integers.Ptrofs.add_zero_l in H1. - remember i0 as OFFSET. + remember i as OFFSET. (** Modular preservation proof *) assert (Integers.Ptrofs.unsigned OFFSET mod 4 = 0) as MOD_PRESERVE. @@ -1578,18 +2128,20 @@ Section CORRECTNESS. eexists. split. eapply Smallstep.plus_one. eapply HTL.step_module; eauto. - econstructor. econstructor. econstructor. crush. - econstructor. econstructor. econstructor. econstructor. crush. + repeat econstructor. crush. + repeat econstructor. crush. all: big_tac. - 1: { assert (HPle : Ple dst (RTL.max_reg_function f)). - eapply RTL.max_reg_function_def. eassumption. auto. - apply ZExtra.Pge_not_eq. apply ZExtra.Ple_Plt_Succ. assumption. } + 1: { + assert (HPle : Ple dst (RTL.max_reg_function f)) by (eauto using RTL.max_reg_function_def). + xomega. + } - 2: { assert (HPle : Ple dst (RTL.max_reg_function f)). - eapply RTL.max_reg_function_def. eassumption. auto. - apply ZExtra.Pge_not_eq. apply ZExtra.Ple_Plt_Succ. assumption. } + 2: { + assert (HPle : Ple dst (RTL.max_reg_function f)) by (eauto using RTL.max_reg_function_def). + xomega. + } (** Match assocmaps *) apply regs_lessdef_add_match; big_tac. @@ -1622,13 +2174,8 @@ Section CORRECTNESS. unfold Ple in HPle. lia. Unshelve. - exact (Values.Vint (Int.repr 0)). - exact tt. - exact (Values.Vint (Int.repr 0)). - exact tt. - exact (Values.Vint (Int.repr 0)). - exact tt. - Qed. + all: try (exact tt); auto. + Admitted. Hint Resolve transl_iload_correct : htlproof. Lemma transl_istore_correct: @@ -1640,9 +2187,9 @@ Section CORRECTNESS. Op.eval_addressing ge sp addr (map (fun r : positive => Registers.Regmap.get r rs) args) = Some a -> Mem.storev chunk m a (Registers.Regmap.get src rs) = Some m' -> forall R1 : HTL.state, - match_states (RTL.State s f sp pc rs m) R1 -> + match_states ge (RTL.State s f sp pc rs m) R1 -> exists R2 : HTL.state, - Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ match_states (RTL.State s f sp pc' rs m') R2. + Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ match_states ge (RTL.State s f sp pc' rs m') R2. Proof. intros s f sp pc rs m chunk addr args src pc' a m' H H0 H1 R1 MSTATES. inv_state. inv_arr_access. @@ -1725,6 +2272,8 @@ Section CORRECTNESS. unfold_merge. apply AssocMap.gss. + edestruct only_main_stores; eauto. subst; constructor. + (** Equality proof *) assert (Integers.Ptrofs.repr 0 = Integers.Ptrofs.zero) as ZERO by reflexivity. @@ -1828,9 +2377,9 @@ Section CORRECTNESS. right. apply ZExtra.mod_0_bounds; try lia. apply ZLib.Z_mod_mult'. - rewrite Z2Nat.id in H15; try lia. - apply Zmult_lt_compat_r with (p := 4) in H15; try lia. - rewrite ZLib.div_mul_undo in H15; try lia. + rewrite Z2Nat.id in *; try lia. + apply Zmult_lt_compat_r with (p := 4) in H27; try lia. + rewrite ZLib.div_mul_undo in *; try lia. split; try lia. apply Z.le_trans with (m := RTL.fn_stacksize f); crush; lia. } @@ -1894,8 +2443,8 @@ Section CORRECTNESS. apply ZExtra.mod_0_bounds; try lia. apply ZLib.Z_mod_mult'. invert H11. - apply Zmult_lt_compat_r with (p := 4) in H14; try lia. - rewrite ZLib.div_mul_undo in H14; try lia. + apply Zmult_lt_compat_r with (p := 4) in H22; try lia. + rewrite ZLib.div_mul_undo in *; try lia. split; try lia. apply Z.le_trans with (m := RTL.fn_stacksize f); crush; lia. } @@ -1965,8 +2514,8 @@ Section CORRECTNESS. apply H11 in HPler1. invert HPler0; invert HPler1; try congruence. rewrite EQr0 in H13. - rewrite EQr1 in H14. - invert H13. invert H14. + rewrite EQr1 in H22. + invert H13. invert H22. clear H0. clear H8. clear H11. unfold check_address_parameter_signed in *; @@ -2026,6 +2575,8 @@ Section CORRECTNESS. unfold_merge. apply AssocMap.gss. + edestruct only_main_stores; eauto; subst; constructor. + (** Equality proof *) assert (Integers.Ptrofs.repr 0 = Integers.Ptrofs.zero) as ZERO by reflexivity. inversion MASSOC; revert HeqOFFSET; subst; clear MASSOC; intros HeqOFFSET. @@ -2094,20 +2645,20 @@ Section CORRECTNESS. erewrite combine_lookup_second. simpl. assert (Ple src (RTL.max_reg_function f)) - by (eapply RTL.max_reg_function_use; eauto; simpl; auto); - apply H14 in H15. - destruct (Registers.Regmap.get src rs) eqn:EQ_SRC; constructor; invert H15; eauto. + by (eapply RTL.max_reg_function_use; eauto; simpl; auto). + apply H22 in H27. + destruct (Registers.Regmap.get src rs) eqn:EQ_SRC; constructor; invert H27; eauto. rewrite <- array_set_len. unfold arr_repeat. crush. rewrite list_repeat_len. auto. assert (4 * ptr / 4 = Integers.Ptrofs.unsigned OFFSET / 4) by (f_equal; assumption). - rewrite Z.mul_comm in H15. - rewrite Z_div_mult in H15; try lia. - replace 4 with (Integers.Ptrofs.unsigned (Integers.Ptrofs.repr 4)) in H15 by reflexivity. - rewrite <- PtrofsExtra.divu_unsigned in H15; unfold_constants; try lia. - rewrite H15. rewrite <- offset_expr_ok_2. + rewrite Z.mul_comm in H27. + rewrite Z_div_mult in H27; try lia. + replace 4 with (Integers.Ptrofs.unsigned (Integers.Ptrofs.repr 4)) in H27 by reflexivity. + rewrite <- PtrofsExtra.divu_unsigned in H27; unfold_constants; try lia. + rewrite H27. rewrite <- offset_expr_ok_2. rewrite HeqOFFSET in *. rewrite array_get_error_set_bound. reflexivity. @@ -2128,9 +2679,9 @@ Section CORRECTNESS. right. apply ZExtra.mod_0_bounds; try lia. apply ZLib.Z_mod_mult'. - rewrite Z2Nat.id in H17; try lia. - apply Zmult_lt_compat_r with (p := 4) in H17; try lia. - rewrite ZLib.div_mul_undo in H17; try lia. + rewrite Z2Nat.id in *; try lia. + apply Zmult_lt_compat_r with (p := 4) in H29; try lia. + rewrite ZLib.div_mul_undo in H29; try lia. split; try lia. apply Z.le_trans with (m := RTL.fn_stacksize f); crush; lia. } @@ -2155,7 +2706,7 @@ Section CORRECTNESS. unfold_constants. intro. rewrite HeqOFFSET in *. - apply Z2Nat.inj_iff in H15; try lia. + apply Z2Nat.inj_iff in H27; try lia. apply Z.div_pos; try lia. apply Integers.Ptrofs.unsigned_range. apply Integers.Ptrofs.unsigned_range_2. @@ -2176,7 +2727,7 @@ Section CORRECTNESS. crush. destruct (Registers.Regmap.get src rs) eqn:EQ_SRC; try constructor. destruct (Archi.ptr64); try discriminate. - pose proof (RSBP src). rewrite EQ_SRC in H14. + pose proof (RSBP src). rewrite EQ_SRC in H22. assumption. simpl. @@ -2194,9 +2745,9 @@ Section CORRECTNESS. right. apply ZExtra.mod_0_bounds; try lia. apply ZLib.Z_mod_mult'. - invert H14. - apply Zmult_lt_compat_r with (p := 4) in H16; try lia. - rewrite ZLib.div_mul_undo in H16; try lia. + invert H22. + apply Zmult_lt_compat_r with (p := 4) in H28; try lia. + rewrite ZLib.div_mul_undo in H28; try lia. split; try lia. apply Z.le_trans with (m := RTL.fn_stacksize f); crush; lia. } @@ -2222,13 +2773,13 @@ Section CORRECTNESS. (Integers.Ptrofs.unsigned (Integers.Ptrofs.add (Integers.Ptrofs.repr 0) (Integers.Ptrofs.repr ptr))) Writable). - { pose proof H1. eapply Mem.store_valid_access_2 in H14. - exact H14. eapply Mem.store_valid_access_3. eassumption. } + { pose proof H1. eapply Mem.store_valid_access_2 in H22. + exact H22. eapply Mem.store_valid_access_3. eassumption. } pose proof (Mem.valid_access_store m AST.Mint32 sp' (Integers.Ptrofs.unsigned (Integers.Ptrofs.add (Integers.Ptrofs.repr 0) (Integers.Ptrofs.repr ptr))) v). - apply X in H14. invert H14. congruence. + apply X in H22. invert H22. congruence. constructor; simplify. unfold Verilog.merge_regs. unfold_merge. rewrite AssocMap.gso. assumption. lia. @@ -2248,7 +2799,7 @@ Section CORRECTNESS. rewrite ZERO in H1. clear ZERO. rewrite Integers.Ptrofs.add_zero_l in H1. - remember i0 as OFFSET. + remember i as OFFSET. (** Modular preservation proof *) assert (Integers.Ptrofs.unsigned OFFSET mod 4 = 0) as MOD_PRESERVE. @@ -2295,6 +2846,9 @@ Section CORRECTNESS. unfold_merge. apply AssocMap.gss. + (** Match frames *) + edestruct only_main_stores; eauto; subst; constructor. + (** Equality proof *) assert (Integers.Ptrofs.repr 0 = Integers.Ptrofs.zero) as ZERO by reflexivity. @@ -2346,7 +2900,7 @@ Section CORRECTNESS. rewrite H4. apply list_repeat_len. - remember i0 as OFFSET. + remember i as OFFSET. destruct (4 * ptr ==Z Integers.Ptrofs.unsigned OFFSET). erewrite Mem.load_store_same. @@ -2492,12 +3046,7 @@ Section CORRECTNESS. assumption. lia. Unshelve. - exact tt. - exact (Values.Vint (Int.repr 0)). - exact tt. - exact (Values.Vint (Int.repr 0)). - exact tt. - exact (Values.Vint (Int.repr 0)). + all: try (exact tt); auto. Qed. Hint Resolve transl_istore_correct : htlproof. @@ -2509,15 +3058,17 @@ Section CORRECTNESS. Op.eval_condition cond (map (fun r : positive => Registers.Regmap.get r rs) args) m = Some b -> pc' = (if b then ifso else ifnot) -> forall R1 : HTL.state, - match_states (RTL.State s f sp pc rs m) R1 -> + match_states ge (RTL.State s f sp pc rs m) R1 -> exists R2 : HTL.state, - Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ match_states (RTL.State s f sp pc' rs m) R2. + Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ match_states ge (RTL.State s f sp pc' rs m) R2. Proof. intros s f sp pc rs m cond args ifso ifnot b pc' H H0 H1 R1 MSTATE. inv_state. destruct b. - eexists. split. apply Smallstep.plus_one. - clear H33. + match goal with + | [H : Z.pos ifnot <= Int.max_unsigned |- _] => clear H + end. eapply HTL.step_module; eauto. inv CONST; assumption. inv CONST; assumption. @@ -2525,7 +3076,7 @@ Section CORRECTNESS. constructor; trivial. eapply Verilog.erun_Vternary_true; simpl; eauto. eapply eval_cond_correct; eauto. intros. - intros. eapply RTL.max_reg_function_use. apply H22. auto. + intros. eapply RTL.max_reg_function_use. eauto. auto. econstructor. auto. simpl. econstructor. constructor. unfold Verilog.merge_regs. unfold_merge. simpl. apply AssocMap.gss. @@ -2533,8 +3084,11 @@ Section CORRECTNESS. inv MARR. inv CONST. big_tac. constructor; rewrite AssocMap.gso; simplify; try assumption; lia. + - eexists. split. apply Smallstep.plus_one. - clear H32. + match goal with + | [H : Z.pos ifso <= Int.max_unsigned |- _] => clear H + end. eapply HTL.step_module; eauto. inv CONST; assumption. inv CONST; assumption. @@ -2542,7 +3096,7 @@ Section CORRECTNESS. constructor; trivial. eapply Verilog.erun_Vternary_false; simpl; eauto. eapply eval_cond_correct; eauto. intros. - intros. eapply RTL.max_reg_function_use. apply H22. auto. + intros. eapply RTL.max_reg_function_use. eauto. auto. econstructor. auto. simpl. econstructor. constructor. unfold Verilog.merge_regs. unfold_merge. simpl. apply AssocMap.gss. @@ -2563,229 +3117,14 @@ Section CORRECTNESS. Registers.Regmap.get arg rs = Values.Vint n -> list_nth_z tbl (Integers.Int.unsigned n) = Some pc' -> forall R1 : HTL.state, - match_states (RTL.State s f sp pc rs m) R1 -> + match_states ge (RTL.State s f sp pc rs m) R1 -> exists R2 : HTL.state, - Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ match_states (RTL.State s f sp pc' rs m) R2. + Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ match_states ge (RTL.State s f sp pc' rs m) R2. Proof. intros s f sp pc rs m arg tbl n pc' H H0 H1 R1 MSTATE. Hint Resolve transl_ijumptable_correct : htlproof.*) - Lemma transl_ireturn_correct: - forall (s : list RTL.stackframe) (f : RTL.function) (stk : Values.block) - (pc : positive) (rs : RTL.regset) (m : mem) (or : option Registers.reg) - (m' : mem), - (RTL.fn_code f) ! pc = Some (RTL.Ireturn or) -> - Mem.free m stk 0 (RTL.fn_stacksize f) = Some m' -> - forall R1 : HTL.state, - match_states (RTL.State s f (Values.Vptr stk Integers.Ptrofs.zero) pc rs m) R1 -> - exists R2 : HTL.state, - Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ - match_states (RTL.Returnstate s (Registers.regmap_optget or Values.Vundef rs) m') R2. - Proof. - intros s f stk pc rs m or m' H H0 R1 MSTATE. - inv_state. - - - econstructor. split. - eapply Smallstep.plus_two. - - eapply HTL.step_module; eauto. - inv CONST; assumption. - inv CONST; assumption. - constructor. - econstructor; simpl; trivial. - econstructor; simpl; trivial. - constructor. - econstructor; simpl; trivial. - constructor. - - constructor. constructor. constructor. - - unfold state_st_wf in WF; big_tac; eauto. - destruct wf1 as [HCTRL HDATA]. apply HCTRL. - apply AssocMapExt.elements_iff. eexists. - match goal with H: control ! pc = Some _ |- _ => apply H end. - - apply HTL.step_finish. - unfold Verilog.merge_regs. - unfold_merge; simpl. - rewrite AssocMap.gso. - apply AssocMap.gss. lia. - apply AssocMap.gss. - rewrite Events.E0_left. reflexivity. - - constructor; auto. - constructor. - - (* FIXME: Duplication *) - - econstructor. split. - eapply Smallstep.plus_two. - eapply HTL.step_module; eauto. - inv CONST; assumption. - inv CONST; assumption. - constructor. - econstructor; simpl; trivial. - econstructor; simpl; trivial. - constructor. constructor. constructor. - constructor. constructor. constructor. - constructor. - - unfold state_st_wf in WF; big_tac; eauto. - - destruct wf1 as [HCTRL HDATA]. apply HCTRL. - apply AssocMapExt.elements_iff. eexists. - match goal with H: control ! pc = Some _ |- _ => apply H end. - - apply HTL.step_finish. - unfold Verilog.merge_regs. - unfold_merge. - unfold_merge. - rewrite AssocMap.gso. - apply AssocMap.gss. simpl; lia. - apply AssocMap.gss. - rewrite Events.E0_left. trivial. - - constructor; auto. - - simpl. inversion MASSOC. subst. - unfold find_assocmap, AssocMapExt.get_default. rewrite AssocMap.gso. - apply H1. eapply RTL.max_reg_function_use. eauto. simpl; tauto. - assert (HPle : Ple r (RTL.max_reg_function f)). - eapply RTL.max_reg_function_use. eassumption. simpl; auto. - apply ZExtra.Ple_not_eq. apply ZExtra.Ple_Plt_Succ. assumption. - - Unshelve. - all: constructor. - Qed. - Hint Resolve transl_ireturn_correct : htlproof. - - Lemma transl_callstate_correct: - forall (s : list RTL.stackframe) (f : RTL.function) (args : list Values.val) - (m : mem) (m' : Mem.mem') (stk : Values.block), - Mem.alloc m 0 (RTL.fn_stacksize f) = (m', stk) -> - forall R1 : HTL.state, - match_states (RTL.Callstate s (AST.Internal f) args m) R1 -> - exists R2 : HTL.state, - Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ - match_states - (RTL.State s f (Values.Vptr stk Integers.Ptrofs.zero) (RTL.fn_entrypoint f) - (RTL.init_regs args (RTL.fn_params f)) m') R2. - Proof. - intros s f args m m' stk H R1 MSTATE. - - inversion MSTATE; subst. inversion TF; subst. - econstructor. split. apply Smallstep.plus_one. - eapply HTL.step_call. crush. - - apply match_state with (sp' := stk); eauto. - - all: big_tac. - - apply regs_lessdef_add_greater. unfold Plt; lia. - apply regs_lessdef_add_greater. unfold Plt; lia. - apply regs_lessdef_add_greater. unfold Plt; lia. - apply init_reg_assoc_empty. - - constructor. - - destruct (Mem.load AST.Mint32 m' stk - (Integers.Ptrofs.unsigned (Integers.Ptrofs.add - Integers.Ptrofs.zero - (Integers.Ptrofs.repr (4 * ptr))))) eqn:LOAD. - pose proof Mem.load_alloc_same as LOAD_ALLOC. - pose proof H as ALLOC. - eapply LOAD_ALLOC in ALLOC. - 2: { exact LOAD. } - ptrofs. rewrite LOAD. - rewrite ALLOC. - repeat constructor. - - ptrofs. rewrite LOAD. - repeat constructor. - - unfold reg_stack_based_pointers. intros. - unfold RTL.init_regs; crush. - destruct (RTL.fn_params f); - rewrite Registers.Regmap.gi; constructor. - - unfold arr_stack_based_pointers. intros. - crush. - destruct (Mem.load AST.Mint32 m' stk - (Integers.Ptrofs.unsigned (Integers.Ptrofs.add - Integers.Ptrofs.zero - (Integers.Ptrofs.repr (4 * ptr))))) eqn:LOAD. - pose proof Mem.load_alloc_same as LOAD_ALLOC. - pose proof H as ALLOC. - eapply LOAD_ALLOC in ALLOC. - 2: { exact LOAD. } - rewrite ALLOC. - repeat constructor. - constructor. - - Transparent Mem.alloc. (* TODO: Since there are opaque there's probably a lemma. *) - Transparent Mem.load. - Transparent Mem.store. - unfold stack_bounds. - split. - - unfold Mem.alloc in H. - invert H. - crush. - unfold Mem.load. - intros. - match goal with | |- context[if ?x then _ else _] => destruct x end; try congruence. - invert v0. unfold Mem.range_perm in H4. - unfold Mem.perm in H4. crush. - unfold Mem.perm_order' in H4. - small_tac. - exploit (H4 ptr). rewrite Integers.Ptrofs.unsigned_repr; small_tac. intros. - rewrite Maps.PMap.gss in H8. - match goal with | H8 : context[if ?x then _ else _] |- _ => destruct x eqn:EQ end; try contradiction. - crush. - apply proj_sumbool_true in H10. lia. - - unfold Mem.alloc in H. - invert H. - crush. - unfold Mem.store. - intros. - match goal with | |- context[if ?x then _ else _] => destruct x end; try congruence. - invert v0. unfold Mem.range_perm in H4. - unfold Mem.perm in H4. crush. - unfold Mem.perm_order' in H4. - small_tac. - exploit (H4 ptr). rewrite Integers.Ptrofs.unsigned_repr; small_tac. intros. - rewrite Maps.PMap.gss in H8. - match goal with | H8 : context[if ?x then _ else _] |- _ => destruct x eqn:EQ end; try contradiction. - crush. - apply proj_sumbool_true in H10. lia. - constructor. simplify. rewrite AssocMap.gss. - simplify. rewrite AssocMap.gso. apply AssocMap.gss. simplify. lia. - Opaque Mem.alloc. - Opaque Mem.load. - Opaque Mem.store. - Qed. - Hint Resolve transl_callstate_correct : htlproof. - - Lemma transl_returnstate_correct: - forall (res0 : Registers.reg) (f : RTL.function) (sp : Values.val) (pc : RTL.node) - (rs : RTL.regset) (s : list RTL.stackframe) (vres : Values.val) (m : mem) - (R1 : HTL.state), - match_states (RTL.Returnstate (RTL.Stackframe res0 f sp pc rs :: s) vres m) R1 -> - exists R2 : HTL.state, - Smallstep.plus HTL.step tge R1 Events.E0 R2 /\ - match_states (RTL.State s f sp pc (Registers.Regmap.set res0 vres rs) m) R2. - Proof. - intros res0 f sp pc rs s vres m R1 MSTATE. - inversion MSTATE. inversion MF. - Qed. - Hint Resolve transl_returnstate_correct : htlproof. - - Lemma option_inv : - forall A x y, - @Some A x = Some y -> x = y. - Proof. intros. inversion H. trivial. Qed. - Lemma main_tprog_internal : forall b, Globalenvs.Genv.find_symbol tge tprog.(AST.prog_main) = Some b -> @@ -2803,19 +3142,26 @@ Section CORRECTNESS. trivial. symmetry; eapply Linking.match_program_main; eauto. Qed. + Hint Constructors list_forall2 : htlproof. + Hint Constructors match_frames : htlproof. + Lemma transl_initial_states : forall s1 : Smallstep.state (RTL.semantics prog), Smallstep.initial_state (RTL.semantics prog) s1 -> exists s2 : Smallstep.state (HTL.semantics tprog), - Smallstep.initial_state (HTL.semantics tprog) s2 /\ match_states s1 s2. + Smallstep.initial_state (HTL.semantics tprog) s2 /\ match_states ge s1 s2. Proof. induction 1. - destruct TRANSL. unfold main_is_internal in H4. - repeat (unfold_match H4). - assert (f = AST.Internal f1). apply option_inv. - rewrite <- Heqo0. rewrite <- H1. replace b with b0. - auto. apply option_inv. rewrite <- H0. rewrite <- Heqo. - trivial. + destruct TRANSL. + unfold main_is_internal in H4. repeat (unfold_match H4). + assert (f = AST.Internal f1). + { + apply option_inv. + rewrite <- Heqo0. rewrite <- H1. replace b with b0. + auto. apply option_inv. rewrite <- H0. rewrite <- Heqo. + trivial. + } + exploit function_ptr_translated; eauto. intros [tf [A B]]. unfold transl_fundef, Errors.bind in B. @@ -2826,18 +3172,17 @@ Section CORRECTNESS. apply Heqo. symmetry; eapply Linking.match_program_main; eauto. inversion H5. econstructor; split. econstructor. - apply (Genv.init_mem_transf_partial TRANSL'); eauto. - replace (AST.prog_main tprog) with (AST.prog_main prog). - rewrite symbols_preserved; eauto. - symmetry; eapply Linking.match_program_main; eauto. - apply H6. - - constructor. - apply transl_module_correct. - assert (Some (AST.Internal x) = Some (AST.Internal m)). - replace (AST.fundef HTL.module) with (HTL.fundef). - rewrite <- H6. setoid_rewrite <- A. trivial. - trivial. inv H7. assumption. + - apply (Genv.init_mem_transf_partial TRANSL'); eauto. + - replace (AST.prog_main tprog) with (AST.prog_main prog) + by (symmetry; eapply Linking.match_program_main; eauto). + rewrite symbols_preserved; eauto. + - eauto. + - constructor; auto with htlproof. + apply transl_module_correct. + assert (Some (AST.Internal x) = Some (AST.Internal m)) as Heqm. + { rewrite <- H6. setoid_rewrite <- A. trivial. } + inv Heqm. + assumption. Qed. Hint Resolve transl_initial_states : htlproof. @@ -2845,11 +3190,13 @@ Section CORRECTNESS. forall (s1 : Smallstep.state (RTL.semantics prog)) (s2 : Smallstep.state (HTL.semantics tprog)) (r : Integers.Int.int), - match_states s1 s2 -> + match_states ge s1 s2 -> Smallstep.final_state (RTL.semantics prog) s1 r -> Smallstep.final_state (HTL.semantics tprog) s2 r. Proof. - intros. inv H0. inv H. inv H4. invert MF. constructor. reflexivity. + intros. + repeat match goal with [ H : _ |- _ ] => try inv H end. + repeat constructor; auto. Qed. Hint Resolve transl_final_states : htlproof. @@ -2857,11 +3204,12 @@ Section CORRECTNESS. forall (S1 : RTL.state) t S2, RTL.step ge S1 t S2 -> forall (R1 : HTL.state), - match_states S1 R1 -> - exists R2, Smallstep.plus HTL.step tge R1 t R2 /\ match_states S2 R2. + match_states ge S1 R1 -> + exists R2, Smallstep.plus HTL.step tge R1 t R2 /\ match_states ge S2 R2. Proof. - induction 1; eauto with htlproof; (intros; inv_state). + induction 1; eauto with htlproof; try solve [ intros; inv_state ]. Qed. + Hint Resolve transl_step_correct : htlproof. Theorem transf_program_correct: diff --git a/src/hls/HTLgenspec.v b/src/hls/HTLgenspec.v index 16bdcaf..934f3f4 100644 --- a/src/hls/HTLgenspec.v +++ b/src/hls/HTLgenspec.v @@ -21,19 +21,136 @@ Require Import Coq.micromega.Lia. Require compcert.backend.RTL. Require compcert.common.Errors. +Require compcert.common.Globalenvs. Require Import compcert.lib.Integers. Require Import compcert.lib.Maps. Require compcert.verilog.Op. Require Import vericert.common.Vericertlib. +Require Import vericert.common.ListExtra. Require Import vericert.hls.Verilog. Require Import vericert.hls.ValueInt. Require Import vericert.hls.HTL. Require Import vericert.hls.HTLgen. Require Import vericert.hls.AssocMap. +From Hammer Require Import Tactics. + +(** * Relational specification of the translation *) + +(** We now define inductive predicates that characterise the fact that the +statemachine that is created by the translation contains the correct +translations for each of the elements *) + +(** [tr_instr] describes the translation of instructions that are directly translated into a single state *) +Inductive tr_instr (fin rtrn st stk : reg) : RTL.instruction -> datapath_stmnt -> control_stmnt -> Prop := +| tr_instr_Inop : + forall n, + Z.pos n <= Int.max_unsigned -> + tr_instr fin rtrn st stk (RTL.Inop n) Vskip (state_goto st n) +| tr_instr_Iop : + forall n op args dst s s' e i, + Z.pos n <= Int.max_unsigned -> + translate_instr op args s = OK e s' i -> + tr_instr fin rtrn st stk (RTL.Iop op args dst n) (Vnonblock (Vvar dst) e) (state_goto st n) +| tr_instr_Icond : + forall n1 n2 cond args s s' i c, + Z.pos n1 <= Int.max_unsigned -> + Z.pos n2 <= Int.max_unsigned -> + translate_condition cond args s = OK c s' i -> + tr_instr fin rtrn st stk (RTL.Icond cond args n1 n2) Vskip (state_cond st c n1 n2) +| tr_instr_Iload : + forall mem addr args s s' i c dst n, + Z.pos n <= Int.max_unsigned -> + translate_arr_access mem addr args stk s = OK c s' i -> + tr_instr fin rtrn st stk (RTL.Iload mem addr args dst n) (Vnonblock (Vvar dst) c) (state_goto st n) +| tr_instr_Istore : + forall mem addr args s s' i c src n, + Z.pos n <= Int.max_unsigned -> + translate_arr_access mem addr args stk s = OK c s' i -> + tr_instr fin rtrn st stk (RTL.Istore mem addr args src n) (Vnonblock c (Vvar src)) + (state_goto st n). +(*| tr_instr_Ijumptable : + forall cexpr tbl r, + cexpr = tbl_to_case_expr st tbl -> + tr_instr fin rtrn st stk (RTL.Ijumptable r tbl) (Vskip) (Vcase (Vvar r) cexpr (Some Vskip)).*) +Hint Constructors tr_instr : htlspec. + +Inductive tr_code (ge : RTL.genv) (c : RTL.code) (pc : RTL.node) (stmnts : datapath) (trans : controllogic) + (externctrl : AssocMap.t (ident * controlsignal)) (fin rtrn st stk : reg) : RTL.instruction -> Prop := +| tr_code_single : + forall i s t, + c!pc = Some i -> + stmnts!pc = Some s -> + trans!pc = Some t -> + tr_instr fin rtrn st stk i s t -> + tr_code ge c pc stmnts trans externctrl fin rtrn st stk i +| tr_code_call : + forall sig fn args dst n, + c!pc = Some (RTL.Icall sig (inr fn) args dst n) -> + (exists fd, find_func ge fn = Some (AST.Internal fd)) -> + Z.pos n <= Int.max_unsigned -> + + (exists pc2 fn_rst fn_return fn_finish fn_params, + externctrl ! fn_rst = Some (fn, ctrl_reset) /\ + externctrl ! fn_return = Some (fn, ctrl_return) /\ + externctrl ! fn_finish = Some (fn, ctrl_finish) /\ + length args = length fn_params /\ + (forall n arg, List.nth_error args n = Some arg -> + exists r, List.nth_error fn_params n = Some r /\ + externctrl ! r = Some (fn, ctrl_param n)) /\ + Z.pos pc2 <= Int.max_unsigned /\ + stmnts!pc = Some (fork fn_rst (List.combine fn_params args)) /\ + trans!pc = Some (state_goto st pc2) /\ + stmnts!pc2 = Some (join fn_return fn_rst dst) /\ + trans!pc2 = Some (state_wait st fn_finish n)) -> + + tr_code ge c pc stmnts trans externctrl fin rtrn st stk (RTL.Icall sig (inr fn) args dst n) +| tr_code_return : + forall r, + c!pc = Some (RTL.Ireturn r) -> + + (exists pc2, + stmnts!pc = Some (do_return fin rtrn r) /\ + trans!pc = Some (state_goto st pc2) /\ + stmnts!pc2 = Some (idle fin) /\ + trans!pc2 = Some Vskip) -> + + tr_code ge c pc stmnts trans externctrl fin rtrn st stk (RTL.Ireturn r). +Hint Constructors tr_code : htlspec. + +Inductive tr_module (ge : RTL.genv) (f : RTL.function) : module -> Prop := + tr_module_intro : + forall data control fin rtrn st stk stk_len m start rst clk scldecls arrdecls externctrl wf, + m = (mkmodule f.(RTL.fn_params) + data + control + f.(RTL.fn_entrypoint) + st stk stk_len fin rtrn start rst clk scldecls arrdecls externctrl wf) -> + (forall pc i, Maps.PTree.get pc f.(RTL.fn_code) = Some i -> + tr_code ge f.(RTL.fn_code) pc data control externctrl fin rtrn st stk i) -> + stk_len = Z.to_nat (f.(RTL.fn_stacksize) / 4) -> + Z.modulo (f.(RTL.fn_stacksize)) 4 = 0 -> + 0 <= f.(RTL.fn_stacksize) < Integers.Ptrofs.modulus -> + (st > (RTL.max_reg_function f))%positive -> + (fin > st)%positive -> + (rtrn > fin)%positive -> + (stk > rtrn)%positive -> + (start > stk)%positive -> + (rst > start)%positive -> + (clk > rst)%positive -> + (forall n, (exists x, externctrl!n = Some x) -> (n > clk)%positive) -> + tr_module ge f m. +Hint Constructors tr_module : htlspec. + Hint Resolve Maps.PTree.elements_keys_norepet : htlspec. Hint Resolve Maps.PTree.elements_correct : htlspec. +Hint Resolve Maps.PTree.gss : htlspec. +Hint Resolve PTree.elements_complete : htlspec. +Hint Resolve -> Z.leb_le : htlspec. + +Hint Unfold block : htlspec. +Hint Unfold nonblock : htlspec. Remark bind_inversion: forall (A B: Type) (f: mon A) (g: A -> mon B) @@ -41,13 +158,7 @@ Remark bind_inversion: bind f g s1 = OK y s3 i -> exists x, exists s2, exists i1, exists i2, f s1 = OK x s2 i1 /\ g x s2 = OK y s3 i2. -Proof. - intros until i. unfold bind. destruct (f s1); intros. - discriminate. - exists a; exists s'; exists s. - destruct (g a s'); inv H. - exists s0; auto. -Qed. +Proof. unfold bind. sauto. Qed. Remark bind2_inversion: forall (A B C: Type) (f: mon (A*B)) (g: A -> B -> mon C) @@ -55,15 +166,12 @@ Remark bind2_inversion: bind2 f g s1 = OK z s3 i -> exists x, exists y, exists s2, exists i1, exists i2, f s1 = OK (x, y) s2 i1 /\ g x y s2 = OK z s3 i2. -Proof. - unfold bind2; intros. - exploit bind_inversion; eauto. - intros [[x y] [s2 [i1 [i2 [P Q]]]]]. simpl in Q. - exists x; exists y; exists s2; exists i1; exists i2; auto. -Qed. +Proof. sauto using bind_inversion. Qed. Ltac monadInv1 H := match type of H with + | ((match ?x with | _ => _ end) = OK _ _ _) => + destruct x eqn:?; try discriminate; try monadInv1 H | (OK _ _ _ = OK _ _ _) => inversion H; clear H; try subst | (Error _ _ = OK _ _ _) => @@ -98,6 +206,7 @@ Ltac monadInv1 H := Ltac monadInv H := match type of H with | (ret _ _ = OK _ _ _) => monadInv1 H + | (OK _ _ = OK _ _ _) => monadInv1 H | (error _ _ = OK _ _ _) => monadInv1 H | (bind ?F ?G ?S = OK ?X ?S' ?I) => monadInv1 H | (bind2 ?F ?G ?S = OK ?X ?S' ?I) => monadInv1 H @@ -119,538 +228,330 @@ Ltac monadInv H := ((progress simpl in H) || unfold F in H); monadInv1 H end. -(** * Relational specification of the translation *) - -(** We now define inductive predicates that characterise the fact that the -statemachine that is created by the translation contains the correct -translations for each of the elements *) - -Inductive tr_instr (fin rtrn st stk : reg) : RTL.instruction -> stmnt -> stmnt -> Prop := -| tr_instr_Inop : - forall n, - Z.pos n <= Int.max_unsigned -> - tr_instr fin rtrn st stk (RTL.Inop n) Vskip (state_goto st n) -| tr_instr_Iop : - forall n op args dst s s' e i, - Z.pos n <= Int.max_unsigned -> - translate_instr op args s = OK e s' i -> - tr_instr fin rtrn st stk (RTL.Iop op args dst n) (Vnonblock (Vvar dst) e) (state_goto st n) -| tr_instr_Icond : - forall n1 n2 cond args s s' i c, - Z.pos n1 <= Int.max_unsigned -> - Z.pos n2 <= Int.max_unsigned -> - translate_condition cond args s = OK c s' i -> - tr_instr fin rtrn st stk (RTL.Icond cond args n1 n2) Vskip (state_cond st c n1 n2) -| tr_instr_Ireturn_None : - tr_instr fin rtrn st stk (RTL.Ireturn None) (Vseq (block fin (Vlit (ZToValue 1%Z))) - (block rtrn (Vlit (ZToValue 0%Z)))) Vskip -| tr_instr_Ireturn_Some : - forall r, - tr_instr fin rtrn st stk (RTL.Ireturn (Some r)) - (Vseq (block fin (Vlit (ZToValue 1%Z))) (block rtrn (Vvar r))) Vskip -| tr_instr_Iload : - forall mem addr args s s' i c dst n, - Z.pos n <= Int.max_unsigned -> - translate_arr_access mem addr args stk s = OK c s' i -> - tr_instr fin rtrn st stk (RTL.Iload mem addr args dst n) (nonblock dst c) (state_goto st n) -| tr_instr_Istore : - forall mem addr args s s' i c src n, - Z.pos n <= Int.max_unsigned -> - translate_arr_access mem addr args stk s = OK c s' i -> - tr_instr fin rtrn st stk (RTL.Istore mem addr args src n) (Vnonblock c (Vvar src)) - (state_goto st n). -(*| tr_instr_Ijumptable : - forall cexpr tbl r, - cexpr = tbl_to_case_expr st tbl -> - tr_instr fin rtrn st stk (RTL.Ijumptable r tbl) (Vskip) (Vcase (Vvar r) cexpr (Some Vskip)).*) -Hint Constructors tr_instr : htlspec. - -Inductive tr_code (c : RTL.code) (pc : RTL.node) (i : RTL.instruction) (stmnts trans : PTree.t stmnt) - (fin rtrn st stk : reg) : Prop := - tr_code_intro : - forall s t, - c!pc = Some i -> - stmnts!pc = Some s -> - trans!pc = Some t -> - tr_instr fin rtrn st stk i s t -> - tr_code c pc i stmnts trans fin rtrn st stk. -Hint Constructors tr_code : htlspec. - -Inductive tr_module (f : RTL.function) : module -> Prop := - tr_module_intro : - forall data control fin rtrn st stk stk_len m start rst clk scldecls arrdecls wf1 wf2 wf3 wf4, - m = (mkmodule f.(RTL.fn_params) - data - control - f.(RTL.fn_entrypoint) - st stk stk_len fin rtrn start rst clk scldecls arrdecls None wf1 wf2 wf3 wf4) -> - (forall pc i, Maps.PTree.get pc f.(RTL.fn_code) = Some i -> - tr_code f.(RTL.fn_code) pc i data control fin rtrn st stk) -> - stk_len = Z.to_nat (f.(RTL.fn_stacksize) / 4) -> - Z.modulo (f.(RTL.fn_stacksize)) 4 = 0 -> - 0 <= f.(RTL.fn_stacksize) < Integers.Ptrofs.modulus -> - st = ((RTL.max_reg_function f) + 1)%positive -> - fin = ((RTL.max_reg_function f) + 2)%positive -> - rtrn = ((RTL.max_reg_function f) + 3)%positive -> - stk = ((RTL.max_reg_function f) + 4)%positive -> - start = ((RTL.max_reg_function f) + 5)%positive -> - rst = ((RTL.max_reg_function f) + 6)%positive -> - clk = ((RTL.max_reg_function f) + 7)%positive -> - tr_module f m. -Hint Constructors tr_module : htlspec. - -Lemma create_reg_datapath_trans : - forall sz s s' x i iop, - create_reg iop sz s = OK x s' i -> - s.(st_datapath) = s'.(st_datapath). -Proof. intros. monadInv H. trivial. Qed. -Hint Resolve create_reg_datapath_trans : htlspec. - -Lemma create_reg_controllogic_trans : - forall sz s s' x i iop, - create_reg iop sz s = OK x s' i -> - s.(st_controllogic) = s'.(st_controllogic). -Proof. intros. monadInv H. trivial. Qed. -Hint Resolve create_reg_controllogic_trans : htlspec. - -Lemma declare_reg_datapath_trans : - forall sz s s' x i iop r, - declare_reg iop r sz s = OK x s' i -> - s.(st_datapath) = s'.(st_datapath). -Proof. intros. monadInv H. trivial. Qed. -Hint Resolve create_reg_datapath_trans : htlspec. - -Lemma declare_reg_controllogic_trans : - forall sz s s' x i iop r, - declare_reg iop r sz s = OK x s' i -> - s.(st_controllogic) = s'.(st_controllogic). -Proof. intros. monadInv H. trivial. Qed. -Hint Resolve create_reg_controllogic_trans : htlspec. - -Lemma declare_reg_freshreg_trans : - forall sz s s' x i iop r, - declare_reg iop r sz s = OK x s' i -> - s.(st_freshreg) = s'.(st_freshreg). -Proof. inversion 1; auto. Qed. -Hint Resolve declare_reg_freshreg_trans : htlspec. - -Lemma create_arr_datapath_trans : - forall sz ln s s' x i iop, - create_arr iop sz ln s = OK x s' i -> - s.(st_datapath) = s'.(st_datapath). -Proof. intros. monadInv H. trivial. Qed. -Hint Resolve create_arr_datapath_trans : htlspec. - -Lemma create_arr_controllogic_trans : - forall sz ln s s' x i iop, - create_arr iop sz ln s = OK x s' i -> - s.(st_controllogic) = s'.(st_controllogic). -Proof. intros. monadInv H. trivial. Qed. -Hint Resolve create_arr_controllogic_trans : htlspec. - -Lemma get_refl_x : - forall s s' x i, - get s = OK x s' i -> - s = x. -Proof. inversion 1. trivial. Qed. -Hint Resolve get_refl_x : htlspec. - -Lemma get_refl_s : - forall s s' x i, - get s = OK x s' i -> - s = s'. -Proof. inversion 1. trivial. Qed. -Hint Resolve get_refl_s : htlspec. - -Ltac inv_incr := - repeat match goal with - | [ H: create_reg _ _ ?s = OK _ ?s' _ |- _ ] => - let H1 := fresh "H" in - assert (H1 := H); eapply create_reg_datapath_trans in H; - eapply create_reg_controllogic_trans in H1 - | [ H: create_arr _ _ _ ?s = OK _ ?s' _ |- _ ] => - let H1 := fresh "H" in - assert (H1 := H); eapply create_arr_datapath_trans in H; - eapply create_arr_controllogic_trans in H1 - | [ H: get ?s = OK _ _ _ |- _ ] => - let H1 := fresh "H" in - assert (H1 := H); apply get_refl_x in H; apply get_refl_s in H1; - subst - | [ H: st_prop _ _ |- _ ] => unfold st_prop in H; destruct H - | [ H: st_incr _ _ |- _ ] => destruct st_incr +Ltac rewrite_states := + match goal with + | [ H: ?x ?s = ?x ?s' |- _ ] => + let c1 := fresh "c" in + let c2 := fresh "c" in + learn (?x ?s) as c1; learn (?x ?s') as c2; try subst end. -Lemma collect_controllogic_trans : - forall A f l cs cs' ci, - (forall s s' x i y, f y s = OK x s' i -> s.(st_controllogic) = s'.(st_controllogic)) -> - @HTLMonadExtra.collectlist A f l cs = OK tt cs' ci -> cs.(st_controllogic) = cs'.(st_controllogic). -Proof. - induction l; intros; monadInv H0. - - trivial. - - apply H in EQ. rewrite EQ. eauto. -Qed. - -Lemma collect_datapath_trans : - forall A f l cs cs' ci, - (forall s s' x i y, f y s = OK x s' i -> s.(st_datapath) = s'.(st_datapath)) -> - @HTLMonadExtra.collectlist A f l cs = OK tt cs' ci -> cs.(st_datapath) = cs'.(st_datapath). -Proof. - induction l; intros; monadInv H0. - - trivial. - - apply H in EQ. rewrite EQ. eauto. -Qed. - -Lemma collect_freshreg_trans : - forall A f l cs cs' ci, - (forall s s' x i y, f y s = OK x s' i -> s.(st_freshreg) = s'.(st_freshreg)) -> - @HTLMonadExtra.collectlist A f l cs = OK tt cs' ci -> cs.(st_freshreg) = cs'.(st_freshreg). -Proof. - induction l; intros; monadInv H0. - - trivial. - - apply H in EQ. rewrite EQ. eauto. -Qed. - -Lemma collect_declare_controllogic_trans : - forall io n l s s' i, - HTLMonadExtra.collectlist (fun r : reg => declare_reg io r n) l s = OK tt s' i -> - s.(st_controllogic) = s'.(st_controllogic). -Proof. - intros. eapply collect_controllogic_trans; try eassumption. - intros. eapply declare_reg_controllogic_trans. simpl in H0. eassumption. -Qed. - -Lemma collect_declare_datapath_trans : - forall io n l s s' i, - HTLMonadExtra.collectlist (fun r : reg => declare_reg io r n) l s = OK tt s' i -> - s.(st_datapath) = s'.(st_datapath). -Proof. - intros. eapply collect_datapath_trans; try eassumption. - intros. eapply declare_reg_datapath_trans. simpl in H0. eassumption. -Qed. - -Lemma collect_declare_freshreg_trans : - forall io n l s s' i, - HTLMonadExtra.collectlist (fun r : reg => declare_reg io r n) l s = OK tt s' i -> - s.(st_freshreg) = s'.(st_freshreg). -Proof. - intros. eapply collect_freshreg_trans; try eassumption. - inversion 1. auto. -Qed. +Ltac saturate_incr := + repeat match goal with + | [INCR1 : st_prop ?s1 ?s2, INCR2 : st_prop ?s2 ?s3 |- _] => + let INCR3 := fresh "INCR" in + learn (st_trans s1 s2 s3 INCR1 INCR2) + end. -Ltac unfold_match H := - match type of H with - | context[match ?g with _ => _ end] => destruct g eqn:?; try discriminate +(** Used to solve goals that follow directly from a single monadic operation *) +Ltac intro_step := + match goal with + | [ H : _ = OK _ _ _ |- _ ] => solve [ monadInv H; simplify; eauto with htlspec ] end. -Lemma translate_eff_addressing_freshreg_trans : - forall op args s r s' i, - translate_eff_addressing op args s = OK r s' i -> - s.(st_freshreg) = s'.(st_freshreg). -Proof. - destruct op; intros; simpl in *; repeat (unfold_match H); inv H; auto. -Qed. -Hint Resolve translate_eff_addressing_freshreg_trans : htlspec. - -Lemma translate_comparison_freshreg_trans : - forall op args s r s' i, - translate_comparison op args s = OK r s' i -> - s.(st_freshreg) = s'.(st_freshreg). -Proof. - destruct op; intros; simpl in *; repeat (unfold_match H); inv H; auto. -Qed. -Hint Resolve translate_comparison_freshreg_trans : htlspec. +(** Used to transfer a result about one of the maps in the state from one + state to a latter one *) +Ltac trans_step s1 s2 := + saturate_incr; + match goal with + | [ INCR : st_prop s1 s2 |- _ ] => try solve [inversion INCR; crush]; destruct INCR + end; + solve [ + match goal with + | [ MAP_INCR : HTLgen.map_incr ?map _ _ |- (?map _) ! ?idx = _ ] => + destruct MAP_INCR with idx; try crush_trans; crush + end + ]. + +(* FIXME: monad_crush can be slow when there are a lot of intermediate states. *) + +(* Try to prove a goal about a state by first proving it for an earlier state and then transfering it to the final. *) +Ltac monad_crush := + match goal with + | [ finalstate : st, prevstate : st |- _] => + match goal with + | [ |- context f[finalstate]] => + let inter := context f[prevstate] in + try solve [ + match inter with + | context f[finalstate] => + let inter := context f[prevstate] in + solve [assert inter by intro_step; trans_step prevstate finalstate] + end + ]; + solve [assert inter by intro_step; trans_step prevstate finalstate] + end + end. -Lemma translate_comparisonu_freshreg_trans : - forall op args s r s' i, - translate_comparisonu op args s = OK r s' i -> - s.(st_freshreg) = s'.(st_freshreg). -Proof. - destruct op; intros; simpl in *; repeat (unfold_match H); inv H; auto. -Qed. -Hint Resolve translate_comparisonu_freshreg_trans : htlspec. +Ltac full_split := repeat match goal with [ |- _ /\ _ ] => split end. -Lemma translate_comparison_imm_freshreg_trans : - forall op args s r s' i n, - translate_comparison_imm op args n s = OK r s' i -> - s.(st_freshreg) = s'.(st_freshreg). -Proof. - destruct op; intros; simpl in *; repeat (unfold_match H); inv H; auto. -Qed. -Hint Resolve translate_comparison_imm_freshreg_trans : htlspec. +Ltac relevant_monad_inv := + multimatch goal with + | [ EQ : _ ?s = OK ?x _ _ |- context[?x] ] => monadInv EQ + | [ EQ : _ ?s = OK (?x, _) _ _ |- context[?x] ] => monadInv EQ + | [ EQ : _ ?s = OK (_, ?x) _ _ |- context[?x] ] => monadInv EQ + | [ EQ : _ ?s = OK (_, ?x) _ _ |- context[?x] ] => monadInv EQ + end. -Lemma translate_comparison_immu_freshreg_trans : - forall op args s r s' i n, - translate_comparison_immu op args n s = OK r s' i -> - s.(st_freshreg) = s'.(st_freshreg). -Proof. - destruct op; intros; simpl in *; repeat (unfold_match H); inv H; auto. -Qed. -Hint Resolve translate_comparison_immu_freshreg_trans : htlspec. +Ltac any_monad_inv := + relevant_monad_inv + + multimatch goal with + | [ EQ : _ ?s = OK _ _ _ |- _ ] => monadInv EQ + end. -Lemma translate_condition_freshreg_trans : - forall op args s r s' i, - translate_condition op args s = OK r s' i -> - s.(st_freshreg) = s'.(st_freshreg). -Proof. - destruct op; intros; simpl in *; repeat (unfold_match H); inv H; eauto with htlspec. -Qed. -Hint Resolve translate_condition_freshreg_trans : htlspec. +Ltac some_incr := + saturate_incr; + multimatch goal with + | [ INCR : st_prop _ _ |- _ ] => inversion INCR + end. -Lemma translate_instr_freshreg_trans : - forall op args s r s' i, - translate_instr op args s = OK r s' i -> - s.(st_freshreg) = s'.(st_freshreg). +Lemma helper__map_externctrl_params_args : forall args param_pairs fn s s' k i, + xmap_externctrl_params k fn args s = OK param_pairs s' i -> + snd (List.split param_pairs) = args. Proof. - destruct op; intros; simpl in *; repeat (unfold_match H); inv H; eauto with htlspec. - monadInv H1. eauto with htlspec. + induction args. + - sauto. + - intros. monadInv H. sauto. Qed. -Hint Resolve translate_instr_freshreg_trans : htlspec. -Lemma translate_arr_access_freshreg_trans : - forall mem addr args st s r s' i, - translate_arr_access mem addr args st s = OK r s' i -> - s.(st_freshreg) = s'.(st_freshreg). -Proof. - intros. unfold translate_arr_access in H. repeat (unfold_match H); inv H; eauto with htlspec. -Qed. -Hint Resolve translate_arr_access_freshreg_trans : htlspec. - -Lemma add_instr_freshreg_trans : - forall n n' st s r s' i, - add_instr n n' st s = OK r s' i -> - s.(st_freshreg) = s'.(st_freshreg). -Proof. intros. unfold add_instr in H. repeat (unfold_match H). inv H. auto. Qed. -Hint Resolve add_instr_freshreg_trans : htlspec. - -Lemma add_branch_instr_freshreg_trans : - forall n n0 n1 e s r s' i, - add_branch_instr e n n0 n1 s = OK r s' i -> - s.(st_freshreg) = s'.(st_freshreg). -Proof. intros. unfold add_branch_instr in H. repeat (unfold_match H). inv H. auto. Qed. -Hint Resolve add_branch_instr_freshreg_trans : htlspec. - -Lemma add_node_skip_freshreg_trans : - forall n1 n2 s r s' i, - add_node_skip n1 n2 s = OK r s' i -> - s.(st_freshreg) = s'.(st_freshreg). -Proof. intros. unfold add_node_skip in H. repeat (unfold_match H). inv H. auto. Qed. -Hint Resolve add_node_skip_freshreg_trans : htlspec. - -Lemma add_instr_skip_freshreg_trans : - forall n1 n2 s r s' i, - add_instr_skip n1 n2 s = OK r s' i -> - s.(st_freshreg) = s'.(st_freshreg). -Proof. intros. unfold add_instr_skip in H. repeat (unfold_match H). inv H. auto. Qed. -Hint Resolve add_instr_skip_freshreg_trans : htlspec. - -Lemma transf_instr_freshreg_trans : - forall fin ret st instr s v s' i, - transf_instr fin ret st instr s = OK v s' i -> - s.(st_freshreg) = s'.(st_freshreg). -Proof. - intros. destruct instr eqn:?. subst. unfold transf_instr in H. - destruct i0; try (monadInv H); try (unfold_match H); eauto with htlspec. - - monadInv H. apply add_instr_freshreg_trans in EQ2. apply translate_instr_freshreg_trans in EQ. - apply declare_reg_freshreg_trans in EQ1. congruence. - - monadInv H. apply add_instr_freshreg_trans in EQ2. apply translate_arr_access_freshreg_trans in EQ. - apply declare_reg_freshreg_trans in EQ1. congruence. - - monadInv H. apply add_instr_freshreg_trans in EQ0. apply translate_arr_access_freshreg_trans in EQ. congruence. - - monadInv H. apply translate_condition_freshreg_trans in EQ. apply add_branch_instr_freshreg_trans in EQ0. - congruence. - (*- inv EQ. apply add_node_skip_freshreg_trans in EQ0. congruence.*) -Qed. -Hint Resolve transf_instr_freshreg_trans : htlspec. +Lemma map_externctrl_params_args : forall args param_pairs fn s s' i, + map_externctrl_params fn args s = OK param_pairs s' i -> + snd (List.split param_pairs) = args. +Proof. sauto use: helper__map_externctrl_params_args. Qed. -Lemma collect_trans_instr_freshreg_trans : - forall fin ret st l s s' i, - HTLMonadExtra.collectlist (transf_instr fin ret st) l s = OK tt s' i -> - s.(st_freshreg) = s'.(st_freshreg). +Lemma helper__map_externctrl_params_spec : forall args n param_pairs k fn s s' i, + xmap_externctrl_params k fn args s = OK param_pairs s' i -> + (n < length args)%nat -> + exists r, (List.nth_error (fst (List.split param_pairs)) n = Some r) /\ + (s'.(st_externctrl) ! r = Some (fn, ctrl_param (n+k))). Proof. - intros. eapply collect_freshreg_trans; try eassumption. - eauto with htlspec. -Qed. - -Ltac rewrite_states := - match goal with - | [ H: ?x ?s = ?x ?s' |- _ ] => - let c1 := fresh "c" in - let c2 := fresh "c" in - remember (?x ?s) as c1; remember (?x ?s') as c2; try subst - end. - -Ltac inv_add_instr' H := - match type of H with - | ?f _ _ = OK _ _ _ => unfold f in H - | ?f _ _ _ = OK _ _ _ => unfold f in H - | ?f _ _ _ _ = OK _ _ _ => unfold f in H - | ?f _ _ _ _ _ = OK _ _ _ => unfold f in H - | ?f _ _ _ _ _ _ = OK _ _ _ => unfold f in H - end; repeat unfold_match H; inversion H. - -Ltac inv_add_instr := - match goal with - | H: (if ?c then _ else _) _ = OK _ _ _ |- _ => destruct c eqn:EQN; try discriminate; inv_add_instr - | H: context[add_instr_skip _ _ _] |- _ => - inv_add_instr' H - | H: context[add_instr_skip _ _] |- _ => - monadInv H; inv_incr; inv_add_instr - | H: context[add_instr _ _ _ _] |- _ => - inv_add_instr' H - | H: context[add_instr _ _ _] |- _ => - monadInv H; inv_incr; inv_add_instr - | H: context[add_branch_instr _ _ _ _ _] |- _ => - inv_add_instr' H - | H: context[add_branch_instr _ _ _ _] |- _ => - monadInv H; inv_incr; inv_add_instr - | H: context[add_node_skip _ _ _] |- _ => - inv_add_instr' H - | H: context[add_node_skip _ _] |- _ => - monadInv H; inv_incr; inv_add_instr - end. - -Ltac destruct_optional := - match goal with H: option ?r |- _ => destruct H end. + induction args. + - sauto use: nth_error_nil. + - intros. + monadInv H. + destruct n; simplify. + + destruct (split x0). simpl. + exists x. crush. monad_crush. + + destruct (IHargs n _ _ _ _ _ _ EQ1 ltac:(lia)). + destruct (split _). simpl in *. + eexists. replace (S (n + k))%nat with (n + S k)%nat by lia. + eassumption. + Qed. + +Lemma map_externctrl_params_spec : forall args n param_pairs fn s s' i, + map_externctrl_params fn args s = OK param_pairs s' i -> + (n < length args)%nat -> + exists r, (List.nth_error (fst (List.split param_pairs)) n = Some r) /\ + (s'.(st_externctrl) ! r = Some (fn, ctrl_param n)). +Proof. sauto use: helper__map_externctrl_params_spec. Qed. +Hint Resolve map_externctrl_params_spec : htlspec. Lemma iter_expand_instr_spec : - forall l fin rtrn stack s s' i x c, - HTLMonadExtra.collectlist (transf_instr fin rtrn stack) l s = OK x s' i -> + forall l prog fin rtrn stack s s' i x c, + HTLMonadExtra.collectlist (transf_instr (Globalenvs.Genv.globalenv prog) fin rtrn stack) l s = OK x s' i -> list_norepet (List.map fst l) -> (forall pc instr, In (pc, instr) l -> c!pc = Some instr) -> - (forall pc instr, In (pc, instr) l -> - c!pc = Some instr -> - tr_code c pc instr s'.(st_datapath) s'.(st_controllogic) fin rtrn s'.(st_st) stack). + (forall pc instr, In (pc, instr) l -> c!pc = Some instr -> + tr_code (Globalenvs.Genv.globalenv prog) c pc s'.(st_datapath) s'.(st_controllogic) s'.(st_externctrl) fin rtrn s'.(st_st) stack instr). Proof. - induction l; simpl; intros; try contradiction. - destruct a as [pc1 instr1]; simpl in *. inv H0. monadInv H. inv_incr. + (** Used to solve the simpler cases of tr_code: those involving tr_instr *) + Ltac tr_code_simple_tac := + eapply tr_code_single; + match goal with + | [ H : (?pc, _) = (?pc, ?instr) \/ In (?pc, ?instr) _ |- _ ] => + inversion H; + do 2 + match goal with + | [ H' : In (_, _) _ |- _ ] => solve [ eapply in_map with (f:=fst) in H'; contradiction ] + | [ H' : (pc, _) = (pc, instr) |- _ ] => inversion H' + end; + simplify; eauto with htlspec + end; + monad_crush. + + induction l; crush. + destruct a as [pc1 instr1]; simplify. inv H0. monadInv H. destruct (peq pc pc1). - subst. - destruct instr1 eqn:?; try discriminate; - try destruct_optional; inv_add_instr; econstructor; try assumption. - + destruct o with pc1; destruct H11; simpl in *; rewrite AssocMap.gss in H9; eauto; congruence. - + destruct o0 with pc1; destruct H11; simpl in *; rewrite AssocMap.gss in H9; eauto; congruence. - + inversion H2. inversion H9. rewrite H. apply tr_instr_Inop. - apply Z.leb_le. assumption. - eapply in_map with (f := fst) in H9. contradiction. - - + destruct o with pc1; destruct H16; simpl in *; rewrite AssocMap.gss in H14; eauto; congruence. - + destruct o0 with pc1; destruct H16; simpl in *; rewrite AssocMap.gss in H14; eauto; congruence. - + inversion H2. inversion H14. unfold nonblock. replace (st_st s4) with (st_st s2) by congruence. - econstructor. apply Z.leb_le; assumption. - apply EQ1. eapply in_map with (f := fst) in H14. contradiction. - - + destruct o with pc1; destruct H16; simpl in *; rewrite AssocMap.gss in H14; eauto; congruence. - + destruct o0 with pc1; destruct H16; simpl in *; rewrite AssocMap.gss in H14; eauto; congruence. - + inversion H2. inversion H14. rewrite <- e2. replace (st_st s2) with (st_st s0) by congruence. - econstructor. apply Z.leb_le; assumption. - apply EQ1. eapply in_map with (f := fst) in H14. contradiction. - - + destruct o with pc1; destruct H11; simpl in *; rewrite AssocMap.gss in H9; eauto; congruence. - + destruct o0 with pc1; destruct H11; simpl in *; rewrite AssocMap.gss in H9; eauto; congruence. - + destruct H2. - * inversion H2. - replace (st_st s2) with (st_st s0) by congruence. - econstructor. apply Z.leb_le; assumption. - eauto with htlspec. - * apply in_map with (f := fst) in H2. contradiction. - - + destruct o with pc1; destruct H11; simpl in *; rewrite AssocMap.gss in H9; eauto; congruence. - + destruct o0 with pc1; destruct H11; simpl in *; rewrite AssocMap.gss in H9; eauto; congruence. - + destruct H2. - * inversion H2. - replace (st_st s2) with (st_st s0) by congruence. - econstructor; try (apply Z.leb_le; apply andb_prop in EQN; apply EQN). - eauto with htlspec. - * apply in_map with (f := fst) in H2. contradiction. - - (*+ destruct o with pc1; destruct H16; simpl in *; rewrite AssocMap.gss in H14; eauto; congruence. - + destruct o0 with pc1; destruct H16; simpl in *; rewrite AssocMap.gss in H14; eauto; congruence. - + inversion H2. - * inversion H14. constructor. congruence. - * apply in_map with (f := fst) in H14. contradiction. - *) - + destruct o with pc1; destruct H11; simpl in *; rewrite AssocMap.gss in H9; eauto; congruence. - + destruct o0 with pc1; destruct H11; simpl in *; rewrite AssocMap.gss in H9; eauto; congruence. - + inversion H2. - * inversion H9. - replace (st_st s2) with (st_st s0) by congruence. - eauto with htlspec. - * apply in_map with (f := fst) in H9. contradiction. - - + destruct o with pc1; destruct H11; simpl in *; rewrite AssocMap.gss in H9; eauto; congruence. - + destruct o0 with pc1; destruct H11; simpl in *; rewrite AssocMap.gss in H9; eauto; congruence. - + inversion H2. - * inversion H9. - replace (st_st s2) with (st_st s0) by congruence. - eauto with htlspec. - * apply in_map with (f := fst) in H9. contradiction. - - - eapply IHl. apply EQ0. assumption. - destruct H2. inversion H2. subst. contradiction. - intros. specialize H1 with pc0 instr0. destruct H1. tauto. trivial. - destruct H2. inv H2. contradiction. assumption. assumption. + destruct instr1 eqn:instr_eq; + repeat destruct_match; try discriminate; try monadInv1 EQ. + + (* Inop *) tr_code_simple_tac. + + (* Iop *) tr_code_simple_tac. + + (* Iload *) tr_code_simple_tac. + + (* Istore *) tr_code_simple_tac. + + (* Icall *) + inversion H2; try solve [eapply in_map with (f:=fst) in H; contradiction]. + inversion H. + + eapply tr_code_call; eauto; crush. + + repeat (eapply ex_intro). + + repeat (apply conj). + * monad_crush. + * monad_crush. + * monad_crush. + * transitivity (length x1). + replace l0 with (snd (List.split x1)). + apply split_length_r. + eapply map_externctrl_params_args; eassumption. + auto using split_length_l. + * intros. + destruct (map_externctrl_params_args _ _ _ _ _ _ EQ1); eauto using nth_error_length. + destruct (map_externctrl_params_spec _ n0 _ _ _ _ _ EQ1); eauto using nth_error_length. + exists x8. simplify; eauto. + monad_crush. + * eapply create_state_max; eassumption. + * replace x5 with (st_freshreg s6) in * by intro_step. + replace l0 with (snd (split x1)) by + eauto using map_externctrl_params_args. + rewrite combine_split. + monad_crush. + * monad_crush. + * replace x6 with (st_freshreg s7) in * by intro_step. + replace x5 with (st_freshreg s6) in * by intro_step. + monad_crush. + * replace x4 with (st_freshreg s5) in * by intro_step. + monad_crush. + + (* Icond *) tr_code_simple_tac. + + (* Ireturn *) + inversion H2; try solve [eapply in_map with (f:=fst) in H; contradiction]. + inversion H. + eapply tr_code_return; crush; eexists; simplify; monad_crush. + - eapply IHl; eauto. + intuition crush. Qed. Hint Resolve iter_expand_instr_spec : htlspec. -Lemma create_arr_inv : forall w x y z a b c d, - create_arr w x y z = OK (a, b) c d -> - y = b /\ a = z.(st_freshreg) /\ c.(st_freshreg) = Pos.succ (z.(st_freshreg)). +Lemma map_incr_some : forall {A} map (s s' : st) idx (x : A), + (map s) ! idx = Some x -> + map_incr map s s' -> + (map s') ! idx = Some x. +Proof. intros * ? Hincr. destruct Hincr with idx; crush. Qed. +Hint Resolve map_incr_some : htlspec. + +Lemma tr_code_trans : forall ge c pc instr fin rtrn stack s s', + tr_code ge c pc (st_datapath s) (st_controllogic s) (st_externctrl s) fin rtrn (st_st s) stack instr -> + st_prop s s' -> + tr_code ge c pc (st_datapath s') (st_controllogic s') (st_externctrl s') fin rtrn (st_st s') stack instr. Proof. - inversion 1; split; auto. + intros * Htr Htrans. + destruct Htr. + + eapply tr_code_single. + * trans_step s s'. + * inversion Htrans. + destruct H6 with pc. crush. + replace ((st_datapath s') ! pc). + eassumption. + * inversion Htrans. + destruct H7 with pc. crush. + replace ((st_controllogic s') ! pc). + eassumption. + * inversion Htrans. crush. + + eapply tr_code_call; eauto with htlspec. + simplify. + inversion Htrans. + replace (st_st s'). + repeat (eapply ex_intro). + repeat (apply conj). + * eapply map_incr_some; inversion Htrans; eauto with htlspec. + * eapply map_incr_some; inversion Htrans; eauto with htlspec. + * eapply map_incr_some; inversion Htrans; eauto with htlspec. + * eassumption. + * intros. + destruct (H6 n0 ltac:(auto) ltac:(auto)) as [r [? ?]]. + eexists. split; eauto with htlspec. + * eauto with htlspec. + * eauto with htlspec. + * eauto with htlspec. + * eauto with htlspec. + * eauto with htlspec. + + eapply tr_code_return; eauto with htlspec. + inversion Htrans. + simplify. eexists. + replace (st_st s'). + repeat split; eauto with htlspec. + Unshelve. all: eauto. Qed. +Hint Resolve tr_code_trans : htlspec. -Lemma create_reg_inv : forall a b s r s' i, - create_reg a b s = OK r s' i -> - r = s.(st_freshreg) /\ s'.(st_freshreg) = Pos.succ (s.(st_freshreg)). +Lemma declare_params_freshreg_trans : forall params s s' x i, + declare_params params s = OK x s' i -> + st_freshreg s = st_freshreg s'. Proof. - inversion 1; auto. + induction params; unfold declare_params in *; intros * H. + - inv H. trivial. + - monadInv H. + transitivity (st_freshreg s0). + + monadInv EQ. auto. + + eauto. Qed. +Hint Resolve declare_params_freshreg_trans : htlspec. + +Lemma declare_params_externctrl_trans : forall params s s' x i, + declare_params params s = OK x s' i -> + st_externctrl s = st_externctrl s'. +Proof. + induction params; unfold declare_params in *; intros * H. + - inv H. trivial. + - monadInv H. + transitivity (st_externctrl s0). + + monadInv EQ. auto. + + eauto. +Qed. +Hint Resolve declare_params_freshreg_trans : htlspec. Theorem transl_module_correct : - forall f m, - transl_module f = Errors.OK m -> tr_module f m. + forall p f m, + transl_module p f = Errors.OK m -> tr_module (Globalenvs.Genv.globalenv p) f m. Proof. - intros until m. - unfold transl_module. - unfold run_mon. - destruct (transf_module f (max_state f)) eqn:?; try discriminate. - intros. inv H. + intros * H. + unfold transl_module in *. + unfold run_mon in *. + unfold_match H. + inv H. inversion s; subst. unfold transf_module in *. unfold stack_correct in *. - destruct (0 <=? RTL.fn_stacksize f) eqn:STACK_BOUND_LOW; - destruct (RTL.fn_stacksize f <? Integers.Ptrofs.modulus) eqn:STACK_BOUND_HIGH; - destruct (RTL.fn_stacksize f mod 4 =? 0) eqn:STACK_ALIGN; - crush; - monadInv Heqr. - - repeat unfold_match EQ9. monadInv EQ9. - - (* TODO: We should be able to fold this into the automation. *) - pose proof (create_arr_inv _ _ _ _ _ _ _ _ EQ0) as STK_LEN. inv STK_LEN. inv H5. - pose proof (create_reg_inv _ _ _ _ _ _ EQ) as FIN_VAL. inv FIN_VAL. - pose proof (create_reg_inv _ _ _ _ _ _ EQ1) as RET_VAL. inv RET_VAL. - destruct x3. destruct x4. - pose proof (collect_trans_instr_freshreg_trans _ _ _ _ _ _ _ EQ2) as TR_INSTR. - pose proof (collect_declare_freshreg_trans _ _ _ _ _ _ EQ3) as TR_DEC. - pose proof (create_reg_inv _ _ _ _ _ _ EQ4) as START_VAL. inv START_VAL. - pose proof (create_reg_inv _ _ _ _ _ _ EQ5) as RESET_VAL. inv RESET_VAL. - pose proof (create_reg_inv _ _ _ _ _ _ EQ6) as CLK_VAL. inv CLK_VAL. - rewrite H9 in *. rewrite H8 in *. replace (st_freshreg s4) with (st_freshreg s2) in * by congruence. - rewrite H6 in *. rewrite H7 in *. rewrite H5 in *. simpl in *. - inv_incr. - econstructor; simpl; auto; try lia. - intros. - assert (EQ3D := EQ3). - apply collect_declare_datapath_trans in EQ3. - apply collect_declare_controllogic_trans in EQ3D. - replace (st_controllogic s10) with (st_controllogic s3) by congruence. - replace (st_datapath s10) with (st_datapath s3) by congruence. - replace (st_st s10) with (st_st s3) by congruence. - eapply iter_expand_instr_spec; eauto with htlspec. - rewrite H5. rewrite H7. apply EQ2. - apply PTree.elements_complete. - eauto with htlspec. - erewrite <- collect_declare_freshreg_trans; try eassumption. - lia. + destruct_match; simplify; crush. + monadInv Heqr. + + repeat destruct_match; crush. + repeat match goal with + | [ EQ : ret _ _ = OK _ _ _ |- _ ] => monadInv EQ + | [ EQ : OK _ _ _ = OK _ _ _ |- _ ] => monadInv EQ + | [ EQ : get _ = OK _ _ _ |- _ ] => monadInv EQ + end. + + econstructor; + eauto with htlspec; + try solve [ repeat relevant_monad_inv; crush ]. + - auto_apply declare_params_freshreg_trans. + replace (st_st s'). + monadInv EQ1. + inversion INCR. + repeat match goal with + | [ H : context[st_freshreg (max_state _)] |- _ ] => unfold max_state in H; simpl in H + end. + crush. + - assert (forall n, (st_externctrl (max_state f)) ! n = None) by (simplify; eauto using AssocMap.gempty). + assert (forall n, (st_externctrl s0) ! n = None) by (erewrite <- (declare_params_externctrl_trans); eauto). + assert (forall n, (st_externctrl s1) ! n = None) by (any_monad_inv; simplify; auto). + assert (forall n, (st_externctrl s2) ! n = None) by (any_monad_inv; simplify; auto). + assert (forall n, (st_externctrl s3) ! n = None) by (any_monad_inv; simplify; auto). + assert (forall n, (st_externctrl s4) ! n = None) by (any_monad_inv; simplify; auto). + assert (forall n, (st_externctrl s5) ! n = None) by (any_monad_inv; simplify; auto). + + assert (forall n, (st_externctrl s6) ! n = None) by (any_monad_inv; simplify; auto). + assert ((st_freshreg s6) > x6)%positive by (relevant_monad_inv; simplify; crush). + + intros. + repeat match goal with + | [ H: forall (_ : positive), _ |- _ ] => specialize (H r) + end. + + enough (n >= st_freshreg s6)%positive by lia. + inversion INCR13. + auto. Qed. diff --git a/src/hls/PrintHTL.ml b/src/hls/PrintHTL.ml index a75d0ee..8608784 100644 --- a/src/hls/PrintHTL.ml +++ b/src/hls/PrintHTL.ml @@ -30,34 +30,53 @@ open VericertClflags let pstr pp = fprintf pp "%s" -let reg pp r = - fprintf pp "x%d" (P.to_int r) +let concat = String.concat "" -let rec regs pp = function - | [] -> () - | [r] -> reg pp r - | r1::rl -> fprintf pp "%a, %a" reg r1 regs rl +let rec intersperse c = function + | [] -> [] + | [x] -> [x] + | x :: xs -> x :: c :: intersperse c xs + +let register a = sprintf "reg_%d" (P.to_int a) +let registers a = String.concat "" (intersperse ", " (List.map register a)) let print_instruction pp (pc, i) = fprintf pp "%5d:\t%s" pc (pprint_stmnt 0 i) +let string_controlsignal = function + | Coq_ctrl_finish -> "finish" + | Coq_ctrl_return -> "return" + | Coq_ctrl_start -> "start" + | Coq_ctrl_reset -> "rst" + | Coq_ctrl_clk -> "clk" + | Coq_ctrl_param idx -> sprintf "param_%d" (Nat.to_int idx) + +let print_externctrl pp ((local_reg : reg), ((target_mod: ident), (target_reg: controlsignal))) = + fprintf pp "%s -> %s.%s\n" (register local_reg) (extern_atom target_mod) (string_controlsignal target_reg) + +let ptree_to_list ptree = + List.sort + (fun (pc1, _) (pc2, _) -> compare pc2 pc1) + (List.rev_map + (fun (pc, i) -> (P.to_int pc, i)) + (PTree.elements ptree)) + let print_module pp id f = - fprintf pp "%s(%a) {\n" (extern_atom id) regs f.mod_params; - let datapath = - List.sort - (fun (pc1, _) (pc2, _) -> compare pc2 pc1) - (List.rev_map - (fun (pc, i) -> (P.to_int pc, i)) - (PTree.elements f.mod_datapath)) in - let controllogic = - List.sort - (fun (pc1, _) (pc2, _) -> compare pc2 pc1) - (List.rev_map - (fun (pc, i) -> (P.to_int pc, i)) - (PTree.elements f.mod_controllogic)) in - fprintf pp " datapath {\n"; + fprintf pp "%s(%s) {\n" (extern_atom id) (registers f.mod_params); + + let externctrl = PTree.elements f.mod_externctrl in + let datapath = ptree_to_list f.mod_datapath in + let controllogic = ptree_to_list f.mod_controllogic in + + fprintf pp "externctrl {\n"; + List.iter (print_externctrl pp) externctrl; + fprintf pp " }\n\n"; + + fprintf pp "datapath {\n"; List.iter (print_instruction pp) datapath; - fprintf pp " }\n\n controllogic {\n"; + fprintf pp " }\n\n"; + + fprintf pp "controllogic {\n"; List.iter (print_instruction pp) controllogic; fprintf pp " }\n}\n\n" @@ -71,10 +90,10 @@ let print_program pp prog = let destination : string option ref = ref None -let print_if prog = +let print_if passno prog = match !destination with | None -> () | Some f -> - let oc = open_out f in - print_program oc prog; - close_out oc + let oc = open_out (f ^ "." ^ Z.to_string passno) in + print_program oc prog; + close_out oc diff --git a/src/hls/PrintVerilog.mli b/src/hls/PrintVerilog.mli index 6a15ee9..dbb8ba0 100644 --- a/src/hls/PrintVerilog.mli +++ b/src/hls/PrintVerilog.mli @@ -18,6 +18,8 @@ val pprint_stmnt : int -> Verilog.stmnt -> string +val pprint_expr : Verilog.expr -> string + val print_value : out_channel -> ValueInt.value -> unit val print_program : bool -> out_channel -> Verilog.program -> unit diff --git a/src/hls/Renaming.v b/src/hls/Renaming.v new file mode 100644 index 0000000..b9fbcaa --- /dev/null +++ b/src/hls/Renaming.v @@ -0,0 +1,231 @@ +Require Import compcert.common.AST. + +Require Import vericert.hls.HTL. +Require Import vericert.hls.Verilog. +Require Import vericert.hls.AssocMap. + +Require Import vericert.common.Statemonad. +Require Import vericert.common.Vericertlib. +Require Import vericert.common.Maps. + +Record renumber_state: Type := + mk_renumber_state { + renumber_freshreg : reg; + renumber_regmap : PTree.t reg; + }. + +Module RenumberState <: State. + Definition st := renumber_state. + + Definition st_prop (st1 st2 : st) := True. + Hint Unfold st_prop : htl_renumber. + + Lemma st_refl : forall (s : st), st_prop s s. + Proof. constructor. Qed. + + Lemma st_trans : forall s1 s2 s3, st_prop s1 s2 -> st_prop s2 s3 -> st_prop s1 s3. + Proof. constructor. Qed. +End RenumberState. + +Module RenumberMonad := Statemonad(RenumberState). +Module RenumberMonadExtra := Monad.MonadExtra(RenumberMonad). + +Import RenumberMonad. +Import RenumberState. +Import RenumberMonadExtra. +Import MonadNotation. + +Definition map_reg (r: reg) : mon reg := + fun st => OK + (renumber_freshreg st) + (mk_renumber_state (Pos.succ (renumber_freshreg st)) + (PTree.set r (renumber_freshreg st) (renumber_regmap st))) + ltac:(auto with htl_renumber). + +Definition clear_regmap : mon unit := + fun st => OK + tt + (mk_renumber_state (renumber_freshreg st) + (PTree.empty reg)) + ltac:(auto with htl_renumber). + +Definition renumber_reg (r : reg) : mon reg := + do st <- get; + match PTree.get r (renumber_regmap st) with + | Some reg' => ret reg' + | None => map_reg r + end. + +Fixpoint renumber_expr (expr : Verilog.expr) := + match expr with + | Vlit val => ret (Vlit val) + | Vvar reg => + do reg' <- renumber_reg reg; + ret (Vvar reg') + | Vvari reg e => + do reg' <- renumber_reg reg; + do e' <- renumber_expr e; + ret (Vvari reg' e') + | Vinputvar reg => + do reg' <- renumber_reg reg; + ret (Vvar reg') + | Vbinop op e1 e2 => + do e1' <- renumber_expr e1; + do e2' <- renumber_expr e2; + ret (Vbinop op e1' e2') + | Vunop op e => + do e' <- renumber_expr e; + ret (Vunop op e') + | Vternary e1 e2 e3 => + do e1' <- renumber_expr e1; + do e2' <- renumber_expr e2; + do e3' <- renumber_expr e3; + ret (Vternary e1' e2' e3') + | Vrange r e1 e2 => + do e1' <- renumber_expr e1; + do e2' <- renumber_expr e2; + do r' <- renumber_reg r; + ret (Vrange r e1' e2') + end. + +Fixpoint renumber_stmnt (stmnt : Verilog.stmnt) := + match stmnt with + | Vskip => ret Vskip + | Vseq s1 s2 => + do s1' <- renumber_stmnt s1; + do s2' <- renumber_stmnt s2; + ret (Vseq s1' s2') + | Vcond e s1 s2 => + do e' <- renumber_expr e; + do s1' <- renumber_stmnt s1; + do s2' <- renumber_stmnt s2; + ret (Vcond e' s1' s2') + | Vcase e cs def => + do e' <- renumber_expr e; + do cs' <- sequence (map + (fun (c : (Verilog.expr * Verilog.stmnt)) => + let (c_expr, c_stmnt) := c in + do expr' <- renumber_expr c_expr; + do stmnt' <- renumber_stmnt c_stmnt; + ret (expr', stmnt')) cs); + do def' <- match def with + | None => ret None + | Some d => do def' <- renumber_stmnt d; ret (Some def') + end; + ret (Vcase e' cs' def') + | Vblock e1 e2 => + do e1' <- renumber_expr e1; + do e2' <- renumber_expr e2; + ret (Vblock e1' e2') + | Vnonblock e1 e2 => + do e1' <- renumber_expr e1; + do e2' <- renumber_expr e2; + ret (Vnonblock e1' e2') + end. + +Fixpoint xrenumber_reg_assocmap {A} (regmap : list (reg * A)) : mon (list (reg * A)) := + match regmap with + | nil => ret nil + | (r, v) :: l => + do r' <- renumber_reg r; + do l' <- xrenumber_reg_assocmap l; + ret ((r', v) :: l') + end. + +Definition renumber_reg_assocmap {A} (regmap : AssocMap.t A) : mon (AssocMap.t A) := + do l <- xrenumber_reg_assocmap (AssocMap.elements regmap); + ret (AssocMap_Properties.of_list l). + +Definition renumber_module (m : HTL.module) : mon HTL.module := + do mod_start' <- renumber_reg (HTL.mod_start m); + do mod_reset' <- renumber_reg (HTL.mod_reset m); + do mod_clk' <- renumber_reg (HTL.mod_clk m); + do mod_finish' <- renumber_reg (HTL.mod_finish m); + do mod_return' <- renumber_reg (HTL.mod_return m); + do mod_st' <- renumber_reg (HTL.mod_st m); + do mod_stk' <- renumber_reg (HTL.mod_stk m); + do mod_params' <- traverselist renumber_reg (HTL.mod_params m); + do mod_controllogic' <- traverse_ptree1 renumber_stmnt (HTL.mod_controllogic m); + do mod_datapath' <- traverse_ptree1 renumber_stmnt (HTL.mod_datapath m); + + do mod_scldecls' <- renumber_reg_assocmap (HTL.mod_scldecls m); + do mod_arrdecls' <- renumber_reg_assocmap (HTL.mod_arrdecls m); + do mod_externctrl' <- renumber_reg_assocmap (HTL.mod_externctrl m); + + do _ <- clear_regmap; + + match zle (Z.pos (max_pc_map mod_datapath')) Integers.Int.max_unsigned, + zle (Z.pos (max_pc_map mod_controllogic')) Integers.Int.max_unsigned with + | left LEDATA, left LECTRL => + ret (HTL.mkmodule + mod_params' + mod_datapath' + mod_controllogic' + (HTL.mod_entrypoint m) + mod_st' + mod_stk' + (HTL.mod_stk_len m) + mod_finish' + mod_return' + mod_start' + mod_reset' + mod_clk' + mod_scldecls' + mod_arrdecls' + mod_externctrl' + (conj (max_pc_wf _ _ LECTRL) (max_pc_wf _ _ LEDATA))) + | _, _ => error (Errors.msg "More than 2^32 states.") + end. + +Definition renumber_fundef (fundef : HTL.fundef) : mon HTL.fundef := + match fundef with + | Internal m => do renumbered <- renumber_module m; ret (Internal renumbered) + | _ => ret fundef + end. + +Section TRANSF_PROGRAM_STATEFUL. + Import RenumberMonad. + Import RenumberState. + Import RenumberMonadExtra. + Import MonadNotation. + + Variables A B V : Type. + Variable transf_fun: ident -> A -> RenumberMonad.mon B. + + Fixpoint transf_globdefs (l: list (ident * globdef A V)) : RenumberMonad.mon (list (ident * globdef B V)) := + match l with + | nil => RenumberMonad.ret nil + | (id, Gfun f) :: l' => + do tf <- transf_fun id f; + do tl' <- transf_globdefs l'; + RenumberMonad.ret ((id, Gfun tf) :: tl') + | (id, Gvar v) :: l' => + do tl' <- transf_globdefs l'; + RenumberMonad.ret ((id, Gvar v) :: tl') + end. + + Definition transform_stateful_program (init_state : RenumberState.st) (p: AST.program A V) : Errors.res (AST.program B V) := + RenumberMonad.run_mon init_state ( + do gl' <- transf_globdefs p.(prog_defs); + RenumberMonad.ret (mkprogram gl' p.(prog_public) p.(prog_main))). + +End TRANSF_PROGRAM_STATEFUL. + +Definition transf_program (p : HTL.program) : Errors.res HTL.program := + transform_stateful_program _ _ _ + (fun _ f => renumber_fundef f) + (mk_renumber_state 1%positive (PTree.empty reg)) + p. + +Definition match_prog : HTL.program -> HTL.program -> Prop := fun _ _ => True. + +Instance TransfRenamingLink : Linking.TransfLink match_prog. +Admitted. + +Lemma transf_program_match : forall p tp, + Renaming.transf_program p = Errors.OK tp -> match_prog p tp. +Admitted. + +Lemma transf_program_correct : forall p tp, + match_prog p tp -> Smallstep.forward_simulation (HTL.semantics p) (HTL.semantics tp). +Admitted. diff --git a/src/hls/Verilog.v b/src/hls/Verilog.v index 1dc7e99..0df8b7e 100644 --- a/src/hls/Verilog.v +++ b/src/hls/Verilog.v @@ -293,6 +293,20 @@ Definition posToLit (p : positive) : expr := Definition fext := unit. Definition fextclk := nat -> fext. +Definition map_body (f : list module_item -> list module_item) (m : module) := + mkmodule + (mod_start m) + (mod_reset m) + (mod_clk m) + (mod_finish m) + (mod_return m) + (mod_st m) + (mod_stk m) + (mod_stk_len m) + (mod_args m) + (f (mod_body m)) + (mod_entrypoint m). + (** ** State The [state] contains the following items: diff --git a/src/hls/Veriloggen.v b/src/hls/Veriloggen.v index aba2293..1ded68a 100644 --- a/src/hls/Veriloggen.v +++ b/src/hls/Veriloggen.v @@ -1,6 +1,7 @@ (* * Vericert: Verified high-level synthesis. * Copyright (C) 2020 Yann Herklotz <yann@yannherklotz.com> + * 2021 Michalis Pardalos <mpardalos@gmail.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 @@ -17,88 +18,133 @@ *) Require Import compcert.common.AST. -Require compcert.common.Errors. -Require Import compcert.lib.Maps. +Require Import compcert.common.Errors. +Require Import vericert.common.Maps. +Require Import vericert.common.Statemonad. Require Import vericert.common.Vericertlib. Require Import vericert.hls.AssocMap. Require Import vericert.hls.HTL. Require Import vericert.hls.ValueInt. Require Import vericert.hls.Verilog. +Import ListNotations. -Definition transl_list_fun (a : node * Verilog.stmnt) := - let (n, stmnt) := a in - (Vlit (posToValue n), stmnt). - -Definition transl_list st := map transl_list_fun st. - -Definition scl_to_Vdecl_fun (a : reg * (option io * scl_decl)) := - match a with (r, (io, VScalar sz)) => (Vdecl io r sz) end. - -Definition scl_to_Vdecl scldecl := map scl_to_Vdecl_fun scldecl. - -Definition arr_to_Vdeclarr_fun (a : reg * (option io * arr_decl)) := - match a with (r, (io, VArray sz l)) => (Vdeclarr io r sz l) end. - -Definition arr_to_Vdeclarr arrdecl := map arr_to_Vdeclarr_fun arrdecl. - -Definition inst_ram clk ram := - Valways (Vnegedge clk) - (Vcond (Vbinop Vne (Vvar (ram_u_en ram)) (Vvar (ram_en ram))) - (Vseq (Vcond (Vvar (ram_wr_en ram)) - (Vnonblock (Vvari (ram_mem ram) (Vvar (ram_addr ram))) - (Vvar (ram_d_in ram))) - (Vnonblock (Vvar (ram_d_out ram)) - (Vvari (ram_mem ram) (Vvar (ram_addr ram))))) - (Vnonblock (Vvar (ram_en ram)) (Vvar (ram_u_en ram)))) - Vskip). - -Definition transl_module (m : HTL.module) : Verilog.module := - let case_el_ctrl := list_to_stmnt (transl_list (PTree.elements m.(mod_controllogic))) in - let case_el_data := list_to_stmnt (transl_list (PTree.elements m.(mod_datapath))) in - match m.(HTL.mod_ram) with - | Some ram => - let body := - Valways (Vposedge m.(HTL.mod_clk)) (Vcond (Vbinop Veq (Vvar m.(HTL.mod_reset)) (Vlit (ZToValue 1))) - (Vnonblock (Vvar m.(HTL.mod_st)) (Vlit (posToValue m.(HTL.mod_entrypoint)))) - (Vcase (Vvar m.(HTL.mod_st)) case_el_ctrl (Some Vskip))) - :: Valways (Vposedge m.(HTL.mod_clk)) (Vcase (Vvar m.(HTL.mod_st)) case_el_data (Some Vskip)) - :: inst_ram m.(HTL.mod_clk) ram - :: List.map Vdeclaration (arr_to_Vdeclarr (AssocMap.elements m.(mod_arrdecls)) - ++ scl_to_Vdecl (AssocMap.elements m.(mod_scldecls))) in - Verilog.mkmodule m.(HTL.mod_start) - m.(HTL.mod_reset) - m.(HTL.mod_clk) - m.(HTL.mod_finish) - m.(HTL.mod_return) - m.(HTL.mod_st) - m.(HTL.mod_stk) - m.(HTL.mod_stk_len) - m.(HTL.mod_params) - body - m.(HTL.mod_entrypoint) - | None => - let body := - Valways (Vposedge m.(HTL.mod_clk)) (Vcond (Vbinop Veq (Vvar m.(HTL.mod_reset)) (Vlit (ZToValue 1))) - (Vnonblock (Vvar m.(HTL.mod_st)) (Vlit (posToValue m.(HTL.mod_entrypoint)))) - (Vcase (Vvar m.(HTL.mod_st)) case_el_ctrl (Some Vskip))) - :: Valways (Vposedge m.(HTL.mod_clk)) (Vcase (Vvar m.(HTL.mod_st)) case_el_data (Some Vskip)) - :: List.map Vdeclaration (arr_to_Vdeclarr (AssocMap.elements m.(mod_arrdecls)) - ++ scl_to_Vdecl (AssocMap.elements m.(mod_scldecls))) in - Verilog.mkmodule m.(HTL.mod_start) - m.(HTL.mod_reset) - m.(HTL.mod_clk) - m.(HTL.mod_finish) - m.(HTL.mod_return) - m.(HTL.mod_st) - m.(HTL.mod_stk) - m.(HTL.mod_stk_len) - m.(HTL.mod_params) - body - m.(HTL.mod_entrypoint) - end. - -Definition transl_fundef := transf_fundef transl_module. - -Definition transl_program (p: HTL.program) : Verilog.program := - transform_program transl_fundef p. +Section TRANSLATE. + Local Open Scope error_monad_scope. + + Definition transl_states : list (HTL.node * HTL.datapath_stmnt) -> list (Verilog.expr * Verilog.stmnt) := + map (fun '(n, s) => (Verilog.Vlit (posToValue n), s)). + + Definition scl_to_Vdecls := + map (fun '(r, (io, Verilog.VScalar sz)) => Vdeclaration (Vdecl io r sz)). + + Definition arr_to_Vdeclarrs := + map (fun '(r, (io, Verilog.VArray sz l)) => Vdeclaration (Vdeclarr io r sz l)). + + Definition called_functions (main_name : ident) (m : HTL.module) : list ident := + (* remove duplicates *) + List.nodup Pos.eq_dec + (* Take just the module name *) + (List.map (Basics.compose fst snd) + (* Remove the main module if it's referenced *) + (List.filter (fun it => negb (Pos.eqb (fst (snd it)) main_name)) + (PTree.elements (HTL.mod_externctrl m)))). + + (** Clean up declarations for an inlined module. Make IO decls into reg, and remove the clk declaration *) + Definition clean_up_decl (clk : reg) (it : Verilog.module_item) := + match it with + | Vdeclaration (Vdecl _ reg sz) => + if Pos.eqb reg clk + then None + else Some (Vdeclaration (Vdecl None reg sz)) + | Vdeclaration (Vdeclarr (Some _) reg sz len) => + Some (Vdeclaration (Vdeclarr None reg sz len)) + | _ => Some it + end. + + Definition mod_body (m : HTL.module) := + + + (* FIXME Remove the fuel parameter (recursion limit)*) + Fixpoint transl_module (fuel : nat) (prog : HTL.program) (externclk : option reg) (m : HTL.module) : res Verilog.module := + match fuel with + | O => Error (msg "Veriloggen: transl_module recursion too deep") + | S fuel' => + let clk := match externclk with + | None => HTL.mod_clk m + | Some c => c + end in + + let inline_names := called_functions (AST.prog_main prog) m in + let modmap := prog_modmap prog in + let htl_modules := PTree.filter + (fun m _ => List.existsb (Pos.eqb m) inline_names) + modmap in + do translated_modules <- PTree.traverse (fun _ => transl_module fuel' prog (Some clk)) htl_modules; + let cleaned_modules := PTree.map1 (map_body (Option.map_option (clean_up_decl clk))) + translated_modules in + + + let case_el_ctrl := transl_states (PTree.elements (HTL.mod_controllogic m)) in + let case_el_data := transl_states (PTree.elements (HTL.mod_datapath m)) in + + let externctrl := HTL.mod_externctrl m in + + (* Only declare the clock if this is the top-level module, i.e. there is no inherited clock *) + let maybe_clk_decl := match externclk with + | None => scl_to_Vdecls [(clk, (Some Vinput, VScalar 1))] + | Some _ => [] + end in + + let local_arrdecls := PTree.filter (fun r _ => negb (PTree.contains r externctrl)) (HTL.mod_arrdecls m) in + let arr_decls := arr_to_Vdeclarrs (AssocMap.elements local_arrdecls) in + + let local_scldecls := PTree.filter (fun r _ => negb (PTree.contains r externctrl)) (HTL.mod_scldecls m) in + let scl_decls := scl_to_Vdecls (AssocMap.elements local_scldecls) in + + let body : list Verilog.module_item := + match (HTL.mod_ram m) with + | Some ram => + Valways (Vposedge clk) (Vcond (Vbinop Veq (Vvar (HTL.mod_reset m)) (Vlit (ZToValue 1))) + (Vseq + (Vnonblock (Vvar (HTL.mod_st m)) (Vlit (posToValue (HTL.mod_entrypoint m)))) + (Vnonblock (Vvar (HTL.mod_finish m)) (Vlit (ZToValue 0)))) + (Vcase (Vvar (HTL.mod_st m)) case_el_ctrl (Some Vskip))) + :: Valways (Vposedge clk) (Vcase (Vvar (HTL.mod_st m)) case_el_data (Some Vskip)) + :: inst_ram m.(HTL.mod_clk) ram + :: arr_decls + ++ scl_decls + ++ maybe_clk_decl + ++ List.flat_map Verilog.mod_body (List.map snd (PTree.elements cleaned_modules)) + | Nothing => + Valways (Vposedge clk) (Vcond (Vbinop Veq (Vvar (HTL.mod_reset m)) (Vlit (ZToValue 1))) + (Vseq + (Vnonblock (Vvar (HTL.mod_st m)) (Vlit (posToValue (HTL.mod_entrypoint m)))) + (Vnonblock (Vvar (HTL.mod_finish m)) (Vlit (ZToValue 0)))) + (Vcase (Vvar (HTL.mod_st m)) case_el_ctrl (Some Vskip))) + :: Valways (Vposedge clk) (Vcase (Vvar (HTL.mod_st m)) case_el_data (Some Vskip)) + :: arr_decls + ++ scl_decls + ++ maybe_clk_decl + ++ List.flat_map Verilog.mod_body (List.map snd (PTree.elements cleaned_modules)) + end + in + + OK (Verilog.mkmodule + (HTL.mod_start m) + (HTL.mod_reset m) + (HTL.mod_clk m) + (HTL.mod_finish m) + (HTL.mod_return m) + (HTL.mod_st m) + (HTL.mod_stk m) + (HTL.mod_stk_len m) + (HTL.mod_params m) + body + (HTL.mod_entrypoint m)) + end. + + Definition transl_fundef (prog : HTL.program) := transf_partial_fundef (transl_module 10 prog None). + Definition transl_program (prog : HTL.program) := transform_partial_program (transl_fundef prog) prog. + +End TRANSLATE. diff --git a/src/hls/Veriloggenproof.v b/src/hls/Veriloggenproof.v index b621632..c54f726 100644 --- a/src/hls/Veriloggenproof.v +++ b/src/hls/Veriloggenproof.v @@ -17,6 +17,7 @@ *) From compcert Require Import Smallstep Linking Integers Globalenvs. +From compcert Require Errors. From vericert Require HTL. From vericert Require Import Vericertlib Veriloggen Verilog ValueInt AssocMap. Require Import Lia. @@ -24,206 +25,244 @@ Require Import Lia. Local Open Scope assocmap. Definition match_prog (prog : HTL.program) (tprog : Verilog.program) := - match_program (fun cu f tf => tf = transl_fundef f) eq prog tprog. + match_program (fun cu f tf => Errors.OK tf = transl_fundef prog f) eq prog tprog. Lemma transf_program_match: - forall prog, match_prog prog (transl_program prog). + forall prog tprog, transl_program prog = Errors.OK tprog -> match_prog prog tprog. Proof. - intros. eapply match_transform_program_contextual. auto. + intros. unfold transl_program in *. eapply match_transform_partial_program_contextual; eauto. Qed. -Inductive match_stacks : list HTL.stackframe -> list stackframe -> Prop := -| match_stack : - forall res m pc reg_assoc arr_assoc hstk vstk, - match_stacks hstk vstk -> - match_stacks (HTL.Stackframe res m pc reg_assoc arr_assoc :: hstk) - (Stackframe res (transl_module m) pc - reg_assoc arr_assoc :: vstk) -| match_stack_nil : match_stacks nil nil. - -Inductive match_states : HTL.state -> state -> Prop := -| match_state : - forall m st reg_assoc arr_assoc hstk vstk, - match_stacks hstk vstk -> - match_states (HTL.State hstk m st reg_assoc arr_assoc) - (State vstk (transl_module m) st reg_assoc arr_assoc) -| match_returnstate : - forall v hstk vstk, - match_stacks hstk vstk -> - match_states (HTL.Returnstate hstk v) (Returnstate vstk v) -| match_initial_call : - forall m, - match_states (HTL.Callstate nil m nil) (Callstate nil (transl_module m) nil). - -Lemma Vlit_inj : - forall a b, Vlit a = Vlit b -> a = b. -Proof. inversion 1. trivial. Qed. - -Lemma posToValue_inj : - forall a b, - 0 <= Z.pos a <= Int.max_unsigned -> - 0 <= Z.pos b <= Int.max_unsigned -> - posToValue a = posToValue b -> - a = b. -Proof. - intros. rewrite <- Pos2Z.id at 1. rewrite <- Pos2Z.id. - rewrite <- Int.unsigned_repr at 1; try assumption. - symmetry. - rewrite <- Int.unsigned_repr at 1; try assumption. - unfold posToValue in *. rewrite H1; auto. -Qed. - -Lemma valueToPos_inj : - forall a b, - 0 < Int.unsigned a -> - 0 < Int.unsigned b -> - valueToPos a = valueToPos b -> - a = b. -Proof. - intros. unfold valueToPos in *. - rewrite <- Int.repr_unsigned at 1. - rewrite <- Int.repr_unsigned. - apply Pos2Z.inj_iff in H1. - rewrite Z2Pos.id in H1; auto. - rewrite Z2Pos.id in H1; auto. - rewrite H1. auto. -Qed. - -Lemma unsigned_posToValue_le : - forall p, - Z.pos p <= Int.max_unsigned -> - 0 < Int.unsigned (posToValue p). -Proof. - intros. unfold posToValue. rewrite Int.unsigned_repr; lia. -Qed. - -Lemma transl_list_fun_fst : - forall p1 p2 a b, - 0 <= Z.pos p1 <= Int.max_unsigned -> - 0 <= Z.pos p2 <= Int.max_unsigned -> - transl_list_fun (p1, a) = transl_list_fun (p2, b) -> - (p1, a) = (p2, b). -Proof. - intros. unfold transl_list_fun in H1. apply pair_equal_spec in H1. - destruct H1. rewrite H2. apply Vlit_inj in H1. - apply posToValue_inj in H1; try assumption. - rewrite H1; auto. -Qed. - -Lemma Zle_relax : - forall p q r, - p < q <= r -> - p <= q <= r. -Proof. lia. Qed. -Hint Resolve Zle_relax : verilogproof. - -Lemma transl_in : - forall l p, - 0 <= Z.pos p <= Int.max_unsigned -> - (forall p0, In p0 (List.map fst l) -> 0 < Z.pos p0 <= Int.max_unsigned) -> - In (Vlit (posToValue p)) (map fst (map transl_list_fun l)) -> - In p (map fst l). -Proof. - induction l. - - simplify. auto. - - intros. destruct a. simplify. destruct (peq p0 p); auto. - right. inv H1. apply Vlit_inj in H. apply posToValue_inj in H; auto. contradiction. - auto with verilogproof. - apply IHl; auto. -Qed. - -Lemma transl_notin : - forall l p, - 0 <= Z.pos p <= Int.max_unsigned -> - (forall p0, In p0 (List.map fst l) -> 0 < Z.pos p0 <= Int.max_unsigned) -> - ~ In p (List.map fst l) -> ~ In (Vlit (posToValue p)) (List.map fst (transl_list l)). -Proof. - induction l; auto. intros. destruct a. unfold not in *. intros. - simplify. - destruct (peq p0 p). apply H1. auto. apply H1. - unfold transl_list in *. inv H2. apply Vlit_inj in H. apply posToValue_inj in H. - contradiction. - auto with verilogproof. auto. - right. apply transl_in; auto. -Qed. - -Lemma transl_norepet : - forall l, - (forall p0, In p0 (List.map fst l) -> 0 < Z.pos p0 <= Int.max_unsigned) -> - list_norepet (List.map fst l) -> list_norepet (List.map fst (transl_list l)). -Proof. - induction l. - - intros. simpl. apply list_norepet_nil. - - destruct a. intros. simpl. apply list_norepet_cons. - inv H0. apply transl_notin. apply Zle_relax. apply H. simplify; auto. - intros. apply H. destruct (peq p0 p); subst; simplify; auto. - assumption. apply IHl. intros. apply H. destruct (peq p0 p); subst; simplify; auto. - simplify. inv H0. assumption. -Qed. - -Lemma transl_list_correct : - forall l v ev f asr asa asrn asan asr' asa' asrn' asan', - (forall p0, In p0 (List.map fst l) -> 0 < Z.pos p0 <= Int.max_unsigned) -> - list_norepet (List.map fst l) -> - asr!ev = Some v -> - (forall p s, - In (p, s) l -> - v = posToValue p -> - stmnt_runp f - {| assoc_blocking := asr; assoc_nonblocking := asrn |} - {| assoc_blocking := asa; assoc_nonblocking := asan |} - s - {| assoc_blocking := asr'; assoc_nonblocking := asrn' |} - {| assoc_blocking := asa'; assoc_nonblocking := asan' |} -> - stmnt_runp f - {| assoc_blocking := asr; assoc_nonblocking := asrn |} - {| assoc_blocking := asa; assoc_nonblocking := asan |} - (Vcase (Vvar ev) (list_to_stmnt (transl_list l)) (Some Vskip)) - {| assoc_blocking := asr'; assoc_nonblocking := asrn' |} - {| assoc_blocking := asa'; assoc_nonblocking := asan' |}). -Proof. - induction l as [| a l IHl]. - - contradiction. - - intros v ev f asr asa asrn asan asr' asa' asrn' asan' BOUND NOREP ASSOC p s IN EQ SRUN. - destruct a as [p' s']. simplify. - destruct (peq p p'); subst. eapply stmnt_runp_Vcase_match. - constructor. simplify. unfold AssocMap.find_assocmap, AssocMapExt.get_default. - rewrite ASSOC. trivial. constructor. auto. - inversion IN as [INV | INV]. inversion INV as [INV2]; subst. assumption. - inv NOREP. eapply in_map with (f := fst) in INV. contradiction. - - eapply stmnt_runp_Vcase_nomatch. constructor. simplify. - unfold AssocMap.find_assocmap, AssocMapExt.get_default. rewrite ASSOC. - trivial. constructor. unfold not. intros. apply n. apply posToValue_inj. - apply Zle_relax. apply BOUND. right. inv IN. inv H0; contradiction. - eapply in_map with (f := fst) in H0. auto. - apply Zle_relax. apply BOUND; auto. auto. - - eapply IHl. auto. inv NOREP. auto. eassumption. inv IN. inv H. contradiction. apply H. - trivial. assumption. -Qed. -Hint Resolve transl_list_correct : verilogproof. - -Lemma pc_wf : - forall A m p v, - (forall p0, In p0 (List.map fst (@AssocMap.elements A m)) -> 0 < Z.pos p0 <= Int.max_unsigned) -> - m!p = Some v -> - 0 <= Z.pos p <= Int.max_unsigned. -Proof. - intros A m p v LT S. apply Zle_relax. apply LT. - apply AssocMap.elements_correct in S. remember (p, v) as x. - exploit in_map. apply S. instantiate (1 := fst). subst. simplify. auto. -Qed. - -Lemma mis_stepp_decl : - forall l asr asa f, - mis_stepp f asr asa (map Vdeclaration l) asr asa. -Proof. - induction l. - - intros. constructor. - - intros. simplify. econstructor. constructor. auto. -Qed. -Hint Resolve mis_stepp_decl : verilogproof. +Instance TransfVerilogLink : TransfLink Veriloggenproof.match_prog. +Admitted. + +(* Inductive match_stacks : list HTL.stackframe -> list stackframe -> Prop := *) +(* | match_stack : *) +(* forall res m pc reg_assoc arr_assoc hstk vstk, *) +(* match_stacks hstk vstk -> *) +(* match_stacks (HTL.Stackframe res m pc reg_assoc arr_assoc :: hstk) *) +(* (Stackframe res (transl_module m) pc *) +(* reg_assoc arr_assoc :: vstk) *) +(* | match_stack_nil : match_stacks nil nil. *) + +(* Inductive match_states : HTL.state -> state -> Prop := *) +(* | match_state : *) +(* forall m st reg_assoc arr_assoc hstk vstk, *) +(* match_stacks hstk vstk -> *) +(* match_states (HTL.State hstk m st reg_assoc arr_assoc) *) +(* (State vstk (transl_module m) st reg_assoc arr_assoc) *) +(* | match_returnstate : *) +(* forall v hstk vstk, *) +(* match_stacks hstk vstk -> *) +(* match_states (HTL.Returnstate hstk v) (Returnstate vstk v) *) +(* | match_initial_call : *) +(* forall m, *) +(* match_states (HTL.Callstate nil m nil) (Callstate nil (transl_module m) nil). *) + +(* Lemma Vlit_inj : *) +(* forall a b, Vlit a = Vlit b -> a = b. *) +(* Proof. inversion 1. trivial. Qed. *) + +(* Lemma posToValue_inj : *) +(* forall a b, *) +(* 0 <= Z.pos a <= Int.max_unsigned -> *) +(* 0 <= Z.pos b <= Int.max_unsigned -> *) +(* posToValue a = posToValue b -> *) +(* a = b. *) +(* Proof. *) +(* intros. rewrite <- Pos2Z.id at 1. rewrite <- Pos2Z.id. *) +(* rewrite <- Int.unsigned_repr at 1; try assumption. *) +(* symmetry. *) +(* rewrite <- Int.unsigned_repr at 1; try assumption. *) +(* unfold posToValue in *. rewrite H1; auto. *) +(* Qed. *) + +(* Lemma valueToPos_inj : *) +(* forall a b, *) +(* 0 < Int.unsigned a -> *) +(* 0 < Int.unsigned b -> *) +(* valueToPos a = valueToPos b -> *) +(* a = b. *) +(* Proof. *) +(* intros. unfold valueToPos in *. *) +(* rewrite <- Int.repr_unsigned at 1. *) +(* rewrite <- Int.repr_unsigned. *) +(* apply Pos2Z.inj_iff in H1. *) +(* rewrite Z2Pos.id in H1; auto. *) +(* rewrite Z2Pos.id in H1; auto. *) +(* rewrite H1. auto. *) +(* Qed. *) + +(* Lemma unsigned_posToValue_le : *) +(* forall p, *) +(* Z.pos p <= Int.max_unsigned -> *) +(* 0 < Int.unsigned (posToValue p). *) +(* Proof. *) +(* intros. unfold posToValue. rewrite Int.unsigned_repr; lia. *) +(* Qed. *) + +(* Lemma transl_ctrl_fun_fst : *) +(* forall p1 p2 a b, *) +(* 0 <= Z.pos p1 <= Int.max_unsigned -> *) +(* 0 <= Z.pos p2 <= Int.max_unsigned -> *) +(* transl_ctrl_fun (p1, a) = transl_ctrl_fun (p2, b) -> *) +(* (p1, a) = (p2, b). *) +(* Proof. *) +(* intros. unfold transl_ctrl_fun in H1. apply pair_equal_spec in H1. *) +(* destruct H1. rewrite H2. apply Vlit_inj in H1. *) +(* apply posToValue_inj in H1; try assumption. *) +(* rewrite H1; auto. *) +(* Qed. *) + +(* Lemma transl_data_fun_fst : *) +(* forall p1 p2 a b, *) +(* 0 <= Z.pos p1 <= Int.max_unsigned -> *) +(* 0 <= Z.pos p2 <= Int.max_unsigned -> *) +(* transl_datapath_fun (p1, a) = transl_datapath_fun (p2, b) -> *) +(* p1 = p2. *) +(* Proof. *) +(* intros. *) +(* unfold transl_datapath_fun in H1. apply pair_equal_spec in H1. destruct H1. *) +(* apply Vlit_inj in H1. apply posToValue_inj in H1; assumption. *) +(* Qed. *) + +(* Lemma Zle_relax : *) +(* forall p q r, *) +(* p < q <= r -> *) +(* p <= q <= r. *) +(* Proof. lia. Qed. *) +(* Hint Resolve Zle_relax : verilogproof. *) + +(* Lemma transl_in : *) +(* forall l p, *) +(* 0 <= Z.pos p <= Int.max_unsigned -> *) +(* (forall p0, In p0 (List.map fst l) -> 0 < Z.pos p0 <= Int.max_unsigned) -> *) +(* In (Vlit (posToValue p)) (map fst (map transl_ctrl_fun l)) -> *) +(* In p (map fst l). *) +(* Proof. *) +(* induction l. *) +(* - simplify. auto. *) +(* - intros. destruct a. simplify. destruct (peq p0 p); auto. *) +(* right. inv H1. apply Vlit_inj in H. apply posToValue_inj in H; auto. contradiction. *) +(* auto with verilogproof. *) +(* apply IHl; auto. *) +(* Qed. *) + +(* Lemma transl_notin : *) +(* forall l p, *) +(* 0 <= Z.pos p <= Int.max_unsigned -> *) +(* (forall p0, In p0 (List.map fst l) -> 0 < Z.pos p0 <= Int.max_unsigned) -> *) +(* ~ In p (List.map fst l) -> ~ In (Vlit (posToValue p)) (List.map fst (transl_ctrl l)). *) +(* Proof. *) +(* induction l; auto. intros. destruct a. unfold not in *. intros. *) +(* simplify. *) +(* destruct (peq p0 p). apply H1. auto. apply H1. *) +(* unfold transl_ctrl in *. inv H2. apply Vlit_inj in H. apply posToValue_inj in H. *) +(* contradiction. *) +(* auto with verilogproof. auto. *) +(* right. apply transl_in; auto. *) +(* Qed. *) + +(* Lemma transl_norepet : *) +(* forall l, *) +(* (forall p0, In p0 (List.map fst l) -> 0 < Z.pos p0 <= Int.max_unsigned) -> *) +(* list_norepet (List.map fst l) -> list_norepet (List.map fst (transl_ctrl l)). *) +(* Proof. *) +(* induction l. *) +(* - intros. simpl. apply list_norepet_nil. *) +(* - destruct a. intros. simpl. apply list_norepet_cons. *) +(* inv H0. apply transl_notin. apply Zle_relax. apply H. simplify; auto. *) +(* intros. apply H. destruct (peq p0 p); subst; simplify; auto. *) +(* assumption. apply IHl. intros. apply H. destruct (peq p0 p); subst; simplify; auto. *) +(* simplify. inv H0. assumption. *) +(* Qed. *) + +(* Lemma transl_ctrl_correct : *) +(* forall l v ev f asr asa asrn asan asr' asa' asrn' asan', *) +(* (forall p0, In p0 (List.map fst l) -> 0 < Z.pos p0 <= Int.max_unsigned) -> *) +(* list_norepet (List.map fst l) -> *) +(* asr!ev = Some v -> *) +(* (forall p s, *) +(* In (p, s) l -> *) +(* v = posToValue p -> *) +(* stmnt_runp f *) +(* {| assoc_blocking := asr; assoc_nonblocking := asrn |} *) +(* {| assoc_blocking := asa; assoc_nonblocking := asan |} *) +(* s *) +(* {| assoc_blocking := asr'; assoc_nonblocking := asrn' |} *) +(* {| assoc_blocking := asa'; assoc_nonblocking := asan' |} -> *) +(* stmnt_runp f *) +(* {| assoc_blocking := asr; assoc_nonblocking := asrn |} *) +(* {| assoc_blocking := asa; assoc_nonblocking := asan |} *) +(* (Vcase (Vvar ev) (transl_ctrl l) (Some Vskip)) *) +(* {| assoc_blocking := asr'; assoc_nonblocking := asrn' |} *) +(* {| assoc_blocking := asa'; assoc_nonblocking := asan' |}). *) +(* Proof. *) +(* induction l as [| a l IHl]. *) +(* - contradiction. *) +(* - intros v ev f asr asa asrn asan asr' asa' asrn' asan' BOUND NOREP ASSOC p s IN EQ SRUN. *) +(* destruct a as [p' s']. simplify. *) +(* destruct (peq p p'); subst. eapply stmnt_runp_Vcase_match. *) +(* constructor. simplify. unfold AssocMap.find_assocmap, AssocMapExt.get_default. *) +(* rewrite ASSOC. trivial. constructor. auto. *) +(* inversion IN as [INV | INV]. inversion INV as [INV2]; subst. assumption. *) +(* inv NOREP. eapply in_map with (f := fst) in INV. contradiction. *) + +(* eapply stmnt_runp_Vcase_nomatch. constructor. simplify. *) +(* unfold AssocMap.find_assocmap, AssocMapExt.get_default. rewrite ASSOC. *) +(* trivial. constructor. unfold not. intros. apply n. apply posToValue_inj. *) +(* apply Zle_relax. apply BOUND. right. inv IN. inv H0; contradiction. *) +(* eapply in_map with (f := fst) in H0. auto. *) +(* apply Zle_relax. apply BOUND; auto. auto. *) + +(* eapply IHl. auto. inv NOREP. auto. eassumption. inv IN. inv H. contradiction. apply H. *) +(* trivial. assumption. *) +(* Qed. *) +(* Hint Resolve transl_ctrl_correct : verilogproof. *) + +(* (* FIXME Probably wrong we probably need some statemnt about datapath_statement_runp *) *) +(* Lemma transl_datapath_correct : *) +(* forall l v ev f asr asa asrn asan asr' asa' asrn' asan', *) +(* (forall p0, In p0 (List.map fst l) -> 0 < Z.pos p0 <= Int.max_unsigned) -> *) +(* list_norepet (List.map fst l) -> *) +(* asr!ev = Some v -> *) +(* (forall p s, *) +(* In (p, s) l -> *) +(* v = posToValue p -> *) +(* stmnt_runp f *) +(* {| assoc_blocking := asr; assoc_nonblocking := asrn |} *) +(* {| assoc_blocking := asa; assoc_nonblocking := asan |} *) +(* s *) +(* {| assoc_blocking := asr'; assoc_nonblocking := asrn' |} *) +(* {| assoc_blocking := asa'; assoc_nonblocking := asan' |} -> *) +(* stmnt_runp f *) +(* {| assoc_blocking := asr; assoc_nonblocking := asrn |} *) +(* {| assoc_blocking := asa; assoc_nonblocking := asan |} *) +(* (Vcase (Vvar ev) (transl_ctrl l) (Some Vskip)) *) +(* {| assoc_blocking := asr'; assoc_nonblocking := asrn' |} *) +(* {| assoc_blocking := asa'; assoc_nonblocking := asan' |}). *) +(* Proof. Admitted. *) + +(* Lemma pc_wf : *) +(* forall A m p v, *) +(* (forall p0, In p0 (List.map fst (@AssocMap.elements A m)) -> 0 < Z.pos p0 <= Int.max_unsigned) -> *) +(* m!p = Some v -> *) +(* 0 <= Z.pos p <= Int.max_unsigned. *) +(* Proof. *) +(* intros A m p v LT S. apply Zle_relax. apply LT. *) +(* apply AssocMap.elements_correct in S. remember (p, v) as x. *) +(* exploit in_map. apply S. instantiate (1 := fst). subst. simplify. auto. *) +(* Qed. *) + +(* Lemma mis_stepp_decl : *) +(* forall l asr asa f, *) +(* mis_stepp f asr asa (map Vdeclaration l) asr asa. *) +(* Proof. *) +(* induction l. *) +(* - intros. constructor. *) +(* - intros. simplify. econstructor. constructor. auto. *) +(* Qed. *) +(* Hint Resolve mis_stepp_decl : verilogproof. *) Lemma mis_stepp_negedge_decl : forall l asr asa f, @@ -350,195 +389,133 @@ Section CORRECTNESS. Proof. intros. eapply (Genv.find_symbol_match TRANSL). Qed. Hint Resolve symbols_preserved : verilogproof. - Lemma function_ptr_translated: - forall (b: Values.block) (f: HTL.fundef), - Genv.find_funct_ptr ge b = Some f -> - exists tf, - Genv.find_funct_ptr tge b = Some tf /\ transl_fundef f = tf. - Proof. - intros. exploit (Genv.find_funct_ptr_match TRANSL); eauto. - intros (cu & tf & P & Q & R); exists tf; auto. - Qed. - Hint Resolve function_ptr_translated : verilogproof. - - Lemma functions_translated: - forall (v: Values.val) (f: HTL.fundef), - Genv.find_funct ge v = Some f -> - exists tf, - Genv.find_funct tge v = Some tf /\ transl_fundef f = tf. - Proof. - intros. exploit (Genv.find_funct_match TRANSL); eauto. - intros (cu & tf & P & Q & R); exists tf; auto. - Qed. - Hint Resolve functions_translated : verilogproof. - - Lemma senv_preserved: - Senv.equiv (Genv.to_senv ge) (Genv.to_senv tge). - Proof. - intros. eapply (Genv.senv_match TRANSL). - Qed. - Hint Resolve senv_preserved : verilogproof. - - Ltac unfold_replace := - match goal with - | H: HTL.mod_ram _ = _ |- context[transl_module] => - unfold transl_module; rewrite H - end. - - Theorem transl_step_correct : - forall (S1 : HTL.state) t S2, - HTL.step ge S1 t S2 -> - forall (R1 : state), - match_states S1 R1 -> - exists R2, Smallstep.plus step tge R1 t R2 /\ match_states S2 R2. - Proof. - induction 1; intros R1 MSTATE; inv MSTATE; destruct (HTL.mod_ram m) eqn:?. - - econstructor; split. apply Smallstep.plus_one. econstructor. - unfold_replace. assumption. unfold_replace. assumption. - unfold_replace. eassumption. apply valueToPos_posToValue. - split. lia. - eapply pc_wf. intros. pose proof (HTL.mod_wf m) as HP. destruct HP as [HP _]. - split. lia. apply HP. eassumption. eassumption. - unfold_replace. - econstructor. econstructor. eapply stmnt_runp_Vcond_false. econstructor. econstructor. - simpl. unfold find_assocmap. unfold AssocMapExt.get_default. - rewrite H. trivial. - - econstructor. simpl. auto. auto. - - eapply transl_list_correct. - intros. split. lia. pose proof (HTL.mod_wf m) as HP. destruct HP as [HP _]. auto. - apply Maps.PTree.elements_keys_norepet. eassumption. - 2: { apply valueToPos_inj. apply unsigned_posToValue_le. - eapply pc_wf. intros. pose proof (HTL.mod_wf m) as HP. destruct HP as [HP _]. - split. lia. apply HP. eassumption. eassumption. - apply unsigned_posToValue_le. eapply pc_wf. intros. pose proof (HTL.mod_wf m) as HP. - destruct HP as [HP _]. - split. lia. apply HP. eassumption. eassumption. trivial. - } - apply Maps.PTree.elements_correct. eassumption. eassumption. - - econstructor. econstructor. - - eapply transl_list_correct. - intros. split. lia. pose proof (HTL.mod_wf m) as HP. destruct HP as [_ HP]. - auto. apply Maps.PTree.elements_keys_norepet. eassumption. - 2: { apply valueToPos_inj. apply unsigned_posToValue_le. - eapply pc_wf. intros. pose proof (HTL.mod_wf m) as HP. destruct HP as [HP _]. - split. lia. apply HP. eassumption. eassumption. - apply unsigned_posToValue_le. eapply pc_wf. intros. pose proof (HTL.mod_wf m) as HP. - destruct HP as [HP _]. - split. lia. apply HP. eassumption. eassumption. trivial. - } - apply Maps.PTree.elements_correct. eassumption. eassumption. - econstructor. econstructor. - apply mis_stepp_decl. simplify. unfold_replace. simplify. - econstructor. econstructor. econstructor. econstructor. - econstructor. - apply ram_exec_match. eauto. - apply mis_stepp_negedge_decl. simplify. auto. auto. - rewrite_eq. eauto. auto. - rewrite valueToPos_posToValue. econstructor. auto. - simplify; lia. - - inv H7. econstructor; split. apply Smallstep.plus_one. econstructor. - unfold_replace. assumption. unfold_replace. assumption. - unfold_replace. eassumption. apply valueToPos_posToValue. - split. lia. - eapply pc_wf. intros. pose proof (HTL.mod_wf m) as HP. destruct HP as [HP _]. - split. lia. apply HP. eassumption. eassumption. - unfold_replace. - econstructor. econstructor. eapply stmnt_runp_Vcond_false. econstructor. econstructor. - simpl. unfold find_assocmap. unfold AssocMapExt.get_default. - rewrite H. trivial. - - econstructor. simpl. auto. auto. - - eapply transl_list_correct. - intros. split. lia. pose proof (HTL.mod_wf m) as HP. destruct HP as [HP _]. auto. - apply Maps.PTree.elements_keys_norepet. eassumption. - 2: { apply valueToPos_inj. apply unsigned_posToValue_le. - eapply pc_wf. intros. pose proof (HTL.mod_wf m) as HP. destruct HP as [HP _]. - split. lia. apply HP. eassumption. eassumption. - apply unsigned_posToValue_le. eapply pc_wf. intros. pose proof (HTL.mod_wf m) as HP. - destruct HP as [HP _]. - split. lia. apply HP. eassumption. eassumption. trivial. - } - apply Maps.PTree.elements_correct. eassumption. eassumption. - - econstructor. econstructor. - - eapply transl_list_correct. - intros. split. lia. pose proof (HTL.mod_wf m) as HP. - destruct HP as [_ HP]; auto. - apply Maps.PTree.elements_keys_norepet. eassumption. - 2: { apply valueToPos_inj. apply unsigned_posToValue_le. - eapply pc_wf. intros. pose proof (HTL.mod_wf m) as HP. destruct HP as [HP _]. - split. lia. apply HP. eassumption. eassumption. - apply unsigned_posToValue_le. eapply pc_wf. intros. pose proof (HTL.mod_wf m) as HP. - destruct HP as [HP _]. - split. lia. apply HP. eassumption. eassumption. trivial. - } - apply Maps.PTree.elements_correct. eassumption. eassumption. - - apply mis_stepp_decl. simplify. - unfold_replace. - repeat econstructor. apply mis_stepp_negedge_decl. trivial. trivial. - simpl. unfold_replace. eassumption. auto. simplify. - rewrite valueToPos_posToValue. constructor; eassumption. simplify; lia. - - econstructor; split. apply Smallstep.plus_one. apply step_finish. - rewrite_eq. assumption. - rewrite_eq. eassumption. - econstructor; auto. - - econstructor; split. apply Smallstep.plus_one. apply step_finish. - unfold transl_module. rewrite Heqo. simplify. - assumption. unfold_replace. eassumption. - constructor; assumption. - - econstructor; split. apply Smallstep.plus_one. constructor. - repeat rewrite_eq. constructor. constructor. - - econstructor; split. apply Smallstep.plus_one. constructor. - repeat rewrite_eq. constructor. constructor. - - inv H3. econstructor; split. apply Smallstep.plus_one. constructor. trivial. - repeat rewrite_eq. apply match_state. assumption. - - inv H3. econstructor; split. apply Smallstep.plus_one. constructor. trivial. - repeat rewrite_eq. apply match_state. assumption. - Qed. - Hint Resolve transl_step_correct : verilogproof. - - Lemma transl_initial_states : - forall s1 : Smallstep.state (HTL.semantics prog), - Smallstep.initial_state (HTL.semantics prog) s1 -> - exists s2 : Smallstep.state (Verilog.semantics tprog), - Smallstep.initial_state (Verilog.semantics tprog) s2 /\ match_states s1 s2. - Proof. - induction 1. - econstructor; split. econstructor. - apply (Genv.init_mem_transf TRANSL); eauto. - rewrite symbols_preserved. - replace (AST.prog_main tprog) with (AST.prog_main prog); eauto. - symmetry; eapply Linking.match_program_main; eauto. - exploit function_ptr_translated; eauto. intros [tf [A B]]. - inv B. eauto. - constructor. - Qed. - Hint Resolve transl_initial_states : verilogproof. - - Lemma transl_final_states : - forall (s1 : Smallstep.state (HTL.semantics prog)) - (s2 : Smallstep.state (Verilog.semantics tprog)) - (r : Integers.Int.int), - match_states s1 s2 -> - Smallstep.final_state (HTL.semantics prog) s1 r -> - Smallstep.final_state (Verilog.semantics tprog) s2 r. - Proof. - intros. inv H0. inv H. inv H3. constructor. reflexivity. - Qed. - Hint Resolve transl_final_states : verilogproof. +(* Lemma function_ptr_translated: *) +(* forall (b: Values.block) (f: HTL.fundef), *) +(* Genv.find_funct_ptr ge b = Some f -> *) +(* exists tf, *) +(* Genv.find_funct_ptr tge b = Some tf /\ transl_fundef f = tf. *) +(* Proof. *) +(* intros. exploit (Genv.find_funct_ptr_match TRANSL); eauto. *) +(* intros (cu & tf & P & Q & R); exists tf; auto. *) +(* Qed. *) +(* Hint Resolve function_ptr_translated : verilogproof. *) + +(* Lemma functions_translated: *) +(* forall (v: Values.val) (f: HTL.fundef), *) +(* Genv.find_funct ge v = Some f -> *) +(* exists tf, *) +(* Genv.find_funct tge v = Some tf /\ transl_fundef f = tf. *) +(* Proof. *) +(* intros. exploit (Genv.find_funct_match TRANSL); eauto. *) +(* intros (cu & tf & P & Q & R); exists tf; auto. *) +(* Qed. *) +(* Hint Resolve functions_translated : verilogproof. *) + +(* Lemma senv_preserved: *) +(* Senv.equiv (Genv.to_senv ge) (Genv.to_senv tge). *) +(* Proof. *) +(* intros. eapply (Genv.senv_match TRANSL). *) +(* Qed. *) +(* Hint Resolve senv_preserved : verilogproof. *) + +(* Theorem transl_step_correct : *) +(* forall (S1 : HTL.state) t S2, *) +(* HTL.step ge S1 t S2 -> *) +(* forall (R1 : state), *) +(* match_states S1 R1 -> *) +(* exists R2, Smallstep.plus step tge R1 t R2 /\ match_states S2 R2. *) +(* Proof. *) +(* induction 1; intros R1 MSTATE; inv MSTATE. *) +(* - econstructor; split. apply Smallstep.plus_one. econstructor. *) +(* assumption. assumption. eassumption. apply valueToPos_posToValue. *) +(* split. lia. *) +(* eapply pc_wf. intros. pose proof (HTL.mod_wf m) as HP. destruct HP as [HP _]. *) +(* split. lia. apply HP. eassumption. eassumption. *) +(* econstructor. econstructor. eapply stmnt_runp_Vcond_false. econstructor. econstructor. *) +(* simpl. unfold find_assocmap. unfold AssocMapExt.get_default. *) +(* rewrite H. trivial. *) + +(* econstructor. simpl. auto. auto. *) + +(* eapply transl_ctrl_correct. *) +(* intros. split. lia. pose proof (HTL.mod_wf m) as HP. destruct HP as [HP _]. auto. *) +(* apply Maps.PTree.elements_keys_norepet. eassumption. *) +(* 2: { apply valueToPos_inj. apply unsigned_posToValue_le. *) +(* eapply pc_wf. intros. pose proof (HTL.mod_wf m) as HP. destruct HP as [HP _]. *) +(* split. lia. apply HP. eassumption. eassumption. *) +(* apply unsigned_posToValue_le. eapply pc_wf. intros. pose proof (HTL.mod_wf m) as HP. *) +(* destruct HP as [HP _]. *) +(* split. lia. apply HP. eassumption. eassumption. trivial. *) +(* } *) +(* apply Maps.PTree.elements_correct. eassumption. eassumption. *) + +(* econstructor. econstructor. *) + +(* { admit. *) +(* (* *) *) +(* (* eapply transl_list_correct. *) *) +(* (* intros. split. lia. pose proof (HTL.mod_wf m) as HP. destruct HP as [_ HP]. auto. *) *) +(* (* apply Maps.PTree.elements_keys_norepet. eassumption. *) *) +(* (* 2: { apply valueToPos_inj. apply unsigned_posToValue_le. *) *) +(* (* eapply pc_wf. intros. pose proof (HTL.mod_wf m) as HP. destruct HP as [HP _]. *) *) +(* (* split. lia. apply HP. eassumption. eassumption. *) *) +(* (* apply unsigned_posToValue_le. eapply pc_wf. intros. pose proof (HTL.mod_wf m) as HP. *) *) +(* (* destruct HP as [HP _]. *) *) +(* (* split. lia. apply HP. eassumption. eassumption. trivial. *) *) +(* (* } *) *) +(* (* apply Maps.PTree.elements_correct. eassumption. eassumption. *) *) +(* (* *) *) +(* } *) + +(* apply mis_stepp_decl. trivial. trivial. simpl. eassumption. auto. *) +(* rewrite valueToPos_posToValue. constructor; assumption. lia. *) +(* - econstructor; split. apply Smallstep.plus_one. apply step_finish. assumption. eassumption. *) +(* constructor; assumption. *) +(* - econstructor; split. apply Smallstep.plus_one. constructor. *) + +(* constructor. constructor. *) +(* - inv H3. econstructor; split. apply Smallstep.plus_one. constructor. trivial. *) + +(* apply match_state. assumption. *) +(* Admitted. *) +(* Hint Resolve transl_step_correct : verilogproof. *) + +(* Lemma transl_initial_states : *) +(* forall s1 : Smallstep.state (HTL.semantics prog), *) +(* Smallstep.initial_state (HTL.semantics prog) s1 -> *) +(* exists s2 : Smallstep.state (Verilog.semantics tprog), *) +(* Smallstep.initial_state (Verilog.semantics tprog) s2 /\ match_states s1 s2. *) +(* Proof. *) +(* induction 1. *) +(* econstructor; split. econstructor. *) +(* apply (Genv.init_mem_transf TRANSL); eauto. *) +(* rewrite symbols_preserved. *) +(* replace (AST.prog_main tprog) with (AST.prog_main prog); eauto. *) +(* symmetry; eapply Linking.match_program_main; eauto. *) +(* exploit function_ptr_translated; eauto. intros [tf [A B]]. *) +(* inv B. eauto. *) +(* constructor. *) +(* Qed. *) +(* Hint Resolve transl_initial_states : verilogproof. *) + +(* Lemma transl_final_states : *) +(* forall (s1 : Smallstep.state (HTL.semantics prog)) *) +(* (s2 : Smallstep.state (Verilog.semantics tprog)) *) +(* (r : Integers.Int.int), *) +(* match_states s1 s2 -> *) +(* Smallstep.final_state (HTL.semantics prog) s1 r -> *) +(* Smallstep.final_state (Verilog.semantics tprog) s2 r. *) +(* Proof. *) +(* intros. inv H0. inv H. inv H3. constructor. reflexivity. *) +(* Qed. *) +(* Hint Resolve transl_final_states : verilogproof. *) Theorem transf_program_correct: forward_simulation (HTL.semantics prog) (Verilog.semantics tprog). Proof. - eapply Smallstep.forward_simulation_plus; eauto with verilogproof. - apply senv_preserved. - Qed. + (* eapply Smallstep.forward_simulation_plus; eauto with verilogproof. *) + (* apply senv_preserved. *) + admit. + Admitted. End CORRECTNESS. |