From ab4eab4f51ce59fd29308c693c2bb77c73575de3 Mon Sep 17 00:00:00 2001 From: Felipe Lisboa <lisboafelipe5@gmail.com> Date: Thu, 8 Feb 2024 15:38:38 +0100 Subject: [PATCH] Succesfull merge between CavaDRAM most updated version and CoqDRAM --- framework/CavaDRAM/CavaCommonInstances.v | 25 +- framework/CavaDRAM/CavaFIFOProperties.v | 1654 +++++++++++++++++ framework/CavaDRAM/CavaFIFOREF.v | 131 +- framework/CavaDRAM/CavaReqQueue.v | 106 +- framework/CavaDRAM/CavaReqQueueProperties.v | 424 +++++ framework/CavaDRAM/CavaSMExtraction.v | 6 +- framework/CavaDRAM/CavaSubtractor.v | 124 +- framework/CavaDRAM/CavaSubtractorProperties.v | 2 +- framework/CavaDRAM/CavaSystem.v | 21 +- framework/CavaDRAM/CavaTDMREF.v | 196 +- framework/CavaDRAM/CavaTDMREFProperties.v | 111 ++ framework/CavaDRAM/Lib/CavaCounter.v | 2 +- framework/CavaDRAM/Lib/CavaFIFO.v | 2 +- .../CavaDRAM/Lib/CavaFIFOREFProperties.v | 1630 ++++++++++++++++ .../CavaDRAM/Lib/CavaFIFOREFProperties2.v | 311 ++++ framework/CavaDRAM/Lib/CavaSM.v | 2 +- framework/CavaDRAM/Lib/CavaSMProperties2.v | 6 +- framework/CavaDRAM/Lib/CavaSMbackup.v | 2 +- framework/CavaDRAM/Lib/CavaTactics.v | 8 +- framework/CavaDRAM/Memory.v | 293 +++ framework/CavaDRAM/README_extraction.md | 9 + framework/CavaDRAM/Step.v | 97 + framework/CavaDRAM/Util.v | 154 ++ framework/CavaDRAM/UtilSM.v | 326 ++++ framework/CavaDRAM/_CoqProject | 15 +- framework/CavaDRAM/backup.v | 1256 +++++++++++++ 26 files changed, 6711 insertions(+), 202 deletions(-) create mode 100644 framework/CavaDRAM/CavaFIFOProperties.v create mode 100644 framework/CavaDRAM/CavaReqQueueProperties.v create mode 100644 framework/CavaDRAM/CavaTDMREFProperties.v create mode 100644 framework/CavaDRAM/Lib/CavaFIFOREFProperties.v create mode 100644 framework/CavaDRAM/Lib/CavaFIFOREFProperties2.v create mode 100644 framework/CavaDRAM/Memory.v create mode 100644 framework/CavaDRAM/README_extraction.md create mode 100644 framework/CavaDRAM/Step.v create mode 100644 framework/CavaDRAM/Util.v create mode 100644 framework/CavaDRAM/UtilSM.v create mode 100644 framework/CavaDRAM/backup.v diff --git a/framework/CavaDRAM/CavaCommonInstances.v b/framework/CavaDRAM/CavaCommonInstances.v index 1fc0a28..a150dfc 100644 --- a/framework/CavaDRAM/CavaCommonInstances.v +++ b/framework/CavaDRAM/CavaCommonInstances.v @@ -1,19 +1,30 @@ +Set Warnings "-notation-overridden,-parsing". From CavaDRAM Require Import CavaSystem. -From DRAM Require Import System. +From CoqDRAM Require Import System. From Coq Require Program. +From mathcomp Require Import fintype ssrZ zify ring. Section CommonInstances. Program Instance CAVA_SYS : CavaSystem := { DRAM_CMD_WIDTH := 5; - FE_ADDR_WIDTH := 32; + (* FE_ADDR_WIDTH := 32 *) + ROW_ADDR_WIDTH := 17; + COL_ADDR_WIDTH := 11; + BANK_ADDR_WIDTH := 4; FE_CMD_WIDTH := 1; - FE_ID_WIDTH := 16; - QUEUE_MAX_SIZE := 32; + (* FE_ID_WIDTH := 16; *) + QUEUE_MAX_SIZE := 256; }. - + Next Obligation. + apply PeanoNat.Nat.lt_0_succ. + Qed. + Next Obligation. + lia. + Qed. + Program Instance SYS_CFG : System_configuration := { - BANKGROUPS := 4; + BANKGROUPS := 4; BANKS := 2; T_BURST := 4; (* 4*) T_WL := 5; (* 5*) @@ -31,7 +42,7 @@ Section CommonInstances. T_WTR_l := 6; (*6*) T_CCD_s := 4; (*4*) T_CCD_l := 5; (*5*) - T_REFI := 2880; (*orig: 2880, 7.8 us*) + T_REFI := 2054; (*orig: 2880, 7.8 us*) T_RFC := 44; (* orig: 44, 1Gb 110 ns *) }. diff --git a/framework/CavaDRAM/CavaFIFOProperties.v b/framework/CavaDRAM/CavaFIFOProperties.v new file mode 100644 index 0000000..3ab6753 --- /dev/null +++ b/framework/CavaDRAM/CavaFIFOProperties.v @@ -0,0 +1,1654 @@ +Set Printing Projections. +Set Warnings "-notation-overridden,-parsing". + +From CavaDRAM Require Import CavaFIFOREF CavaReqQueue CavaReqQueueProperties +CavaCommonInstances CavaSubtractor Step CavaSystem Memory Util UtilSM. +From CoqDRAM Require Import FIFO. +From Coq Require Import Program BinaryString HexString NArith. +From Cava Require Import Cava CavaProperties Util.Vector Util.Tactics. +From mathcomp Require Import fintype ssrZ zify ring. + +Section CavaFIFOProperties. + + Context {signal : SignalType -> Type} {semantics : Cava signal}. + (* From Cava *) + Existing Instance CombinationalSemantics. + (* From CavaDRAM*) + Context {CAVA_SYS : CavaSystem}. + (* From CoqDRAM *) + Existing Instance REQESTOR_CFG. + Context {SYS_CFG : System_configuration}. + Context {FIFO_CFG : FIFO_configuration}. + Context {HAF : HW_Arrival_function_t}. + Existing Instance ARBITER_CFG. + Existing Instance FIFO_implementation. + + Import Memory.Properties BvectorNotations. + Open Scope Bvector_scope. + + Definition mem_cells_ := + mem_cells (Vec Bit REQUEST_WIDTH) ADDR_WIDTH (Nat.pow 2 ADDR_WIDTH) InitMem. + + Lemma nth_cells_read {T W I} (ad : Bvector W) c_req def + (c : circuit_state (mem_cells T W (2 ^ W) I)) : + nth_default def (N.to_nat (Bv2N ad)) (Cells_read true (N.to_nat (Bv2N ad)) c_req c) = c_req. + Admitted. + + Lemma nth_cells_read_ {T W I N} (ad : Bvector (Nat.log2 N)) c_req def + (c : circuit_state (mem_cells T W N I)) : N > 0 -> + nth_default def (N.to_nat (Bv2N ad)) (Cells_read true (N.to_nat (Bv2N ad)) c_req c) = c_req. + Proof. + intros Hpos; rewrite nth_default_to_list. + induction N; intros; [ discriminate | ]. + rewrite leq_eqVlt in Hpos; move: Hpos => /orP [/eqP Heq | Hpos]. + { assert (N = 0); [ lia | ]; clear IHN Heq; subst N. + revert ad; rewrite Nat.log2_1; intros. + apply Vector.case0 with (v := ad). + simpl in c; destruct_products. + rewrite /Cells_read //= andb_true_r. + } + assert (0 < N); [ lia | ]; clear Hpos. + simpl in c; destruct_products; rewrite //= andb_true_r. + specialize (Nat.log2_succ_or N) as Hor; destruct Hor as [Hor | Hor]. + { revert ad; rewrite Hor; intros. + destruct (Nat.eqb (N.to_nat (Bv2N ad)) N) eqn:HH; set memvec := Cells_read true _ _ _. + { assert (N.to_nat (Bv2N ad) = N) as H0; [ lia | ]; clear HH; + rewrite H0. + specialize (@length_to_list_shiftin (combType T) N memvec c_req) as HH. + assert (N = (Datatypes.length (Vector.to_list (Vector.shiftin c_req memvec))) - 1)%coq_nat; [ lia | ]. + apply nth_last with (d := def) in H1; rewrite H1. + by rewrite last_shiftin. } + { unfold memvec. + specialize (IHN (VectorDef.tl ad) c0); apply IHN in H as IH; clear IHN. + rewrite (Vector.eta ad) Bv2N_cons. + destruct (Vector.hd ad). + { rewrite N2Nat.inj_succ_double //= !Nat.add_0_r. + rewrite -nth_tl. + set adtl := N.to_nat (Bv2N (VectorDef.tl ad)). + fold adtl in IH. + admit. } + { admit. } + Admitted. + + Lemma memcell_nch (c: circuit_state mem_cells_) (wra rda : Bvector ADDR_WIDTH) c_req def: + wra <> rda -> + nth_default def (N.to_nat (Bv2N rda)) (Cells_data c) = + nth_default def (N.to_nat (Bv2N rda)) (Cells_read true (N.to_nat (Bv2N wra)) c_req c). + Admitted. + + (* ----------------------------------------------------------------------- *) + (* Getters and state signals manipulation -------------------------------- *) + + Definition State_t := circuit_state FIFOSM_. + + Definition get_fields (s : State_t) := + let '(_,(_,(_,(_,(_,(_,(_,_,_,mem,_,_,_,_,rda),wra)),_,(_,(_,cr)),_,_,_,_,_,cref),cnt),st)) := s + in (mem,rda,wra,cr,cref,cnt,st). + + Definition get_st (s : State_t) := + let '(_,_,_,_,_,_,st) := get_fields s in st. + + Definition get_cnt (s : State_t) := + let '(_,_,_,_,_,cnt,_) := get_fields s in cnt. + + Definition get_cref (s : State_t) := + let '(_,_,_,_,cref,_,_) := get_fields s in cref. + + Definition get_cr (s : State_t) := + let '(_,_,_,cr,_,_,_) := get_fields s in cr. + + Definition get_wra (s : State_t) := + let '(_,_,wra,_,_,_,_) := get_fields s in wra. + + Definition get_rda (s : State_t) := + let '(_,rda,_,_,_,_,_) := get_fields s in rda. + + Definition get_mem (s : State_t) : circuit_state memqueue' := + let '(mem,_,_,_,_,_,_) := get_fields s in mem. + + Definition get_reqqueue (s : State_t) : circuit_state RequestQueue' := + let '(_,(_,(_,(_,cs_requeue,_,_,_,_,_,_,_,_),_),_)) := s in cs_requeue. + + Create HintDb get_state. + Hint Unfold get_fields get_st get_cnt get_cref get_reqqueue get_addr_RequestQueue get_mem + get_memcells_RequestQueue get_mem_RequestQueue get_memcells get_cr : get_state. + + (* --------------------------Bounding the counter ------------------- *) + Lemma cnt_bounded (cnt : Bvector COUNTER_WIDTH) : + N.to_nat (Bv2N cnt) < WAIT. + Proof. + specialize @Bv2N_upper_bound_nat with (bv := cnt) as H. + by rewrite /COUNTER_WIDTH WAIT_PW_2 in H. + Qed. + + Definition Bv2cnt (cnt : Bvector COUNTER_WIDTH) : Counter_t := + Ordinal (cnt_bounded cnt). + + Definition cnt2Bv (cnt : Counter_t) := + N2Bv_sized COUNTER_WIDTH (N.of_nat (nat_of_ord cnt)). + + (* -------------------------- cref counter -------------------------- *) + Definition cref2Bv (cref : Counter_ref_t) := + N2Bv_sized COUNTER_REF_WIDTH (N.of_nat (nat_of_ord cref)). + + Lemma cref_bound (c : Counter_ref_t) : + c < 2 ^ COUNTER_REF_WIDTH. + Proof. + unfold COUNTER_REF_WIDTH. + destruct (_ == PREA_date + (WAIT - 1)) eqn:HPW2; destruct c. + { simpl in *; move: HPW2 => /eqP HPW2; rewrite HPW2; lia. } + { specialize (Nat.log2_spec (PREA_date + (WAIT - 1))) as h. + specialize WAIT_pos as Hwpos; assert ((0 < PREA_date + (WAIT - 1))%coq_nat) as H0; [ lia | ]. + apply h in H0; destruct H0 as [_ H1]; move: H1 => /ltP H1. + set aux := 2 ^ (Nat.log2 (PREA_date + (WAIT - 1))).+1; simpl; unfold aux; clear aux; lia. + } + Qed. + + Lemma prea_date_bound : + PREA_date -1 < 2 ^ COUNTER_REF_WIDTH. + Proof. + unfold COUNTER_REF_WIDTH. + destruct (_ == PREA_date + (WAIT - 1)) eqn:HPW2. + { simpl in *; move: HPW2 => /eqP HPW2; rewrite HPW2; specialize WAIT_gt_one; lia. } + { specialize (Nat.log2_spec (PREA_date + (WAIT - 1))) as h. + assert ((0 < PREA_date + (WAIT - 1))%coq_nat) as H0; + specialize WAIT_gt_one as Hwt1; [ lia | ]; clear Hwt1. + apply h in H0; destruct H0 as [H0 H1]; lia. + } + Qed. + + Lemma wait_bound : + WAIT - 1 < 2 ^ COUNTER_REF_WIDTH. + Proof. + unfold COUNTER_REF_WIDTH. + destruct (_ == PREA_date + (WAIT - 1)) eqn:HPW2. + { simpl in *; move: HPW2 => /eqP HPW2; rewrite HPW2. specialize PREA_date_pos; lia. } + { specialize (Nat.log2_spec (PREA_date + (WAIT - 1))) as h. + assert ((0 < PREA_date + (WAIT - 1))%coq_nat) as H0; + specialize WAIT_gt_one as Hwt1; [ lia | ]; clear Hwt1. + apply h in H0; destruct H0 as [H0 H1]; lia. + } + Qed. + + Lemma cref_preadate_false (c : Counter_ref_t) : + (cref2Bv c =? CNT_REF_PREA) = false <-> + (nat_of_ord c == PREA_date - 1) = false. + Proof. + split. { + unfold cref2Bv, CNT_REF_PREA; intros. + apply BVEq_iff_neq in H; rewrite bitvec_literal_correct in H. + apply N2Bv_sized_neq_if in H. + apply of_nat_neq in H. + by apply /eqP. } + { intros. + apply BVEq_iff_neq. + rewrite /cref2Bv /CNT_REF_PREA bitvec_literal_correct. + apply N2Bv_sized_neq_iff; [ | | move: H => /eqP H; by rewrite Nat2N.inj_iff ]; + apply /leP; apply N.size_nat_le_nat; apply /leP; + [ apply cref_bound | apply prea_date_bound ]. } + Qed. + + Lemma cref_preadate_true (c : Counter_ref_t) : + (cref2Bv c =? CNT_REF_PREA) = true <-> + (nat_of_ord c == PREA_date - 1) = true. + Proof. + split. + { unfold cref2Bv, CNT_REF_PREA; intros. + apply BVEq_iff_eq in H; rewrite bitvec_literal_correct in H. + apply N2Bv_sized_eq_iff in H; + [ apply Nat2N.inj in H; rewrite H; by apply /eqP | | ]; + apply N.size_nat_le_nat; apply /leP; + [ apply cref_bound | apply prea_date_bound ]. + } + { intros Href_prea; move: Href_prea => /eqP Href_prea; apply BVEq_iff_eq. + rewrite /cref2Bv /CNT_REF_PREA bitvec_literal_correct; f_equal. + by rewrite Href_prea. + } + Qed. + + Lemma CrefPREA_lt_CNT_REF_PREA: + CrefPREA_lt CNT_REF_PREA = false. + Proof. + cbv [CrefPREA_lt]; simpl_ident. + unfold greaterThanOrEqual; simpl_ident; unfold greaterThanOrEqualBool. + apply /negbF. + rewrite {1}/CNT_REF_PREA; rewrite !bitvec_literal_correct. + apply /N.leb_spec0; rewrite /CNT_REF_PREA /CNT_REF_WAIT !bitvec_literal_correct. + rewrite !Bv2N_N2Bv_sized. { apply N.le_add_r. } + all: apply to_nat_lt_pow; try rewrite -Nat2N.inj_add; rewrite Nat2N.id. + 2 : { + unfold COUNTER_REF_WIDTH; destruct (_ == PREA_date + (WAIT - 1)) eqn:Hpw2. + { move: Hpw2 => /eqP Hpw2; rewrite Hpw2; + specialize WAIT_gt_one; specialize PREA_date_gt_one; lia. } + { specialize (Nat.log2_spec (PREA_date + (WAIT - 1))) as h. + specialize WAIT_gt_one as Hwpos; assert ((0 < PREA_date + (WAIT - 1))%coq_nat) as H0; [ lia | ]. + apply h in H0; destruct H0 as [H0 H1]; lia. + } + } + all: try (apply wait_bound || apply prea_date_bound). + Qed. + + Lemma CrefPREA_lt_CNT_REF_WAIT cref: + (cref2Bv cref =? CNT_REF_PREA) = false -> (cref + WAIT < PREA_date) = true -> + CrefPREA_lt (cref2Bv cref) = true. + Proof. + intros Href_prea Href_service. + rewrite /CrefPREA_lt; simpl_ident; rewrite /greaterThanOrEqual; simpl_ident. + rewrite /greaterThanOrEqualBool /CNT_REF_WAIT /CNT_REF_PREA !bitvec_literal_correct !Bv2N_N2Bv_sized. + { destruct (~~ _) eqn:Hbug; [ done | ]. + apply negbFE in Hbug; move: Hbug => /N.leb_spec0 Hbug. + assert (cref + (WAIT - 1) < (PREA_date - 1)). + { rewrite addnBA; [ | exact WAIT_pos]. + rewrite subn1 -ltnS prednK; [ | by rewrite addn_gt0 WAIT_pos orb_true_r ]. + rewrite subn1 prednK; [ | exact PREA_date_pos]. + by rewrite Href_service. + } + move: H => /ltP H; apply N_lt_inj in H. + contradict Hbug; apply N.nle_gt; by rewrite -Nat2N.inj_add. + } + all: apply to_nat_lt_pow; try rewrite -Nat2N.inj_add; rewrite Nat2N.id. + all: try (apply cref_bound || apply wait_bound || apply prea_date_bound). + { unfold COUNTER_REF_WIDTH. + destruct (_ == PREA_date + (WAIT - 1)) eqn:Heq. + { move: Heq => /eqP Heq; rewrite Heq. + destruct cref; simpl in *; lia. } + { destruct cref. + set aux := 2 ^ (Nat.log2 (PREA_date + (WAIT - 1))).+1; simpl. + assert ((m + (WAIT - 1))%coq_nat < PREA_date + (WAIT - 1)); [ lia | ]. + specialize (Nat.log2_spec (PREA_date + (WAIT - 1))) as HH; lia. + } + } + Qed. + + Lemma CrefPREA_lt_CNT_REF_WAIT_F (c1 : Counter_ref_t) : + (c1 + WAIT < PREA_date) = false -> + CrefPREA_lt (cref2Bv c1) = false. + Proof. + intros; + rewrite /CrefPREA_lt; simpl_ident; rewrite /greaterThanOrEqual; simpl_ident. + rewrite /greaterThanOrEqualBool /CNT_REF_WAIT /CNT_REF_PREA !bitvec_literal_correct !Bv2N_N2Bv_sized. + { apply negb_false_iff; apply /N.leb_spec0; lia. } + all: apply to_nat_lt_pow; try rewrite -Nat2N.inj_add; rewrite Nat2N.id. + all: try (apply cref_bound || apply wait_bound || apply prea_date_bound). + all: try (apply cref_bound || apply wait_bound || apply prea_date_bound). + { unfold COUNTER_REF_WIDTH. + destruct (_ == PREA_date + (WAIT - 1)) eqn:Heq. + { move: Heq => /eqP Heq; rewrite Heq. + destruct c1; simpl in *; lia. } + { destruct c1. + set aux := 2 ^ (Nat.log2 (PREA_date + (WAIT - 1))).+1; simpl. + assert ((m + (WAIT - 1))%coq_nat < PREA_date + (WAIT - 1)); [ lia | ]. + specialize (Nat.log2_spec (PREA_date + (WAIT - 1))) as HH; lia. + } + } + Qed. + + (* -------------------------- Predicates -------------------------------- *) + Program Definition EqReq (r : Request_t) (r' : Bvector REQUEST_WIDTH) : bool. + Admitted. + + Lemma EqReqNil : EqReq nullreq REQUEST_NIL = true. + Admitted. + + Hypothesis HaltIfFull : forall t c, + let wra := get_wra c in + let rda := get_rda c in + if (HW_Arrival_at t != []) then ~~ fullQueue wra rda else true. + + Definition EqCmd (f_cmd : Command_kind_t) (c_cmd : Bvector DRAM_CMD_WIDTH) : bool := + match f_cmd with + | ACT => (c_cmd =? ACT_VEC) + | PRE => (c_cmd =? PRE_VEC) + | PREA => (c_cmd =? PREA_VEC) + | CRD => (c_cmd =? RD_VEC) + | CWR => (c_cmd =? WR_VEC) + | REF => (c_cmd =? REF_VEC) + | NOP => (c_cmd =? NOP_VEC) + end. + + Fixpoint EqQueue (P : Requests_t) (wra rda : Bvector ADDR_WIDTH) := + match P with + | [::] => (wra =? rda) + | x :: x0 => negb (wra =? rda) && (EqQueue x0 wra (N2Bv_sized ADDR_WIDTH (Bv2N rda + 1))) + end. + + Lemma EqQueue_diff_adr r0 r1 wra rda: + EqQueue (r0 :: r1) wra rda -> wra <> rda. + Proof. + simpl; intros; move: H => /andP [Hd H]; + by move: Hd => /negPf Hd; apply BVEq_iff_neq in Hd. + Qed. + + (* ----------------------------------------- *) + Lemma leN_leqn a b: + leq (S (addn (nat_of_bin a) 1)) (nat_of_bin b) -> N.lt (N.add a 1) b. + Proof. lia. Qed. + + Lemma ltN_ltn a b: + leq (S (nat_of_bin a)) (nat_of_bin b) <-> N.lt a b. + Proof. lia. Qed. + + Lemma succ_double_inj_neq a b: + a <> b -> N.succ_double a <> N.succ_double b. + Proof. + intros; rewrite !N.succ_double_spec; lia. + Qed. + + Lemma succ_double_double_inj_neq a b: + a <> b -> N.succ_double a <> N.double b. + Proof. + intros; rewrite N.succ_double_spec N.double_spec; lia. + Qed. + + Lemma neq_nat_of_bin (a b : N) : + not (@eq N a b) <-> + not (@eq nat (nat_of_bin a) (nat_of_bin b)). + Proof. lia. Qed. + + Lemma cons_neq_BV {n} (a : bool) (x y: Bvector n) : + ((a :: x)%vector) <> ((a :: y) %vector) -> x <> y. + Admitted. + + Lemma Bv2N_neq_inj {W} (a b : Bvector W): + a <> b -> Bv2N a <> Bv2N b. + Proof. + intros; induction W; [ admit | ]. + rewrite (Vector.eta a) (Vector.eta b); simpl; + destruct (Vector.hd a) eqn:Ha, (Vector.hd b) eqn:Hb; + specialize (IHW (VectorDef.tl a) (VectorDef.tl b)). + { assert ((VectorDef.tl a) <> (VectorDef.tl b)) as H0. + { rewrite (Vector.eta a) (Vector.eta b) in H; rewrite Ha Hb in H. + by apply cons_neq_BV in H. } + apply IHW in H0; by apply succ_double_inj_neq. } + all: admit. + Admitted. + + (* Use in EqQueue_aux *) + Lemma Bvector_neq_N2Bv_sized_p1_neq {W} (a b : Bvector W) : + W > 0 -> a <> b -> + N2Bv_sized W (Bv2N a + 1) <> N2Bv_sized W (Bv2N b + 1). + Proof. + intros. + specialize (@Bv2N_upper_bound_nat W b) as Hub_b. + specialize (@Bv2N_upper_bound_nat W a) as Hub_a. + specialize (N2Bv_sized_neq_iff W (Bv2N a) (Bv2N b)) as Hneq. + apply Bv2N_neq_inj in H0; apply Hneq in H0; try (apply /leP; apply N.size_nat_le); + [ | by apply to_nat_lt_pow in Hub_a | by apply to_nat_lt_pow in Hub_b]; clear Hneq. + rewrite !N.add_1_r. + (* apply N2Bv_sized_neq_iff. *) + specialize (N2Bv_sized_neq_succ W (Bv2N a)) as Hsucc_a. + specialize (N2Bv_sized_neq_succ W (Bv2N b)) as Hsucc_b. + apply Hsucc_a in H as Ha'; clear Hsucc_a. + apply Hsucc_b in H as Hb'; clear Hsucc_b. + Admitted. + + (* Use in EqQueue_aux *) + Lemma notfull_rd (wr rd : Bvector ADDR_WIDTH) : + let rdp1 := N2Bv_sized ADDR_WIDTH (Bv2N rd + 1) in + wr <> rd -> wr <> rdp1 -> ~~ fullQueue wr rd -> + ~~ fullQueue wr rdp1. + Proof. + intros rdp1 Hdif1 Hdif2 HF; unfold fullQueue in HF. + destruct (leq _ _) eqn:Hleq. + { rewrite leq_eqVlt in Hleq; move: Hleq => /orP [/eqP Heq | Hleq]. + { admit. (* impossible *)} + unfold fullQueue. + destruct (Bv2N rdp1 <= _) eqn:Hleq2. + { apply /negPf; apply Nat.eqb_neq. + specialize (N.lt_neq (Bv2N wr - Bv2N rdp1) (N.of_nat QUEUE_MAX_SIZE - 1)) as H. + apply neq_nat_of_bin; apply H; clear H. + move: HF => /negPf HF; apply Nat.eqb_neq in HF. + apply neq_nat_of_bin in HF. + apply (N.lt_gt_cases (Bv2N wr - Bv2N rd) (N.of_nat QUEUE_MAX_SIZE - 1)) in HF as HF'; + destruct HF' as [H0 | H1]. + 2: admit. (* Impossible, Bv2N wr - Bv2N rd cannot be bigger than QMS *) + apply (N.lt_trans (Bv2N wr - Bv2N rdp1) (Bv2N wr - Bv2N rd) (N.of_nat QUEUE_MAX_SIZE - 1)); + [ | exact H0 ]. + assert (N.lt (Bv2N rd) (Bv2N rdp1)); [ admit | ]. + lia. + } + { admit. } + } + { admit. } + Admitted. + + (* Use in EqQueue_aux *) + Lemma notfull_adrs (wr rd : Bvector ADDR_WIDTH) : + let rdp1 := N2Bv_sized ADDR_WIDTH (Bv2N rd + 1) in + let wrp1 := N2Bv_sized ADDR_WIDTH (Bv2N wr + 1) in + wr <> rd -> ~~ fullQueue wr rd -> + wrp1 <> rd. + Proof. + intros rdp1 wrp1 Hdif NF; unfold fullQueue in NF. + destruct (leq _ _) eqn:Hleq. + { move: NF => /negPf NF; apply Nat.eqb_neq in NF. + rewrite leq_eqVlt in Hleq; move: Hleq => /orP [/eqP Hbug | Hltn]. + { admit. (* Impossible *)} + apply neq_nat_of_bin in NF. + apply (N.lt_gt_cases (Bv2N wr - Bv2N rd) (N.of_nat QUEUE_MAX_SIZE - 1)) in NF as NF'; + destruct NF' as [NF'| _]. + 2: admit. (* Impossible *) + unfold wrp1. + specialize (N2Bv_sized_Bv2N ADDR_WIDTH rd) as HH; rewrite -HH; clear HH. + apply N2Bv_sized_neq_iff; + admit. + } + { admit. } + Admitted. + + Lemma EqQueue_aux wra rda r0 r1 r: + ~~ fullQueue wra rda -> wra <> rda -> + EqQueue (r0 :: r1)%SEQ wra rda -> + EqQueue ((r0 :: r1)%SEQ ++ [r])%SEQ (N2Bv_sized ADDR_WIDTH (Bv2N wra + 1)) rda. + Proof. + intros NFULL Hadr HQ; rewrite //=. + simpl in HQ; move: HQ => /andP [_ HQ]. + revert HQ Hadr NFULL; generalize wra rda; induction r1; intros; simpl in HQ. + { apply /andP; split. + { unfold fullQueue in NFULL. + move: NFULL; apply contraPN; intros; apply /negP; rewrite negb_involutive. + specialize ADDR_WIDTH_pos as Hawp; move: Hawp => /ltP Hawp. + destruct (Bv2N rda0 <= _) eqn:Hleq. + { apply BVEq_iff_eq in HQ as HQ'; rewrite HQ' in H; clear HQ'. + apply Bvector_wrap in H; [ | apply /ltP; exact ADDR_WIDTH_pos ]. + apply log2_eq1_pw2 in H as H2 ; [ | by rewrite QUEUE_MAX_SIZE_PW2 ]; clear H. + rewrite H2; simpl ((N.of_nat 2 - 1)%N); simpl (N.add (Npos _) (Npos _)). + apply BVEq_iff_eq in HQ; rewrite HQ Bv2N_N2Bv_sized; [ lia | ]. + apply /N.ltb_spec0. + destruct ((Bv2N rda0 + 1 <? 2 ^ N.of_nat ADDR_WIDTH)%N) eqn:Hcont; [ done | ]. + move: Hcont => /negP /negP Hcont; rewrite -N.leb_antisym in Hcont. + move: Hcont => /N.leb_spec0 Hcont. + unfold ADDR_WIDTH in Hcont; rewrite QUEUE_MAX_SIZE_PW2_N in Hcont. + rewrite leq_eqVlt in Hleq; move: Hleq => /orP [/eqP Hbug | Hltn]. + { specialize (@Bv2N_inj ADDR_WIDTH rda0 wra0) as HH. + apply Bv_eq_translation in Hbug; apply HH in Hbug; by rewrite Hbug in Hadr. } + { apply N.le_lteq in Hcont; destruct Hcont as [Hcont0 | Hcont1]; + specialize (@Bv2N_upper_bound_nat ADDR_WIDTH wra0) as H; + apply Bv_ltn_translation in Hltn; + apply to_nat_lt_pow in H; + rewrite /ADDR_WIDTH QUEUE_MAX_SIZE_PW2_N in H; + apply lt_trans_le with (p := N.of_nat QUEUE_MAX_SIZE) in Hltn; try by apply ltN_ltn. + { contradict Hcont0; apply N.lt_asymm; by apply leN_leqn in Hltn. } + { contradict Hcont1; apply N.neq_sym; apply N.lt_neq; by apply leN_leqn. } + } + } + { apply BVEq_iff_eq in H; rewrite -H Bv2N_N2Bv_sized; [ lia | ]. + move: Hleq => /negP /negP Hleq; rewrite -ltnNge in Hleq; rename Hleq into Hltn. + apply /N.ltb_spec0. + destruct ((Bv2N wra0 + 1 <? 2 ^ N.of_nat ADDR_WIDTH)%N) eqn:Hcont; [ done | ]. + unfold ADDR_WIDTH in Hcont; rewrite QUEUE_MAX_SIZE_PW2_N in Hcont. + move: Hcont => /negP /negP Hcont; rewrite -N.leb_antisym in Hcont; move: Hcont => /N.leb_spec0 Hcont. + apply N.le_lteq in Hcont; destruct Hcont as [Hcont0 | Hcont1]; + specialize (@Bv2N_upper_bound_nat ADDR_WIDTH rda0) as Hub; + apply Bv_ltn_translation in Hltn; + apply to_nat_lt_pow in Hub; + rewrite /ADDR_WIDTH QUEUE_MAX_SIZE_PW2_N in Hub; + apply lt_trans_le with (p := N.of_nat QUEUE_MAX_SIZE) in Hltn; try by apply ltN_ltn. + { contradict Hcont0; apply N.lt_asymm; by apply leN_leqn in Hltn. } + { contradict Hcont1; apply N.neq_sym; apply N.lt_neq; by apply leN_leqn. } + } + } + { simpl; apply BVEq_iff_eq in HQ; apply /andP; split. + { apply /negPf; apply BVEq_iff_neq. + apply Bvector_neq_N2Bv_sized_p1_neq; [ apply /ltP; exact ADDR_WIDTH_pos | done]. } + { rewrite HQ; by apply BVEq_iff_eq. } + } + } + move: HQ => /andP [neq HQ]. + specialize (IHr1 wra0 (N2Bv_sized ADDR_WIDTH (Bv2N rda0 + 1))); apply IHr1 in HQ as IH; clear IHr1. + 3: { + move: neq => /negPf neq; apply BVEq_iff_neq in neq. + apply notfull_rd; done. + } + 2: by move: neq => /negPf neq; apply BVEq_iff_neq in neq. + simpl; apply /andP; split. + { move: IH => /andP [neq_ IH]. + apply /negPf; apply BVEq_iff_neq. + apply notfull_adrs; try done. + } + exact IH. + Qed. + + Fixpoint EqMem_ {W} (P : Requests_t) (rda : Bvector W) + (memcells_vec : Vector.t (Bvector REQUEST_WIDTH) (Nat.pow 2 W)) : bool := + match P with + | [::] => true + | x :: x0 => + let nrda := N2Bv_sized W (Bv2N rda + 1) in + let s := nth_default REQUEST_NIL (N.to_nat (Bv2N rda)) memcells_vec in + (EqReq x s) && (EqMem_ x0 nrda memcells_vec) + end. + + Lemma EqMem_rcons r1 (rda wra : Bvector ADDR_WIDTH) c R (c_req : combType (Vec Bit REQUEST_WIDTH)) : + EqQueue r1 wra rda -> + EqMem_ r1 rda (@Cells_data (Vec Bit REQUEST_WIDTH) ADDR_WIDTH (Nat.pow 2 ADDR_WIDTH) InitMem c) -> + EqReq R c_req -> + EqMem_ (r1 ++ [R])%SEQ rda (Cells_read true (N.to_nat (Bv2N wra)) c_req c). + Proof. + intros HQ Mem EqR; fold mem_cells_ in c; rewrite cats1. + revert Mem HQ; generalize wra rda; induction r1; intros. + { simpl; rewrite andb_true_r; simpl in HQ; apply BVEq_iff_eq in HQ; rewrite HQ. + rewrite VectorSpec.map_id. + unfold ADDR_WIDTH in wra,rda. + specialize (@nth_cells_read (Vec Bit REQUEST_WIDTH) ADDR_WIDTH InitMem + rda0 c_req REQUEST_NIL) as HH; rewrite /REQUEST_NIL bitvec_literal_correct //= in HH; + unfold mem_cells_ in c; by rewrite HH. } + simpl in Mem,HQ; simpl. + move: Mem => /andP [EqR_ Mem]; apply /andP; split. + { move: HQ => /andP [/negPf Heq HQ]; + apply BVEq_iff_neq in Heq; rewrite VectorSpec.map_id; rewrite VectorSpec.map_id in EqR_. + rewrite -memcell_nch; done. + } + { move: HQ => /andP [neq HQ]. + specialize (IHr1 wra0 (N2Bv_sized ADDR_WIDTH (Bv2N rda0 + 1))); apply IHr1; done. + } + Qed. + + (* Just use the circuit directly <-> circuit does the work directly *) + Definition EqMem (P : Requests_t) rda (mem : circuit_state RequestQueue') := + let memcells_vec := Cells_data (get_memcells_RequestQueue mem) in + EqMem_ P rda memcells_vec. + + Definition State_Eq (fram_state : FIFO_state_t) (cava_state : State_t) : bool := + let s := get_st cava_state in + let c' := get_cnt cava_state in + let cref' := get_cref cava_state in + let r' := get_cr cava_state in + let RQ := get_reqqueue cava_state in + let wra := fst (get_addr_RequestQueue RQ) in + let rda := snd (get_addr_RequestQueue RQ) in + match fram_state with + | IDLE c cref P => + (s =? STATE_IDLE_VEC) && (c' =? cnt2Bv c) && (cref' =? cref2Bv cref) && + (EqMem P rda RQ) && (EqQueue P wra rda) + | RUNNING c cref P r => + (s =? STATE_RUN_VEC) && (c' =? cnt2Bv c) && (cref' =? cref2Bv cref) && (EqMem P rda RQ) && + (EqQueue P wra rda) && (EqReq r r') + | REFRESHING cref P => + (s =? STATE_REF_VEC) && (cref' =? cref2Bv cref) && + (EqMem P rda RQ) && (EqQueue P wra rda) + end. + + (* -------------- Proofs about CmdGen ------------------------------- *) + Lemma CmdGen_equiv_idle_to_idle_E (c : circuit_state CmdGen) cnt cref: + (cref =? CNT_REF_PREA) = false -> + exists c', step CmdGen c (STATE_IDLE_VEC,true,cnt,cref,REQUEST_NIL) = + (c',NOP_VEC). + Proof. + intros H; simpl in c; destruct_products. + eapply ex_intro. + cbv [CmdGen]; cbn [step fst snd]. + simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + fast_simpl_bool; simpl. + cbv [CrefPREA_eq]. + apply BVEq_iff_neq in H. + specialize @CavaPreludeProperties.eqb_neq with (t := Vec Bit (@COUNTER_REF_WIDTH SYS_CFG FIFO_CFG)) as HH. + apply HH in H; rewrite H VectorSpec.map_id; reflexivity. + Qed. + + Lemma CmdGen_equiv_idle_to_idle (c : circuit_state CmdGen) cnt cref: + (cref2Bv cref =? CNT_REF_PREA) = false -> + (cref + WAIT < PREA_date) = false -> + exists c', step CmdGen c (STATE_IDLE_VEC,false,cnt,(cref2Bv cref),REQUEST_NIL) = + (c',NOP_VEC). + Proof. + intros H Href_service; simpl in c; destruct_products; eapply ex_intro. + cbv [CmdGen]; cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + fast_simpl_bool; simpl. + cbv [CrefPREA_eq]; apply BVEq_iff_neq in H. + specialize @CavaPreludeProperties.eqb_neq with (t := Vec Bit (@COUNTER_REF_WIDTH SYS_CFG FIFO_CFG)) as HH. + apply HH in H; rewrite H !VectorSpec.map_id. + rewrite CrefPREA_lt_CNT_REF_WAIT_F; done. + Qed. + + Lemma CmdGen_equiv_idle_to_ref (c : circuit_state CmdGen) cnt cref e: + (cref =? CNT_REF_PREA) = true -> + exists c', step CmdGen c (STATE_IDLE_VEC,e,cnt,cref,REQUEST_NIL) = (c',PREA_VEC). + Proof. + intros; simpl in c; destruct_products; eapply ex_intro. + cbv [CmdGen]; cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + fast_simpl_bool; simpl; rewrite VectorSpec.map_id. + apply BVEq_iff_eq in H; subst cref; rewrite CrefPREA_lt_CNT_REF_PREA !VectorSpec.map_id. + rewrite andb_false_r; rewrite /CrefPREA_eq. + specialize @CavaPreludeProperties.eqb_eq with (t := Vec Bit (@COUNTER_REF_WIDTH SYS_CFG FIFO_CFG)) as HH. + assert (CNT_REF_PREA = CNT_REF_PREA); [done | ]; apply HH in H; by rewrite H. + Qed. + + Lemma CmdGen_equiv_idle_to_running (c : circuit_state CmdGen) cnt cref tr: + (cref2Bv cref =? CNT_REF_PREA) = false -> + (cref + WAIT < PREA_date) = true -> + exists c', step CmdGen c (STATE_IDLE_VEC,false,cnt,(cref2Bv cref),tr) = (c',PRE_VEC). + Proof. + intros; simpl in c; destruct_products; eapply ex_intro. + cbv [CmdGen]; cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + fast_simpl_bool; simpl; rewrite !VectorSpec.map_id. + rewrite CrefPREA_lt_CNT_REF_WAIT; done. + Qed. + (* ------------------------------------------------------------------ *) + + (* -------------- Proofs about NextCR ------------------------------- *) + Lemma NextCR_equiv (c : circuit_state NextCR) cnt cref tr: + exists c', step NextCR c (STATE_IDLE_VEC,true,cnt,cref,tr) = + (c',REQUEST_NIL). + Proof. + simpl in c; destruct_products. + eapply ex_intro. + cbv [NextCR LoopInit]; cbn [step fst snd]. + simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + fast_simpl_bool; by simpl. + Qed. + + Lemma NextCR_equiv_IDLE_NE_PREA c cnt cref tr: + (cref =? CNT_REF_PREA) = true -> + exists c', step NextCR c (STATE_IDLE_VEC,false,cnt,cref,tr) = + (c',REQUEST_NIL). + Proof. + intros; simpl in c; destruct_products; eapply ex_intro. + cbv [NextCR LoopInit]; cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + rewrite negb_false andb_true_l; rewrite /Srun //= VectorSpec.map_id. + apply BVEq_iff_eq in H; subst cref. + by rewrite CrefPREA_lt_CNT_REF_PREA. + Qed. + + Lemma NextCR_equiv_IDLE_IDLE c cnt (cref : Counter_ref_t) tr: + (cref + WAIT < PREA_date) = false -> + exists c', step NextCR c (STATE_IDLE_VEC,false,cnt,cref2Bv cref,tr) = + (c',REQUEST_NIL). + Proof. + intros Href_service; simpl in c; destruct_products; eapply ex_intro. + cbv [NextCR LoopInit]; cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + rewrite negb_false andb_true_l; rewrite /Srun //= VectorSpec.map_id. + rewrite CrefPREA_lt_CNT_REF_WAIT_F; done. + Qed. + + Lemma NextCR_equiv_IDLE_RUNNING c cnt (cref : Counter_ref_t) tr: + (cref2Bv cref =? CNT_REF_PREA) = false -> + (cref + WAIT < PREA_date) = true -> + exists c', + step NextCR c (STATE_IDLE_VEC,false,cnt,cref2Bv cref,tr) = (c',tr) /\ + (snd (snd c')) = tr. + Proof. + intros Href_service Href_prea; simpl in c; destruct_products; eapply ex_intro. + cbv [NextCR LoopInit]; cbn [step fst snd]; simpl_ident. + rewrite negb_false andb_true_l; rewrite /Srun //= VectorSpec.map_id. + rewrite CrefPREA_lt_CNT_REF_WAIT; done. + Qed. + (* ------------------------------------------------------------------ *) + + Create HintDb update. + Lemma Sidle_true : + Sidle STATE_IDLE_VEC = true. + Proof. + apply CavaPreludeProperties.eqb_refl. + Qed. + Hint Rewrite @Sidle_true : update. + + Lemma Sref_idle_false : + Sref STATE_IDLE_VEC = false. + Proof. + by apply CavaPreludeProperties.eqb_neq. + Qed. + Hint Rewrite @Sref_idle_false : update. + + Lemma cnt_equiv (cnt : Bvector COUNTER_WIDTH) : + (if CeqWAIT cnt then Bvect_false COUNTER_WIDTH + else N2Bv_sized COUNTER_WIDTH (Bv2N cnt + 1)) = cnt2Bv (Next_cycle (Bv2cnt cnt)). + Proof. + cbv [CeqWAIT]. + destruct (CavaPrelude.eqb (cnt, CNT_WAIT)) eqn:Heq; rewrite Heq. + { specialize @CavaPreludeProperties.eqb_eq with (t := Vec Bit COUNTER_WIDTH) (x := cnt) as H. + apply H in Heq; clear H. + unfold Next_cycle; set (Hc := (Bv2cnt cnt).+1 < WAIT); dependent destruction Hc; + apply Logic.eq_sym in x; move : Logic.eq_refl; rewrite {2 3} x; simpl; intro. + { rewrite /CNT_WAIT bitvec_literal_correct in Heq. + rewrite Heq /Bv2cnt //= Bv2N_N2Bv_sized in x. + 2: { + rewrite /COUNTER_WIDTH; have id := (N2Nat.id 2). + rewrite -id Nat2N.inj_pow //= /Pos.to_nat //= WAIT_PW_2. + apply: N_lt_inj; apply /ltP; by rewrite subn1 ltn_predL WAIT_pos. + } + rewrite Nat2N.id subn1 prednK in x; [ | exact WAIT_pos ]; by rewrite ltnn in x. + } + { unfold cnt2Bv,OCycle0; by simpl. }} + { unfold Next_cycle; set (Hc := (Bv2cnt cnt).+1 < WAIT); dependent destruction Hc; + apply Logic.eq_sym in x; move : Logic.eq_refl; rewrite {2 3} x; simpl; intro. + { unfold cnt2Bv; apply f_equal; simpl. + rewrite N.add_1_r -(N.succ_pos_pred (Pos.of_succ_nat (N.to_nat (Bv2N cnt)))). + apply f_equal; by rewrite predN_of_succ_nat. } + { apply ltn_gt in e,x. + rewrite leq_eqVlt in e; move: e => /orP [/eqP e | e]. + { have HH := (@eqb_iff_neq (Vec Bit (@COUNTER_WIDTH SYS_CFG FIFO_CFG))). + apply HH in Heq. rewrite /CNT_WAIT bitvec_literal_correct in Heq; + rewrite -(N2Bv_sized_Bv2N (@COUNTER_WIDTH SYS_CFG FIFO_CFG) cnt) in Heq. + apply N2Bv_sized_neq_if in Heq. + by rewrite e subn1 -pred_Sn N2Nat.id in Heq. } + { specialize ltn_ord with (n := @WAIT SYS_CFG FIFO_CFG) (i := Ordinal (cnt_bounded cnt)) as H. + rewrite //= in H. + contradict H; apply /negP; by rewrite -ltnNge. + } + } + } + Qed. + + (* -------------- Proofs about Update ------------------------------- *) + Lemma Update_equiv_idle_idle_E (c : circuit_state Update) cnt cref : + (cref =? CNT_REF_PREA) = false -> + let nc := cnt2Bv (Next_cycle (Bv2cnt cnt)) in + let ncref := N2Bv_sized COUNTER_REF_WIDTH (Bv2N cref + 1) in + exists c', step Update_ c (STATE_IDLE_VEC,true,cnt,cref) = + (c',(STATE_IDLE_VEC,nc,ncref)). + Proof. + intros Hcref Hcnt; simpl in c; eapply ex_intro. + cbv [cnt2Bv]; unfold Hcnt; clear Hcnt. + cbv [Update_ Update_s Update_c Update_cref]. + cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + autorewrite with update; vm_compute (false && _). + apply BVEq_iff_neq in Hcref. + specialize @CavaPreludeProperties.eqb_neq with (t := Vec Bit (@COUNTER_REF_WIDTH SYS_CFG FIFO_CFG)) as HH. + apply pair_equal_spec; split. + 2: { + rewrite orb_false_l andb_true_l. + rewrite /CrefPREA_eq; apply HH in Hcref; by rewrite Hcref. + } + cbv [CrefPREA_eq]; apply HH in Hcref as Hcref'; rewrite Hcref'; + vm_compute (false || true && false); simpl; rewrite !VectorSpec.map_id andb_false_r. + apply pair_equal_spec; split; [ done | ]. + vm_compute (orb false false); rewrite orb_false_r; by specialize (cnt_equiv cnt). + Qed. + + Lemma Update_equiv_idle_idle (c : circuit_state Update) cnt cref : + (cref2Bv cref =? CNT_REF_PREA) = false -> + (cref + WAIT < PREA_date) = false -> + let nc := cnt2Bv (Next_cycle (Bv2cnt cnt)) in + let ncref := N2Bv_sized COUNTER_REF_WIDTH (Bv2N (cref2Bv cref) + 1) in + exists c', step Update_ c (STATE_IDLE_VEC,false,cnt,(cref2Bv cref)) = + (c',(STATE_IDLE_VEC,nc,ncref)). + Proof. + intros Hcref Href_service Hcnt; simpl in c; eapply ex_intro. + cbv [cnt2Bv]; unfold Hcnt; clear Hcnt. + cbv [Update_ Update_s Update_c Update_cref]. + cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + autorewrite with update; vm_compute (false && _). + apply BVEq_iff_neq in Hcref. + specialize @CavaPreludeProperties.eqb_neq with (t := Vec Bit (@COUNTER_REF_WIDTH SYS_CFG FIFO_CFG)) as HH. + apply pair_equal_spec; split. + 2: { + rewrite orb_false_l andb_true_l /CrefPREA_eq. + apply HH in Hcref; by rewrite Hcref. + } + cbv [CrefPREA_eq]; apply HH in Hcref as Hcref'; rewrite Hcref'; + vm_compute (false || true && false); simpl; rewrite !VectorSpec.map_id andb_true_r !orb_false_r. + rewrite !CrefPREA_lt_CNT_REF_WAIT_F; [ | done]. + rewrite //=. + apply pair_equal_spec; split; [ done | ]. + rewrite orb_false_r; by specialize (cnt_equiv cnt). + Qed. + + Lemma Update_equiv_idle_ref (c : circuit_state Update) cnt cref e: + (cref =? CNT_REF_PREA) = true -> + let nc := cnt2Bv (Next_cycle (Bv2cnt cnt)) in + let ncref := CNT_REF_NIL in + exists c', (step Update_ c (STATE_IDLE_VEC,e,cnt,cref)) = + (c',(STATE_REF_VEC,nc,ncref)). + Proof. + intros Hcref Hcnt; simpl in c; eapply ex_intro. + cbv [cnt2Bv]; unfold Hcnt; clear Hcnt. + cbv [Update_ Update_s Update_e Update_c Update_cref]. + cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + autorewrite with update; vm_compute (false && _). + apply BVEq_iff_eq in Hcref. + specialize @CavaPreludeProperties.eqb_eq with (t := Vec Bit (@COUNTER_REF_WIDTH SYS_CFG FIFO_CFG)) as HH. + apply pair_equal_spec; split. + 2: { + rewrite orb_false_l andb_true_l. + rewrite /CrefPREA_eq; apply HH in Hcref; by rewrite Hcref. + } + cbv [CrefPREA_eq]; apply HH in Hcref as Hcref'; rewrite Hcref'; + vm_compute (false || true && false); simpl; rewrite !VectorSpec.map_id. + apply pair_equal_spec; split. + 2: { + vm_compute (orb false false); rewrite orb_false_r. + destruct e; [rewrite negb_true | rewrite negb_false]. + { rewrite andb_false_r orb_false_r; by specialize (cnt_equiv cnt). } + { rewrite andb_true_r. + destruct (CrefPREA_lt cref) eqn:Hbug. + { by rewrite Hcref CrefPREA_lt_CNT_REF_PREA in Hbug. } + { rewrite orb_false_r; by specialize (cnt_equiv cnt). } + } + } + done. + Qed. + + Lemma Update_equiv_idle_running (c : circuit_state Update) cnt + (cref : Counter_ref_t) : + (cref2Bv cref =? CNT_REF_PREA) = false -> + (cref + WAIT < PREA_date) = true -> + let nc := CNT_NIL in + let ncref := N2Bv_sized COUNTER_REF_WIDTH (Bv2N (cref2Bv cref) + 1) in + exists c', step Update_ c (STATE_IDLE_VEC,false,cnt,(cref2Bv cref)) = + (c',(STATE_RUN_VEC,nc,ncref)). + Proof. + intros Href_prea Href_service Hcnt; + simpl in c; destruct_products; eapply ex_intro. + cbv [cnt2Bv]; unfold Hcnt; clear Hcnt. + cbv [Update_ Update_s Update_e Update_c Update_cref]. + cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]; + autorewrite with update; fast_simpl_bool. + rewrite !orb_false_l !andb_true_l /CrefPREA_eq. + specialize @CavaPreludeProperties.eqb_neq with (t := Vec Bit (@COUNTER_REF_WIDTH SYS_CFG FIFO_CFG)) as HH. + apply BVEq_iff_neq in Href_prea as Haux; apply HH in Haux. + rewrite Haux //= !orb_false_r andb_true_r !VectorSpec.map_id; clear Haux. + apply pair_equal_spec; split; [ | done]. + apply pair_equal_spec; split; rewrite CrefPREA_lt_CNT_REF_WAIT; try done. + by rewrite orb_true_r. + Qed. + (* ------------------------------------------------------------------ *) + + (* ----------------------------- Cases ------------------------------ *) + Theorem SM_Eq_3b (t : nat) (c_state : State_t) c0 (r0 r : Request_t) r1 + (c1 : Counter_ref_t) (c_req : Bvector REQUEST_WIDTH) : + (c1 + WAIT < PREA_date) = false -> + (nat_of_ord c1 == PREA_date - 1) = false -> + let f_state := (HW_Default_arbitrate t).(Implementation_State) in + let R := HW_Arrival_at t in + R == [:: r] -> EqReq r c_req -> State_Eq (IDLE c0 c1 (r0 :: r1)) c_state -> + let '(f_nextstate,(f_cmd_o,f_req_o)) := Next_state R (IDLE c0 c1 (r0 :: r1)) in + let '(c_nextstate,(_,c_cmd_o,c_req_o)) := step FIFOSM_ c_state (true,c_req) in + (State_Eq f_nextstate c_nextstate) && + (EqCmd f_cmd_o c_cmd_o) && (EqReq f_req_o c_req_o). + Proof. + intros Href_service Href_prea f_state R NF EqR H; unfold FIFOSM_. + unfold R in NF; specialize (HaltIfFull t c_state) as NFULL; move: NF => /eqP NF. + unfold State_t in c_state; simpl in c_state; destruct_products. + rewrite NF //= in NFULL; cbv [get_wra get_rda get_fields] in NFULL. + rename t0 into s, t1 into cnt, t2 into cref, t3 into cr, t4 into wra, t5 into rda. + rewrite /State_Eq /EqMem in H; autounfold with get_state in H; cbn [fst snd] in H. + + move: H => /andP [/andP [/andP [/andP [EqS EqCnt] EqCref] Mem] HQ]. + apply EqQueue_diff_adr in HQ as Hadr. + + apply BVEq_iff_eq in EqS, EqCnt, EqCref; subst s cnt cref. + cbv [LoopInit]; cbn [step fst snd]; simpl_ret; cbv [and2]; cbn [fst snd]. + + assert ((Sidle STATE_IDLE_VEC && CrefPREA_lt (cref2Bv c1)) = false) as Haux; + [ apply CrefPREA_lt_CNT_REF_WAIT_F in Href_service; by rewrite Href_service andb_false_r | ]. + rewrite Haux; clear Haux. + + rewrite (surjective_pairing (step RequestQueue' _ _)). + apply (Queue_WR_NF_NE_snd ((u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21), (u14, (u16, (u18, u19, u17), u15)),u13, rda), wra))) c_req false) in NFULL as S; + apply S in Hadr as S'; clear S. + cbv [get_addr_RequestQueue get_memcells_RequestQueue get_mem_RequestQueue get_memcells] in S'. + destruct S' as [full_o H]; rewrite H; clear H; cbn [fst snd]. + + set tr := nth_default req_null (N.to_nat (Bv2N rda)) _. + apply (NextCR_equiv_IDLE_IDLE (u7, (u8, cr)) (cnt2Bv c0) c1 tr) in Href_service as H. + destruct H as [cs_nextcr H]; rewrite H; clear H; cbn [fst snd]. + + apply cref_preadate_false in Href_prea as Href_prea_. + apply (CmdGen_equiv_idle_to_idle u5 (cnt2Bv c0) c1) in Href_prea_ as H; [ | done ]. + destruct H as [cs_cmdgen H]; rewrite H; clear H; cbn [fst snd]. + + apply (Update_equiv_idle_idle u3 (cnt2Bv c0) c1) in Href_prea_ as H; [ | done]. + destruct H as [cs_update H]; rewrite H; clear H; cbn [fst snd]. + + rewrite /Next_state Href_prea Href_service /State_Eq. + specialize (Queue_WR_NF_NE_fst (u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21),(u14, (u16, (u18, u19, u17), u15)), u13, rda), wra)) c_req false) as S. + apply S in NFULL as H; clear S; apply H in Hadr as H'; clear H; rename H' into H. + destruct H as [cs_requeue' [Hx H]]; destruct Hx as [Hrw [Hwra' Hrda']]. + autounfold with get_state. + + apply /andP; split. + 2 : exact EqReqNil. + apply /andP; split. + 2 : unfold EqCmd; by apply BVEq_iff_eq. + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H. + cbv [get_addr_RequestQueue] in Hwra'; rewrite Hwra'; clear Hwra'. + cbv [get_addr_RequestQueue] in Hrda'; rewrite Hrda'; clear Hrda'. + rewrite /Enqueue /R NF. + apply (EqQueue_aux wra rda r0 r1 r); done. + } + apply /andP; split. + 2 : { + rewrite /EqMem (surjective_pairing (step RequestQueue' _ _)) H Hrda'; cbn [fst snd]; + unfold R; rewrite NF Hrw /Enqueue. + cbv [get_memcells_RequestQueue get_mem_RequestQueue get_memcells]. + apply EqMem_rcons; try done. + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H; + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; cbn [fst snd]. + rewrite //= /Next_cycle_ref. + set Hc := c1.+1 < PREA_date; dependent destruction Hc; + apply Logic.eq_sym in x; move : Logic.eq_refl; rewrite {2 3} x; simpl; intro. + { rewrite /cref2Bv //= Bv2N_N2Bv_sized. + 2: apply to_nat_lt_pow; rewrite Nat2N.id; apply cref_bound. + rewrite /N2Bv_sized. + destruct (N.of_nat c1 + 1)%N eqn:Hbug; + [ rewrite N.add_1_r in Hbug; contradict Hbug; apply N.neq_succ_0 | ]. + apply BVEq_iff_eq; f_equal; lia. + } + { specialize (cref_bound c1) as Hc1_bound. + destruct c1; clear H Hrw Hwra' Hrda' cs_requeue' cs_nextcr; simpl in *. + apply ltn_gt in x; rewrite leq_eqVlt in x; move: x => /orP [/eqP x | x]; [ | lia]. + assert (m = PREA_date.-1); [ lia | ]. + rewrite H in Href_prea; contradict Href_prea; apply not_false_iff_true; by rewrite subn1 eq_refl. + } + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H; + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; cbn [fst snd]. + rewrite /cnt2Bv //=; apply BVEq_iff_eq; f_equal; apply Nat2N.inj_iff. + rewrite /Bv2cnt /Next_cycle //= Bv2N_N2Bv_sized //=. + 2: { + destruct c0; rewrite //= /COUNTER_WIDTH. + rewrite WAIT_PW_2_N; apply N_lt_inj; by apply /ltP. + } + set (Hc := _ < WAIT); dependent destruction Hc; + apply Logic.eq_sym in x; move : Logic.eq_refl; rewrite {2 3} x; simpl; intro; try rewrite Nat2N.id; + try by rewrite Nat2N.id in x; move: Logic.eq_refl; rewrite {2 3}x; simpl; intro. + } + rewrite (surjective_pairing (step RequestQueue' _ _)) H; + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; cbn [fst snd]. + by []. + Qed. + + Theorem SM_Eq_3a (t : nat) (c_state : State_t) c0 (r : Request_t) + (c1 : Counter_ref_t) (c_req : Bvector REQUEST_WIDTH) : + (c1 + WAIT < PREA_date) = false -> + (nat_of_ord c1 == PREA_date - 1) = false -> + let f_state := (HW_Default_arbitrate t).(Implementation_State) in + let R := HW_Arrival_at t in + R == [:: r] -> EqReq r c_req -> State_Eq (IDLE c0 c1 []) c_state -> + let '(f_nextstate,(f_cmd_o,f_req_o)) := Next_state R (IDLE c0 c1 []) in + let '(c_nextstate,(_,c_cmd_o,c_req_o)) := step FIFOSM_ c_state (true,c_req) in + (State_Eq f_nextstate c_nextstate) && + (EqCmd f_cmd_o c_cmd_o) && (EqReq f_req_o c_req_o). + Proof. + intros Href_service Href_prea f_state R NF EqR H; unfold FIFOSM_. + unfold R in NF; specialize (HaltIfFull t c_state) as NFULL; move: NF => /eqP NF. + unfold State_t in c_state; simpl in c_state; destruct_products. + rewrite NF //= in NFULL; cbv [get_wra get_rda get_fields] in NFULL. + rename t0 into s, t1 into cnt, t2 into cref, t3 into cr, t4 into wra, t5 into rda. + rewrite /State_Eq /EqMem in H; autounfold with get_state in H; cbn [fst snd] in H. + + move: H => /andP [/andP [/andP [/andP [EqS EqCnt] EqCref] Mem] Hadr]. + simpl in Hadr. + apply BVEq_iff_eq in EqS, EqCnt, EqCref, Hadr; subst s cnt cref. + cbv [LoopInit]; cbn [step fst snd]; simpl_ret; cbv [and2]; cbn [fst snd]. + + assert ((Sidle STATE_IDLE_VEC && CrefPREA_lt (cref2Bv c1)) = false) as Haux; + [ apply CrefPREA_lt_CNT_REF_WAIT_F in Href_service; by rewrite Href_service andb_false_r | ]. + rewrite Haux; clear Haux. + + rewrite (surjective_pairing (step RequestQueue' _ _)). + specialize (Queue_WR_E_snd ((u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21), (u14, (u16, (u18, u19, u17), u15)),u13, rda), wra))) c_req false) as S. + cbv [get_addr_RequestQueue get_memcells_RequestQueue get_mem_RequestQueue get_memcells] in S. + apply S in Hadr as H; clear S; destruct H as [full_o H]. + rewrite H; clear H; cbn [fst snd]. + + set tr := nth_default req_null (N.to_nat (Bv2N rda)) _. + specialize NextCR_equiv with (c := (u7, (u8, cr))) (cnt := cnt2Bv c0) + (cref := cref2Bv c1) (tr := tr) as [cs_nextcr H]. + rewrite H; cbv [fst]; clear H. cbn [snd]. + + apply cref_preadate_false in Href_prea as Href_prea_. + apply (CmdGen_equiv_idle_to_idle_E u5 (cnt2Bv c0) (cref2Bv c1)) in Href_prea_ as H. + destruct H as [cs_CmdGen H]; rewrite H; clear H; cbn [snd]. + + apply (Update_equiv_idle_idle_E u3 (cnt2Bv c0) (cref2Bv c1)) in Href_prea_ as H. + destruct H as [cs_update H]; rewrite H; clear H; cbn [fst snd]. + + rewrite /Next_state Href_prea Href_service /State_Eq. + specialize (Queue_WR_NF_E_fst (u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21),(u14, (u16, (u18, u19, u17), u15)), u13, rda), wra)) c_req false) as S. + apply S in NFULL as H; clear S; apply H in Hadr as H'; clear H; rename H' into H. + destruct H as [cs_requeue' [Hx H]]; destruct Hx as [Hrw [Hwra' Hrda']]. + autounfold with get_state. + + apply /andP; split. + 2 : exact EqReqNil. + apply /andP; split. + 2 : unfold EqCmd; by apply BVEq_iff_eq. + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H. + cbv [get_addr_RequestQueue] in Hwra'; rewrite Hwra'; clear Hwra'. + cbv [get_addr_RequestQueue] in Hrda'; rewrite Hrda'; clear Hrda'. + simpl; rewrite Hadr; unfold R; rewrite NF //=. + apply /andP; split. + { apply /negPf; apply (@N2Bv_sized_eq_p1_false ADDR_WIDTH rda); + specialize ADDR_WIDTH_pos as Hpos; by move: Hpos => /ltP Hpos. } + by apply BVEq_iff_eq. + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H. + cbv [get_addr_RequestQueue] in Hrda'; rewrite Hrda'; clear Hrda'. + simpl; unfold R; rewrite NF //= /EqMem //= andb_true_r. + rewrite Hrw; autounfold with get_state; rewrite Hadr VectorSpec.map_id. + specialize (@nth_cells_read (Vec Bit REQUEST_WIDTH) ADDR_WIDTH InitMem rda c_req + (Bvect_false REQUEST_WIDTH) c) as H'. + rewrite H'; exact EqR. + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H; + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; cbn [fst snd]. + rewrite //= /Next_cycle_ref. + set Hc := c1.+1 < PREA_date; dependent destruction Hc; + apply Logic.eq_sym in x; move : Logic.eq_refl; rewrite {2 3} x; simpl; intro. + { rewrite /cref2Bv //= Bv2N_N2Bv_sized. + 2: apply to_nat_lt_pow; rewrite Nat2N.id; apply cref_bound. + rewrite /N2Bv_sized. + destruct (N.of_nat c1 + 1)%N eqn:Hbug; + [ rewrite N.add_1_r in Hbug; contradict Hbug; apply N.neq_succ_0 | ]. + apply BVEq_iff_eq; f_equal; lia. + } + { specialize (cref_bound c1) as Hc1_bound. + destruct c1; clear H Hrw Hwra' Hrda' cs_requeue' cs_nextcr; simpl in *. + apply ltn_gt in x; rewrite leq_eqVlt in x; move: x => /orP [/eqP x | x]; [ | lia]. + assert (m = PREA_date.-1); [ lia | ]. + rewrite H in Href_prea; contradict Href_prea; apply not_false_iff_true; by rewrite subn1 eq_refl. + } + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H; + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; cbn [fst snd]. + rewrite /cnt2Bv //=; apply BVEq_iff_eq; f_equal; apply Nat2N.inj_iff. + rewrite /Bv2cnt /Next_cycle //= Bv2N_N2Bv_sized //=. + 2: { + destruct c0; rewrite //= /COUNTER_WIDTH. + rewrite WAIT_PW_2_N; apply N_lt_inj; by apply /ltP. + } + set (Hc := _ < WAIT); dependent destruction Hc; + apply Logic.eq_sym in x; move : Logic.eq_refl; rewrite {2 3} x; simpl; intro; try rewrite Nat2N.id; + try by rewrite Nat2N.id in x; move: Logic.eq_refl; rewrite {2 3}x; simpl; intro. + } + rewrite (surjective_pairing (step RequestQueue' _ _)) H; + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; cbn [fst snd]. + by []. + Qed. + + Theorem SM_Eq_2b (t : nat) (c_state : State_t) c0 r0 r1 + (c1 : Counter_ref_t) (c_req : Bvector REQUEST_WIDTH) r : + (c1 + WAIT < PREA_date) = true -> + (nat_of_ord c1 == PREA_date - 1) = false -> + let f_state := (HW_Default_arbitrate t).(Implementation_State) in + let R := HW_Arrival_at t in + R == [:: r] -> EqReq r c_req -> State_Eq (IDLE c0 c1 (r0 :: r1)) c_state -> + let '(f_nextstate,(f_cmd_o,f_req_o)) := Next_state R (IDLE c0 c1 (r0 :: r1)) in + let '(c_nextstate,(_,c_cmd_o,c_req_o)) := step FIFOSM_ c_state (true,c_req) in + (State_Eq f_nextstate c_nextstate) && + (EqCmd f_cmd_o c_cmd_o) && (EqReq f_req_o c_req_o). + Proof. + intros Href_service Href_prea f_state R NF EqR H; unfold FIFOSM_. + unfold R in NF; specialize (HaltIfFull t c_state) as NFULL; move: NF => /eqP NF. + unfold State_t in c_state; simpl in c_state; destruct_products. + rewrite NF //= in NFULL; cbv [get_wra get_rda get_fields] in NFULL. + rename t0 into s, t1 into cnt, t2 into cref, t3 into cr, t4 into wra, t5 into rda. + rewrite /State_Eq /EqMem in H; autounfold with get_state in H; cbn [fst snd] in H. + + move: H => /andP [/andP [/andP [/andP [EqS EqCnt] EqCref] Mem] HQ]. + apply EqQueue_diff_adr in HQ as Hadr. + + apply BVEq_iff_eq in EqS, EqCnt, EqCref; subst s cnt cref. + cbv [LoopInit]; cbn [step fst snd]; simpl_ret; cbv [and2]. + assert ((Sidle STATE_IDLE_VEC && CrefPREA_lt (cref2Bv c1)) = true) as Haux; [ + rewrite //= ; apply CrefPREA_lt_CNT_REF_WAIT; + [ by apply cref_preadate_false in Href_prea | done ] | ]; rewrite Haux; clear Haux; cbn [snd]. + + rewrite (surjective_pairing (step RequestQueue' _ _)). + specialize (Queue_WR_NF_NE_snd ((u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21), (u14, (u16, (u18, u19, u17), u15)),u13, rda), wra))) c_req true) as S. + cbv [get_addr_RequestQueue get_memcells_RequestQueue get_mem_RequestQueue get_memcells] in S. + apply S in NFULL as S'; [ | done]; clear S; destruct S' as [full_o H]. + rewrite H; clear H; cbn [fst snd]. + + set tr := nth_default req_null (N.to_nat (Bv2N rda)) _. + apply NextCR_equiv_IDLE_RUNNING with (c := (u7, (u8, cr))) (cnt := cnt2Bv c0) + (cref := c1) (tr := tr) in Href_service as H. + 2: by apply cref_preadate_false in Href_prea. + destruct H as [cs_nextcr H]; destruct H as [H Htr]. + rewrite H; clear H; cbv [fst snd]. + + specialize (CmdGen_equiv_idle_to_running u5 (cnt2Bv c0) c1 tr) as S. + specialize Href_service as Href_service_. + apply S in Href_service; clear S; rename Href_service into H. + 2: by apply cref_preadate_false in Href_prea. + destruct H as [cs_CmdGen H]; rewrite H; clear H; cbn [snd]. + + specialize (Update_equiv_idle_running u3 (cnt2Bv c0) c1) as S; + apply S in Href_service_ as S'; clear S. + 2: by apply cref_preadate_false in Href_prea. + destruct S' as [cs_update H]; rewrite H; clear H; cbn [fst snd]. + + rewrite /Next_state Href_prea Href_service_ /State_Eq. + specialize Queue_NF_WR_RD_fst with (c := (u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21),(u14, (u16, (u18, u19, u17), u15)), u13, rda), wra))) (c_req := c_req) as S. + apply S in NFULL as H; clear S. + apply H in Hadr as H'; clear H; rename H' into H. + destruct H as [cs_requeue' [Hx H]]; destruct Hx as [Hrw [Hwra' Hrda']]. + autounfold with get_state. + + apply /andP; split. + 2: { + unfold tr; simpl in Mem; move: Mem => /andP [EqReq_r0 Mem]. + rewrite {2}/get_memcells_RequestQueue /get_mem_RequestQueue /get_memcells in Hrw. + apply (memcell_nch c wra rda c_req req_null) in Hadr as HH. + rewrite /req_null //= in HH. + rewrite VectorSpec.map_id /Bvect_false HH in EqReq_r0. + by rewrite /req_null //=. + } + apply /andP; split. + 2 : unfold EqCmd; by apply BVEq_iff_eq. + apply /andP; split. + 2 : { + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; rewrite Htr; + unfold tr; simpl in Mem; move: Mem => /andP [EqReq_r0 Mem]. + rewrite {2}/get_memcells_RequestQueue /get_mem_RequestQueue /get_memcells in Hrw. + apply (memcell_nch c wra rda c_req req_null) in Hadr as HH. + rewrite /req_null //= in HH. + rewrite VectorSpec.map_id /Bvect_false HH in EqReq_r0. + by rewrite /req_null //=. + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H Hwra' Hrda'. + simpl; rewrite eq_refl. + rewrite /Enqueue /R NF. + simpl in HQ. + specialize (EqQueue_aux wra rda r0 r1 r) as HH. + apply HH in NFULL as HH'; clear HH; try done. + move: HH'; simpl; intros HH. + by move: HH => /andP [_ HH]. + } + apply /andP; split. + 2 : { + rewrite /EqMem (surjective_pairing (step RequestQueue' _ _)) H Hrda' /Enqueue. + simpl; unfold R; rewrite NF //=. + rewrite Hrw eq_refl. + simpl in Mem; move: Mem => /andP [_ Mem]. + apply EqMem_rcons; try done. + simpl in HQ; by move: HQ => /andP [_ HQ]. + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H //=. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end. + rewrite VectorSpec.map_id; cbn [fst snd]. + rewrite /Next_cycle_ref. + set Hc := c1.+1 < WAIT_REF; dependent destruction Hc; + apply Logic.eq_sym in x; move : Logic.eq_refl; rewrite {2 3} x; simpl; intro. + { rewrite /cref2Bv //= Bv2N_N2Bv_sized. + 2: { + unfold COUNTER_REF_WIDTH; rewrite WAIT_REF_PW_N. + destruct c1; simpl; apply N_lt_inj; by apply /ltP. + } + rewrite /N2Bv_sized. + destruct (N.of_nat c1 + 1)%N eqn:Hbug; + [ rewrite N.add_1_r in Hbug; contradict Hbug; apply N.neq_succ_0 | ]. + apply BVEq_iff_eq; f_equal; lia. + } + { apply cref_preadate_false in Href_prea as Href_prea_. + destruct c1; simpl in x,e,Hc0,Href_service_,Href_prea,Href_prea_. + rewrite /cref2Bv VectorSpec.map_id //= in Href_prea_. + apply ltn_gt in x; rewrite leq_eqVlt in x; move: x => /orP [/eqP x | x]. + { assert (m = WAIT_REF.-1); [ lia | ]. + rewrite H0 addnC -ltn_subRL in Href_service_. + rewrite -subn1 ltn_subLR in Href_service_; [ | exact WAIT_REF_pos ]. + contradict Href_service_; apply /negP. + rewrite -leqNgt leq_eqVlt addnC. + specialize WAIT_REF_PREA_date as HH. + apply ltn_trans with (m := PREA_date - WAIT + 1) in HH; + [ by rewrite HH orb_true_r | ]. + rewrite -subnA. + { by rewrite ltn_subrL subn_gt0 WAIT_gt_one PREA_date_pos. } + { exact WAIT_pos. } + { by rewrite leq_eqVlt PREA_date_WAIT orb_true_r. } + } + { rewrite ltnS in x; contradict x; apply /negP; by rewrite -ltnNge. } + } + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H //=. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end. cbn [fst snd]. rewrite VectorSpec.map_id. + rewrite /cnt2Bv; apply BVEq_iff_eq; f_equal. + rewrite /Bv2cnt /Next_cycle //= Bv2N_N2Bv_sized //=. + } + rewrite (surjective_pairing (step RequestQueue' _ _)) H //=. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; cbn [fst snd]. by []. + Qed. *) + + Theorem SM_Eq_2a (t : nat) (c_state : State_t) c0 + (c1 : Counter_ref_t) (c_req : Bvector REQUEST_WIDTH) r : + (c1 + WAIT < PREA_date) = true -> + (nat_of_ord c1 == PREA_date - 1) = false -> + let f_state := (HW_Default_arbitrate t).(Implementation_State) in + let R := HW_Arrival_at t in + R == [:: r] -> EqReq r c_req -> State_Eq (IDLE c0 c1 []) c_state -> + let '(f_nextstate,(f_cmd_o,f_req_o)) := Next_state R (IDLE c0 c1 []) in + let '(c_nextstate,(_,c_cmd_o,c_req_o)) := step FIFOSM_ c_state (true,c_req) in + (State_Eq f_nextstate c_nextstate) && + (EqCmd f_cmd_o c_cmd_o) && (EqReq f_req_o c_req_o). + Admitted. + (* Proof. + intros Href_service Href_prea f_state R NF EqR H; unfold FIFOSM_. + unfold R in NF; specialize (HaltIfFull t c_state) as NFULL; move: NF => /eqP NF. + unfold State_t in c_state; simpl in c_state; destruct_products. + rewrite NF //= in NFULL. + rename t0 into s, t1 into cnt, t2 into cref, t3 into cr, t4 into wra, t5 into rda. + rewrite /State_Eq /EqMem in H; autounfold with get_state in H; cbn [fst snd] in H. + move: H => /andP [/andP [/andP [/andP [EqS EqCnt] EqCref] Mem] Hadr]. + simpl in Hadr. + + apply BVEq_iff_eq in EqS, EqCnt, EqCref, Hadr; subst s cnt cref. + cbv [LoopInit]; cbn [step fst snd]; simpl_ret. + cbv [and2]. + assert ((Sidle STATE_IDLE_VEC && CrefPREA_lt (cref2Bv c1)) = true) as Haux; [ + rewrite //= ; apply CrefPREA_lt_CNT_REF_WAIT; + [ by apply cref_preadate_false in Href_prea | done ] | ]; rewrite Haux; clear Haux. + cbn [snd]. + + rewrite (surjective_pairing (step RequestQueue' _ _)). + specialize (Queue_EMP_WR_snd ((u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21), (u14, (u16, (u18, u19, u17), u15)),u13, rda), wra))) c_req true) as S. + cbv [get_addr_RequestQueue get_memcells_RequestQueue get_mem_RequestQueue get_memcells] in S. + apply S in Hadr as H; clear S; destruct H as [full_o H]. + rewrite H; clear H; cbn [fst snd]. + + set tr := nth_default req_null (N.to_nat (Bv2N rda)) _. + specialize NextCR_equiv with (c := (u7, (u8, cr))) (cnt := cnt2Bv c0) + (cref := cref2Bv c1) (tr := tr) as [cs_nextcr H]. + rewrite H; cbv [fst]; clear H. cbn [snd]. + + apply cref_preadate_false in Href_prea as Href_prea_. + apply (CmdGen_equiv_idle_to_idle_E u5 (cnt2Bv c0) (cref2Bv c1)) in Href_prea_ as H. + destruct H as [cs_CmdGen H]; rewrite H; clear H; cbn [snd]. + + apply (Update_equiv_idle_idle_E u3 (cnt2Bv c0) (cref2Bv c1)) in Href_prea_ as H. + destruct H as [cs_update H]; rewrite H; clear H; cbn [fst snd]. + + cbv [get_rda get_wra get_fields] in NFULL. + rewrite /Next_state Href_prea Href_service /State_Eq. + specialize Queue_NF_EMP_WR_fst with (c := (u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21),(u14, (u16, (u18, u19, u17), u15)), u13, rda), wra))) (c_req := c_req) as S. + apply S in NFULL as H; clear S. apply H in Hadr as H'; clear H; rename H' into H. + destruct H as [cs_requeue' [Hx H]]; destruct Hx as [Hrw [Hwra' Hrda']]. + autounfold with get_state. + + apply /andP; split. + 2 : exact EqReqNil. + apply /andP; split. + 2 : unfold EqCmd; by apply BVEq_iff_eq. + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H Hwra' Hrda'. + simpl; rewrite Hadr; unfold R; rewrite NF //=. + apply /andP; split. + { apply /negPf; apply (@N2Bv_sized_eq_p1_false ADDR_WIDTH rda); + specialize ADDR_WIDTH_pos as Hpos; by move: Hpos => /ltP Hpos. } + by apply BVEq_iff_eq. + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H Hrda'. + simpl; unfold R; rewrite NF //= /EqMem //= andb_true_r. + rewrite Hrw; autounfold with get_state; rewrite Hadr VectorSpec.map_id. + specialize (@nth_cells_read (Vec Bit REQUEST_WIDTH) ADDR_WIDTH InitMem rda c_req + (Bvect_false REQUEST_WIDTH) c) as H'. + rewrite H'; exact EqR. + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H //=. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end. + cbn [fst snd]. + rewrite /Next_cycle_ref. + set Hc := c1.+1 < WAIT_REF; dependent destruction Hc; + apply Logic.eq_sym in x; move : Logic.eq_refl; rewrite {2 3} x; simpl; intro. + { rewrite /cref2Bv //= Bv2N_N2Bv_sized. + 2: { + unfold COUNTER_REF_WIDTH; rewrite WAIT_REF_PW_N. + destruct c1; simpl; apply N_lt_inj; by apply /ltP. + } + rewrite /N2Bv_sized. + destruct (N.of_nat c1 + 1)%N eqn:Hbug; + [ rewrite N.add_1_r in Hbug; contradict Hbug; apply N.neq_succ_0 | ]. + apply BVEq_iff_eq; f_equal; lia. + } + { destruct c1; simpl in x,e,Hc0,Href_prea,Href_prea_,Href_service. + rewrite /cref2Bv VectorSpec.map_id //= in Href_prea_. + apply ltn_gt in x; rewrite leq_eqVlt in x; move: x => /orP [/eqP x | x]. + { assert (m = WAIT_REF.-1); [ lia | ]. + rewrite H0 addnC -ltn_subRL in Href_service. + rewrite -subn1 ltn_subLR in Href_service; [ | exact WAIT_REF_pos ]. + contradict Href_service; apply /negP. + rewrite -leqNgt leq_eqVlt addnC. + specialize WAIT_REF_PREA_date as HH. + apply ltn_trans with (m := PREA_date - WAIT + 1) in HH; + [ by rewrite HH orb_true_r | ]. + rewrite -subnA. + { by rewrite ltn_subrL subn_gt0 WAIT_gt_one PREA_date_pos. } + { exact WAIT_pos. } + { by rewrite leq_eqVlt PREA_date_WAIT orb_true_r. } + } + { rewrite ltnS in x; contradict x; apply /negP; by rewrite -ltnNge. } + } + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H //=. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end. cbn [fst snd]. + rewrite /cnt2Bv; apply BVEq_iff_eq; f_equal. + apply Nat2N.inj_iff. + rewrite /Bv2cnt /Next_cycle //= Bv2N_N2Bv_sized //=. + 2: { + destruct c0; rewrite //= /COUNTER_WIDTH. + rewrite WAIT_PW_2_N; apply N_lt_inj; by apply /ltP. + } + set (Hc := _ < WAIT); dependent destruction Hc; + apply Logic.eq_sym in x; move : Logic.eq_refl; rewrite {2 3} x; simpl; intro; try rewrite Nat2N.id; + try by rewrite Nat2N.id in x; move: Logic.eq_refl; rewrite {2 3}x; simpl; intro. + } + rewrite (surjective_pairing (step RequestQueue' _ _)) H //=. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; cbn [fst snd]. by []. + Qed. *) + + + (* Assuming a non-full regime, i.e., the front-end has yielded a valid request *) + (* If R is non empty than the queue is not full *) + Theorem SM_Eq_1b (t : nat) (c_state : State_t) c0 c1 (c_req : Bvector REQUEST_WIDTH) r0 r1 (r : Request_t) : + (nat_of_ord c1 == PREA_date - 1) = true -> + let f_state := (HW_Default_arbitrate t).(Implementation_State) in + let R := HW_Arrival_at t in + R == [:: r] -> EqReq r c_req -> State_Eq (IDLE c0 c1 (r0 :: r1)) c_state -> + let '(f_nextstate,(f_cmd_o,f_req_o)) := Next_state R (IDLE c0 c1 (r0 :: r1)) in + let '(c_nextstate,(_,c_cmd_o,c_req_o)) := step FIFOSM_ c_state (true,c_req) in + (State_Eq f_nextstate c_nextstate) && + (EqCmd f_cmd_o c_cmd_o) && (EqReq f_req_o c_req_o). + Admitted. + (* Proof. + intros Href_prea f_state R NF EqR H; unfold FIFOSM_. + unfold R in NF; specialize (HaltIfFull t c_state) as NFULL; move: NF => /eqP NF. + unfold State_t in c_state; simpl in c_state; destruct_products. + rewrite NF //= in NFULL; cbv [get_wra get_rda get_fields] in NFULL. + rename t0 into s, t1 into cnt, t2 into cref, t3 into cr, t4 into wra, t5 into rda. + rewrite /State_Eq /EqMem in H; autounfold with get_state in H; cbn [fst snd] in H. + move: H => /andP [/andP [/andP [/andP [EqS EqCnt] EqCref] Mem] HQ]. + apply EqQueue_diff_adr in HQ as Hadr. + + apply BVEq_iff_eq in EqS, EqCnt, EqCref; subst s cnt cref. + cbv [LoopInit]; cbn [step fst snd]; simpl_ret. + + apply cref_preadate_true in Href_prea as Href_prea_; + apply BVEq_iff_eq in Href_prea_ as H'. + cbv [and2]. cbn [fst snd]. + rewrite {1}H' CrefPREA_lt_CNT_REF_PREA andb_false_r. + + rewrite (surjective_pairing (step RequestQueue' _ _)). + specialize (Queue_NEMP_NF_WR_snd ((u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21), (u14, (u16, (u18, u19, u17), u15)),u13, rda), wra))) c_req false) as S. + cbv [get_addr_RequestQueue get_memcells_RequestQueue get_mem_RequestQueue get_memcells] in S. + apply S in NFULL as S'; [ | done]; clear S; destruct S' as [full_o H]. + rewrite H; clear H; cbn [fst snd]. + + set tr := nth_default req_null (N.to_nat (Bv2N rda)) _. + specialize (NextCR_equiv_IDLE_NE_PREA (u7, (u8, cr)) (cnt2Bv c0) (cref2Bv c1) tr) as S. + apply S in Href_prea_ as S'; clear S; destruct S' as [cs_nextcr H]; rewrite H. + + cbn [fst snd]; clear H. + apply (CmdGen_equiv_idle_to_ref u5 (cnt2Bv c0) (cref2Bv c1) false) in Href_prea_ as H. + destruct H as [cs_CmdGen H]; rewrite H; clear H; cbn [snd]. + + apply (Update_equiv_idle_ref u3 (cnt2Bv c0) (cref2Bv c1) false) in Href_prea_ as H. + destruct H as [cs_update H]; rewrite H; clear H; cbn [fst snd]. + + rewrite /Next_state Href_prea /State_Eq. + specialize Queue_NF_WR_fst with (c := (u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21),(u14, (u16, (u18, u19, u17), u15)), u13, rda), wra))) (c_req := c_req) as S. + apply S in NFULL as H; clear S. + destruct H as [cs_requeue' [Hx H]]; destruct Hx as [Hrw [Hwra' Hrda']]. + autounfold with get_state. + + apply /andP; split. + 2 : exact EqReqNil. + apply /andP; split. + 2 : unfold EqCmd; by apply BVEq_iff_eq. + apply /andP; split. + 2 : { + rewrite H /Enqueue /R NF. + cbv [get_addr_RequestQueue] in Hwra'; rewrite Hwra'. + cbv [get_addr_RequestQueue] in Hrda'; rewrite Hrda'. + by apply (EqQueue_aux wra rda r0 r1 r). + } + apply /andP; split. + 2 : { + rewrite H. + cbv [get_addr_RequestQueue] in Hrda'; rewrite Hrda'; clear Hrda'. + rewrite /EqMem Hrw /Enqueue. + autounfold with get_state; unfold R; rewrite NF. + apply EqMem_rcons; done. + } + apply /andP; split. + 2 : { + rewrite H. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end. cbn [fst snd]; simpl; rewrite VectorSpec.map_id. + rewrite /cref2Bv /OCycle0REF //=; by apply BVEq_iff_eq. + } + rewrite H; + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; cbn [fst snd]. by []. + Qed. *) + + Theorem SM_Eq_1a (t : nat) (c_state : State_t) c0 c1 (c_req : Bvector REQUEST_WIDTH) r : + (nat_of_ord c1 == PREA_date - 1) = true -> + let f_state := (HW_Default_arbitrate t).(Implementation_State) in + let R := HW_Arrival_at t in + R == [:: r] -> EqReq r c_req -> State_Eq (IDLE c0 c1 []) c_state -> + let '(f_nextstate,(f_cmd_o,f_req_o)) := Next_state R (IDLE c0 c1 []) in + let '(c_nextstate,(_,c_cmd_o,c_req_o)) := step FIFOSM_ c_state (true,c_req) in + (State_Eq f_nextstate c_nextstate) && + (EqCmd f_cmd_o c_cmd_o) && (EqReq f_req_o c_req_o). + Admitted. + (* Proof. + intros Href_prea f_state R NF EqR H; unfold FIFOSM_. + unfold R in NF; specialize (HaltIfFull t c_state) as NFULL; move: NF => /eqP NF. + unfold State_t in c_state; simpl in c_state; destruct_products. + rewrite NF //= in NFULL; cbv [get_wra get_rda get_fields] in NFULL. + rename t0 into s, t1 into cnt, t2 into cref, t3 into cr, t4 into wra, t5 into rda. + rewrite /State_Eq /EqMem in H; autounfold with get_state in H; cbn [fst snd] in H. + move: H => /andP [/andP [/andP [/andP [EqS EqCnt] EqCref] Mem] Hadr]. + + apply BVEq_iff_eq in EqS, EqCnt, EqCref,Hadr; subst s cnt cref. + cbv [LoopInit]; cbn [step fst snd]; simpl_ret. + + apply cref_preadate_true in Href_prea as Href_prea_; + apply BVEq_iff_eq in Href_prea_ as H'. + cbv [and2]. cbn [fst snd]. + rewrite {1}H' CrefPREA_lt_CNT_REF_PREA andb_false_r. + + rewrite (surjective_pairing (step RequestQueue' _ _)). + specialize (Queue_EMP_WR_snd ((u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21), (u14, (u16, (u18, u19, u17), u15)),u13, rda), wra))) c_req false) as S. + cbv [get_addr_RequestQueue get_memcells_RequestQueue get_mem_RequestQueue get_memcells] in S. + apply S in Hadr as H; clear S; destruct H as [full_o H]. + rewrite H; clear H; cbn [fst snd]. + + set tr := nth_default req_null (N.to_nat (Bv2N rda)) _. + specialize NextCR_equiv with (c := (u7, (u8, cr))) (cnt := cnt2Bv c0) + (cref := cref2Bv c1) (tr := tr) as [cs_nextcr H]. + rewrite H; cbv [fst snd]; clear H. + + apply (CmdGen_equiv_idle_to_ref u5 (cnt2Bv c0) (cref2Bv c1) true) in Href_prea_ as H. + destruct H as [cs_CmdGen H]; rewrite H; clear H; cbn [snd]. + + apply (Update_equiv_idle_ref u3 (cnt2Bv c0) (cref2Bv c1) true) in Href_prea_ as H. + destruct H as [cs_update H]; rewrite H; clear H. + + rewrite /Next_state Href_prea /State_Eq. + specialize Queue_NF_WR_fst with (c := (u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21),(u14, (u16, (u18, u19, u17), u15)), u13, rda), wra))) (c_req := c_req) as S. + apply S in NFULL as H; clear S. + destruct H as [cs_requeue' [Hx H]]; destruct Hx as [Hrw [Hwra' Hrda']]. + autounfold with get_state. + + apply /andP; split. + 2 : exact EqReqNil. + apply /andP; split. + 2 : unfold EqCmd; by apply BVEq_iff_eq. + apply /andP; split. + 2 : { + rewrite /Enqueue. + rewrite (surjective_pairing (step RequestQueue' _ _)) H. + cbv [get_addr_RequestQueue] in Hwra'; rewrite Hwra'; clear Hwra'. + cbv [get_addr_RequestQueue] in Hrda'; rewrite Hrda'; clear Hrda'. + rewrite //= /R NF //= Hadr. + apply /andP; split. + { apply /negPf; apply (@N2Bv_sized_eq_p1_false ADDR_WIDTH rda); + specialize ADDR_WIDTH_pos as Hpos; by move: Hpos => /ltP Hpos. } + by apply BVEq_iff_eq. + } + apply /andP; split. + 2 : { + rewrite /Enqueue. + rewrite (surjective_pairing (step RequestQueue' _ _)) H. + cbv [get_addr_RequestQueue] in Hrda'; rewrite Hrda'; clear Hrda'. + simpl; unfold R; rewrite NF //= /EqMem //= andb_true_r VectorSpec.map_id. + rewrite Hrw; autounfold with get_state; rewrite Hadr. + specialize (@nth_cells_read (Vec Bit REQUEST_WIDTH) ADDR_WIDTH InitMem rda c_req + (Bvect_false REQUEST_WIDTH) c) as HH. + rewrite HH; exact EqR. + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; cbn [fst snd]. + rewrite //= VectorSpec.map_id. + rewrite /cref2Bv /OCycle0REF //=; by apply BVEq_iff_eq. + } + rewrite (surjective_pairing (step RequestQueue' _ _)) H. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; cbn [fst snd]. + by []. + Qed. *) + + Theorem SM_Eq_NFULL (t : nat) (c_state : State_t) (f_req: Request_t) + (c_req : Bvector REQUEST_WIDTH) (push : bool) : + let f_state := (HW_Default_arbitrate t).(Implementation_State) in + let R := HW_Arrival_at t in + R == [:: f_req] -> EqReq f_req c_req -> State_Eq f_state c_state -> + let '(f_nextstate,(f_cmd_o,f_req_o)) := Next_state R f_state in + let '(c_nextstate,(_,c_cmd_o,c_req_o)) := step FIFOSM_ c_state (true,c_req) in + (State_Eq f_nextstate c_nextstate) && + (EqCmd f_cmd_o c_cmd_o) && (EqReq f_req_o c_req_o). + Proof. + destruct (f_state) eqn:Hf_state. + { destruct (nat_of_ord c0 == PREA_date - 1) eqn:Hcref_prea; move: Hcref_prea. + { destruct r eqn:HR. + { apply SM_Eq_1a. } + { apply SM_Eq_1b. } + } + { destruct (c0 + WAIT < PREA_date) eqn:Hcref_service; move: Hcref_service. + { destruct r eqn:HR. + { apply SM_Eq_2a. } + { apply SM_Eq_2b. } + } + { destruct r eqn:HR. + { apply SM_Eq_3a. (* Case 3a: IDLE -> IDLE (empty queue )*) } + { apply SM_Eq_3b. (* Case 3b: IDLE -> IDLE (non empty queue) *) } + } + } + } + { destruct (nat_of_ord c == OACT_date) eqn:Hact_date. + { destruct r eqn:HR. + { admit. (* Case 4a : RUNNING -> RUNNING (ACT) (empty queue) *) } + { admit. (* Case 4b : RUNNING -> RUNNING (ACT) (non empty queue) *)} + } + { destruct (nat_of_ord c == OCAS_date) eqn:Hcas_date. + { destruct r eqn:HR. + { admit. (* Case 5a : RUNNING -> RUNNING (CAS) (empty queue )*) } + { admit. (* Case 5b : RUNNING -> RUNNING (CAS) (non-empty queue) *)} + } + { destruct (nat_of_ord c == WAIT.-1) eqn:Hend_date. + { destruct r eqn:HR. + { admit. (* Case 6a : RUNNING -> IDLE (empty queue) *) } + { admit. (* Case 6b : RUNNING -> IDLE (non empty queue) *)} + } + { destruct r eqn:HR. + { admit. (* Case 7a : RUNNING -> RUNNING (empty queue) *) } + { admit. (* Case 7b : RUNNING -> RUNNING (non empty queue) *) } + } + } + } + } + { destruct (nat_of_ord c == OREF_date) eqn:Href_date. + { destruct r eqn:HR. + { admit. (* Case 8a REFRESHING -> REFRESHING (REF) *)} + { admit. (* Case 8b REFRESHING -> REFRESHING (REF) *)} + } + { destruct (nat_of_ord c == OENDREF_date) eqn:Hendref_date. + { destruct r eqn:HR. + { admit. (* Case 9a REFRESHING -> IDLE*) } + { admit. (* Case 9b REFRESHING -> IDLE *) } + } + { destruct r eqn:HR. + { admit. (* Case 10a REFRESHING -> REFRESHING (REF) *) } + { admit. (* Case 10b REFRESHING -> REFRESHING (REF) *) } + } + } + } + Admitted. + +End EquivalenceProof. \ No newline at end of file diff --git a/framework/CavaDRAM/CavaFIFOREF.v b/framework/CavaDRAM/CavaFIFOREF.v index c1ba51b..7f067eb 100644 --- a/framework/CavaDRAM/CavaFIFOREF.v +++ b/framework/CavaDRAM/CavaFIFOREF.v @@ -1,6 +1,8 @@ -From CavaDRAM Require Import CavaReqQueue CavaSM CavaCommonInstances. -From DRAM Require Import FIFO. -From Coq Require Import BinaryString HexString NArith. +Set Warnings "-notation-overridden,-parsing". +From CavaDRAM Require Import CavaReqQueue CavaCommonInstances Util CavaSystem Memory. +From CoqDRAM Require Import FIFO. +From Coq Require Import BinaryString HexString NArith Program.Equality. +From Cava Require Import Cava. Section CavaFIFOREF. @@ -9,13 +11,24 @@ Section CavaFIFOREF. Context {SYS_CFG : System_configuration}. Context {FIFO_CFG : FIFO_configuration}. + Import CavaReqQueue.DataNotation. + Open Scope data_scope. + Definition STATE_WIDTH := 2. - Definition COUNTER_WIDTH := - if (powerOfTwo WAIT) then Nat.log2 WAIT else (Nat.log2 WAIT + 1). + Definition COUNTER_WIDTH := Nat.log2 (WAIT). + Definition CNT_WAIT := Vec.bitvec_literal (#D (N.of_nat (WAIT - 1)) | COUNTER_WIDTH). + Definition CNT_ACT := Vec.bitvec_literal (#D (N.of_nat ACT_date) | COUNTER_WIDTH). + Definition CNT_CAS := Vec.bitvec_literal (#D (N.of_nat CAS_date) | COUNTER_WIDTH). + Definition CNT_NIL := Vec.bitvec_literal (#D (N.of_nat 0) | COUNTER_WIDTH). + Definition CNT_NIL_VEC := Vector.const false COUNTER_WIDTH. + + (* Definition COUNTER_REF_WIDTH := Nat.log2 (WAIT_REF). *) Definition COUNTER_REF_WIDTH := - if (powerOfTwo PREA_date) then Nat.log2 PREA_date else (Nat.log2 PREA_date + 1). + if Nat.pow 2 (Nat.log2 (PREA_date + (WAIT - 1))) == (PREA_date + (WAIT - 1)) + then Nat.log2 (PREA_date + (WAIT - 1)) + else (Nat.log2 (PREA_date + (WAIT - 1))).+1. Definition state := Vec Bit STATE_WIDTH. Definition counter := Vec Bit COUNTER_WIDTH. @@ -26,9 +39,6 @@ Section CavaFIFOREF. Definition counter_t := signal counter. Definition counter_ref_t := signal counter_ref. - Import CavaSM.DataNotation. - Open Scope data_scope. - Definition NOP_VEC := (#B "11111" | DRAM_CMD_WIDTH). Definition NOP := Vec.bitvec_literal NOP_VEC. Definition PRE_VEC := (#B "10010" | DRAM_CMD_WIDTH). @@ -44,14 +54,8 @@ Section CavaFIFOREF. Definition REF_VEC := (#B "10001" | DRAM_CMD_WIDTH). Definition REF := Vec.bitvec_literal REF_VEC. - Definition CNT_WAIT := Vec.bitvec_literal (#D (N.of_nat (WAIT - 1)) | COUNTER_WIDTH). - Definition CNT_ACT := Vec.bitvec_literal (#D (N.of_nat ACT_date) | COUNTER_WIDTH). - Definition CNT_CAS := Vec.bitvec_literal (#D (N.of_nat CAS_date) | COUNTER_WIDTH). - Definition CNT_NIL := Vec.bitvec_literal (#D (N.of_nat 0) | COUNTER_WIDTH). - Definition CNT_NIL_VEC := Vector.const false COUNTER_WIDTH. - Definition CNT_REF_WAIT := Vec.bitvec_literal (#D (N.of_nat (WAIT - 1)) | COUNTER_REF_WIDTH). - Definition CNT_REF_PREA := Vec.bitvec_literal (#D (N.of_nat PREA_date) | COUNTER_REF_WIDTH). + Definition CNT_REF_PREA := Vec.bitvec_literal (#D (N.of_nat (PREA_date - 1)) | COUNTER_REF_WIDTH). Definition CNT_REF_REF := Vec.bitvec_literal (#D (N.of_nat REF_date) | COUNTER_REF_WIDTH). Definition CNT_REF_END := Vec.bitvec_literal (#D (N.of_nat END_REF_date) | COUNTER_REF_WIDTH). Definition CNT_REF_NIL := Vec.bitvec_literal (#D (N.of_nat 0) | COUNTER_REF_WIDTH). @@ -176,15 +180,6 @@ Section CavaFIFOREF. mux_ref_sel <- or2 (t3,t4) ;; mux2 mux_ref_sel (mux_idle_run_out,STATE_REF). - Definition Update_e (input : state_t * empty_t * counter_t * counter_ref_t) : - cava (empty_t) := let '(s,e,_,cref) := input in - s_idle <- Sidle s ;; - c_service <- CrefPREA_lt cref ;; - ne <- inv e ;; - t0 <- and2 (c_service,ne) ;; - mux_sel <- and2 (s_idle,t0) ;; - mux2 mux_sel (zero,one). - Definition Update_c (input : state_t * empty_t * counter_t * counter_ref_t) : cava (counter_t) := let '(s,e,c,cref) := input in s_idle <- Sidle s ;; @@ -214,35 +209,39 @@ Section CavaFIFOREF. crefp1 <- incrN cref ;; mux2 mux2_sel (crefp1,CNT_REF_NIL). - Definition Update : Circuit + Definition Update_ : Circuit (state_t * empty_t * counter_t * counter_ref_t) - (state_t * empty_t * counter_t * counter_ref_t) := + (state_t * counter_t * counter_ref_t) := Comb (fun '(s,e,c,cref) => s' <- Update_s (s,e,c,cref) ;; - e' <- Update_e (s,e,c,cref) ;; c' <- Update_c (s,e,c,cref) ;; cref' <- Update_cref (s,e,c,cref) ;; - ret (s',e',c',cref') + ret (s',c',cref') ). - Definition FIFOSM : Circuit - (signal Bit * request_t) (signal Bit * command_t * request_t) := - let pop_init : combType (Bit) := false in + Definition FIFOSM_ : Circuit + (signal Bit * signal (Vec Bit REQUEST_WIDTH)) + (signal Bit * signal (Vec Bit DRAM_CMD_WIDTH) * signal (Vec Bit REQUEST_WIDTH)) := let s_init : combType (state) := STATE_IDLE_VEC in let cnt_init : combType (counter) := CNT_NIL_VEC in let cref_init : combType (counter_ref) := CNT_REF_NIL_VEC in - LoopInit pop_init ( (* Rp, Rd, p *) - RequestQueue >==> (* full, data, empty *) - LoopInit s_init ( (* full, data, empty, s *) - LoopInit cnt_init ( (* full, data, empty, s, cnt *) - LoopInit cref_init ( (* full, data, empty, s, cnt, cref *) - Comb (fun '(full,data,empty,s,c,cref) => ret (full,s,empty,c,cref,(s,empty,c,cref,data))) - >==> Second (NextCR) >==> - Comb (fun '(full,s,e,c,cref,cr) => ret (full,cr,s,e,c,cref,(s,e,c,cref,cr))) - >==> Second (CmdGen) >==> - Comb (fun '(full,cr,s,e,c,cref,cmd) => ret (full,cmd,cr,(s,e,c,cref))) - >==> Second (Update) >==> - Comb (fun '(full,cmd,cr,(ns,np,nc,ncref)) => ret (full,cmd,cr,np,ns,nc,ncref)))))). + LoopInit s_init ( (* Rp, Rd, s *) + LoopInit cnt_init ( (* Rp, Rd, s, cnt *) + LoopInit cref_init ( (* Rp, Rd, s, cref, cref *) + Comb (fun '(Rp,Rd,s,cnt,cref) => + s_idle <- Sidle s ;; + c_service <- CrefPREA_lt cref ;; + pop <- and2 (s_idle,c_service) ;; + ret(s,cnt,cref,(Rp,Rd,pop)) + ) >==> + Second (RequestQueue') >==> + Comb (fun '(s,c,cref,(full,data,empty)) => ret (full,s,empty,c,cref,(s,empty,c,cref,data))) + >==> Second (NextCR) >==> + Comb (fun '(full,s,e,c,cref,cr) => ret (full,cr,s,e,c,cref,(s,e,c,cref,cr))) + >==> Second (CmdGen) >==> + Comb (fun '(full,cr,s,e,c,cref,cmd) => ret (full,cmd,cr,(s,e,c,cref))) + >==> Second (Update_) >==> + Comb (fun '(full,cmd,cr,(ns,nc,ncref)) => ret (full,cmd,cr,ns,nc,ncref))))). End CavaFIFOREF. @@ -256,18 +255,32 @@ Section SimCodeGen. Program Instance FIFO_CFG : FIFO_configuration := { (* orig: 65 *) - WAIT := 27 + WAIT := 32; }. - Definition sm_interface - := sequentialInterface "sm_interface" + Definition fifo_interface + := sequentialInterface "fifo_interface" "clk" PositiveEdge "rst" PositiveEdge [mkPort "Rp" Bit; mkPort "Rd" (Vec Bit REQUEST_WIDTH)] [mkPort "full_o" Bit; mkPort "cmd_o" (Vec Bit DRAM_CMD_WIDTH); mkPort "CR" (Vec Bit REQUEST_WIDTH)]. - Definition sm_netlist := makeCircuitNetlist sm_interface FIFOSM. + Definition sm_netlist := makeCircuitNetlist fifo_interface FIFOSM_. - (* Import CavaSM.DataNotation. + (* Compute circuit_state memqueue'. + Compute circuit_state RequestQueue'. + Compute circuit_state FIFOSM_. + + Compute circuit_state NextCR. *) + + (* Compute circuit_state FIFOSM. *) + + (* Compute circuit_state memqueue'. *) + + (* Compute circuit_state memqueue'. *) + (* Compute circuit_state *) + + (* + Import CavaSM.DataNotation. Open Scope data_scope. Definition Rsim1_wr := #H "00fe468b00000" | REQUEST_WIDTH. Definition Rsim1_rd := #H "00fe468b10000" | REQUEST_WIDTH. @@ -321,7 +334,7 @@ Section SimCodeGen. Vector.t bool COUNTER_REF_WIDTH)) := map (fun '(s,e,cnt,cref) => (state2string s,e,Bv2N cnt,Bv2N cref)) e. - Compute map_queue_out (simulate RequestQueue [ + (* Compute map_queue_out (simulate RequestQueue [ (true,Rsim1_wr,false); (true,Rsim1_rd,false) ]). @@ -338,23 +351,25 @@ Section SimCodeGen. Compute (map_update_out (simulate Update [ (STATE_IDLE_VEC,true,CNT_NIL,CNT_REF_NIL) - ])). + ])). *) + Open Scope seq_scope. Definition sm_inputs := [ (true,Rsim1_wr); - (true,Rsim1_rd) - (* (true,Rsim1_rd); *) - (* (true,Rsim2_wr); *) - (* (true,Rsim2_rd); *) - (* (true,Rsim3_wr); *) - (* (true,Rsim3_rd) *) + (true,Rsim1_rd); + (true,Rsim2_wr); + (true,Rsim2_rd); + (true,Rsim3_wr); + (true,Rsim3_rd) ] ++ (repeat (false,REQUEST_NIL) 20). + Close Scope seq_scope. Compute (map_out (simulate FIFOSM sm_inputs)). Definition expected_out := simulate FIFOSM sm_inputs. Definition sm_tb := - testBench "sm_tb" (sm_interface) sm_inputs expected_out. *) + testBench "sm_tb" (sm_interface) sm_inputs expected_out. + *) End SimCodeGen. \ No newline at end of file diff --git a/framework/CavaDRAM/CavaReqQueue.v b/framework/CavaDRAM/CavaReqQueue.v index bf1b465..8200b90 100644 --- a/framework/CavaDRAM/CavaReqQueue.v +++ b/framework/CavaDRAM/CavaReqQueue.v @@ -1,22 +1,77 @@ -From Cava Require Export Cava CavaProperties. -From Coq Require Export Vectors.Fin Bool.Bool Program.Basics BinaryString HexString NArith. -From CavaDRAM Require Export CavaSystem CavaMemory CavaSubtractor. +From Cava Require Import Cava CavaProperties. +From Coq Require Import Vectors.Fin Bool.Bool Program BinaryString HexString NArith. +From CavaDRAM Require Import CavaSystem CavaMemory CavaSubtractor Memory. +From mathcomp Require Import ssreflect. Export Circuit.Notations. +Module DataNotation. +Declare Scope data_scope. +Delimit Scope data_scope with ds. +Infix "++" := Vector.append. +Notation "'#B' n '|' w" := (N2Bv_sized w (BinaryString.Raw.to_N n 0)) (at level 0) : data_scope. +Notation "'#D' n '|' w" := (N2Bv_sized w n) (at level 0) : data_scope. +Notation "'#H' n '|' w" := (N2Bv_sized w (HexString.Raw.to_N n 0)) (at level 0) : data_scope. +End DataNotation. + Section CavaReqQueue. Context {CAVA_SYS : CavaSystem}. Context {signal : SignalType -> Type} {semantics : Cava signal}. - Definition REQUEST_WIDTH := FE_ADDR_WIDTH + FE_CMD_WIDTH + FE_ID_WIDTH. + Import DataNotation. + Open Scope data_scope. + + Definition REQUEST_WIDTH := FE_CMD_WIDTH + BANK_ADDR_WIDTH + COL_ADDR_WIDTH + ROW_ADDR_WIDTH. + Definition request := Vec Bit REQUEST_WIDTH. + Definition request_t := signal request. + Definition REQUEST_NIL := Vec.bitvec_literal (#D 0 | REQUEST_WIDTH). + + Definition row_t := signal (Vec Bit ROW_ADDR_WIDTH). + Definition col_t := signal (Vec Bit COL_ADDR_WIDTH). + Definition bank_t := signal (Vec Bit BANK_ADDR_WIDTH). + Definition reqtype_t := signal (Vec Bit FE_CMD_WIDTH). + + Definition StripRequest : Circuit (request_t) (row_t * col_t * bank_t * reqtype_t) := + Comb (fun req => rV <- unpackV req ;; + row <- packV (slice_default defaultSignal rV 0 ROW_ADDR_WIDTH) ;; (* bits 0 to 16 *) + col <- packV (slice_default defaultSignal rV ROW_ADDR_WIDTH COL_ADDR_WIDTH) ;; (* bits 17 to 26 *) + bank <- packV (slice_default defaultSignal rV (ROW_ADDR_WIDTH + COL_ADDR_WIDTH) BANK_ADDR_WIDTH) ;; + type <- packV (slice_default defaultSignal rV (ROW_ADDR_WIDTH + COL_ADDR_WIDTH + BANK_ADDR_WIDTH) FE_CMD_WIDTH) ;; + ret(row,col,bank,type) + ). + Definition ADDR_WIDTH := Nat.log2 QUEUE_MAX_SIZE. + Lemma ADDR_WIDTH_pos : + 0 < ADDR_WIDTH. + Proof. + unfold ADDR_WIDTH; apply Nat.log2_pos. + by specialize QUEUE_MAX_SIZE_GT_1. + Qed. + + Definition READ_REQUEST := Vec.bitvec_literal (#D 1 | FE_CMD_WIDTH). + Definition WRITE_REQUEST := Vec.bitvec_literal (#D 0 | FE_CMD_WIDTH). + + Definition command := Vec Bit DRAM_CMD_WIDTH. + Definition command_t := signal command. + + Definition ReqType (input : signal (Vec Bit FE_CMD_WIDTH)) : cava (signal Bit) := + CavaPrelude.eqb (input,WRITE_REQUEST). + + Definition RequestType (r : request_t) : cava (signal Bit) := + rV <- unpackV r ;; + type <- packV (slice_default defaultSignal rV (ROW_ADDR_WIDTH + COL_ADDR_WIDTH + BANK_ADDR_WIDTH) FE_CMD_WIDTH) ;; + ReqType type. + Definition memqueue := memory_dp (Vec Bit REQUEST_WIDTH) ADDR_WIDTH (QUEUE_MAX_SIZE - 1). - (* A bitvector of length ADDR_WIDTH containing the value of WAIT *) + Definition InitMem (n : nat) := Bvect_false REQUEST_WIDTH. + + Definition memqueue' := Memory' (Vec Bit REQUEST_WIDTH) ADDR_WIDTH 1 InitMem. + Definition FullVEC := Vec.bitvec_literal (N2Bv_sized ADDR_WIDTH (N.of_nat QUEUE_MAX_SIZE - 1)). Definition EmptyVec := Vec.bitvec_literal (N2Bv_sized ADDR_WIDTH 0). @@ -44,43 +99,44 @@ Section CavaReqQueue. mux2 en (ptr,ptr_p1) ). - Definition RequestQueue (* this is the right one *) - : Circuit - ( signal Bit - * signal (Vec Bit REQUEST_WIDTH) - * signal Bit) - ( signal Bit - * signal (Vec Bit REQUEST_WIDTH) - * signal Bit) := - let addr_init : combType (Vec Bit (ADDR_WIDTH)) := - (Vector.const zero (ADDR_WIDTH)) in + Definition req_null := (Vector.const false REQUEST_WIDTH). + + Definition RequestQueue' : Circuit + ( signal Bit * signal (Vec Bit REQUEST_WIDTH) * signal Bit) (* pop_i *) + ( signal Bit * signal (Vec Bit REQUEST_WIDTH) * signal Bit) (* empty *) + := let addr_init : combType (Vec Bit ADDR_WIDTH) := (Vector.const zero ADDR_WIDTH) in LoopInit addr_init ( (* push_i,data_i,pop_i,wr_ad *) - LoopInit addr_init ( (* push_i, data_i, pop_i, wr_ad,rd_zadr *) + LoopInit addr_init ( (* push_i, data_i, pop_i, wr_ad,rd_adr *) Comb (fun '(push_i,data_i,pop_i,wr_ad,rd_ad) => ret (push_i,data_i,pop_i,(wr_ad,rd_ad))) >==> Second (Comb fork2 >==> (Second FullEmptyLogic)) >==> Comb (fun '(push_i, data_i, pop_i, ((wr_ad, rd_ad), (full_o, empty_o))) => + (* Read Enable Logic *) n_empt <- inv empty_o ;; rd_en <- and2 (pop_i,n_empt) ;; - (* can also write if one element will be poped *) + (* Write Enable Logic *) n_full <- inv full_o ;; t0 <- and2(full_o,rd_en) ;; t1 <- or2 (t0,n_full) ;; wr_en <- and2 (push_i,t1) ;; - ret (full_o,empty_o,wr_ad,wr_en,rd_ad,rd_en,(data_i,wr_ad,rd_ad,wr_en))) - >==> Second (memqueue) - >==> Comb (fun '(full_o, empty_o,wr_ad,w_en,r_ad,r_en,data_o) => - ret (full_o,data_o,empty_o,((wr_ad,w_en),(r_ad,r_en)))) + (* Builds the Read Port Vector *) + vec_nil <- (Vec.nil (A := (Vec Bit ADDR_WIDTH))) ;; + rd_ad_vec <- Vec.cons rd_ad vec_nil ;; + (* Returns *) + ret (full_o,empty_o,wr_ad,wr_en,rd_ad,rd_en,(rd_ad_vec,(data_i,wr_ad,wr_en)))) + >==> Second (memqueue') + >==> Comb (fun '(full_o,empty_o,wr_ad,w_en,r_ad,r_en,data_o) => + ret (full_o,data_o,empty_o,((wr_ad,w_en),(r_ad,r_en))) + ) >==> Second (First (incr_pointr) >==> Second (incr_pointr)) >==> Second (Comb(fork2) >==> First(FullEmptyLogic)) - (* the empty signal is purposely delayed *) + (* full is calculated based on the new address values *) >==> Comb (fun '(full_o,data_o,empty_o,(n_full_o, n_empty_o,(n_wr_ad,n_rd_ad))) => - ret (n_full_o,data_o,empty_o,n_wr_ad,n_rd_ad)) - ) - ). + ret (n_full_o,data_o,empty_o,n_wr_ad,n_rd_ad)))). End CavaReqQueue. Section CodeGeneration. + Existing Instance CavaCombinationalNet. (* Definition queue_interface diff --git a/framework/CavaDRAM/CavaReqQueueProperties.v b/framework/CavaDRAM/CavaReqQueueProperties.v new file mode 100644 index 0000000..280751c --- /dev/null +++ b/framework/CavaDRAM/CavaReqQueueProperties.v @@ -0,0 +1,424 @@ +Set Printing Projections. +Set Warnings "-notation-overridden,-parsing". + +From CavaDRAM Require Import CavaReqQueue CavaCommonInstances CavaSubtractor Step CavaSystem Memory Util UtilSM. +From Coq Require Import Program BinaryString HexString NArith Bool. +From Cava Require Import Cava CavaProperties Util.Vector Util.Tactics. +From mathcomp Require Import ssreflect ssrnat ssrbool eqtype fintype ssrZ zify ring. + +Section CavaReqQueueProperties. + + Context {signal : SignalType -> Type} {semantics : Cava signal}. + (* From Cava *) + (* Context {combsemantics : CombinationalSemantics}. *) + Existing Instance CombinationalSemantics. + (* From CavaDRAM*) + Context {CAVA_SYS : CavaSystem}. + + Import Memory.Properties BvectorNotations. + Open Scope Bvector_scope. + + Lemma size_nat_qms : + N.size_nat (N.of_nat QUEUE_MAX_SIZE - 1) <= Nat.log2 QUEUE_MAX_SIZE. + Proof. + rewrite N.sub_1_r -Nat2N.inj_pred. + apply /leP; apply N.size_nat_le_nat. + rewrite QUEUE_MAX_SIZE_PW2. + apply /ltP; rewrite ltn_predL; apply /ltP. + exact QUEUE_MAX_SIZE_GT_0. + Qed. + + Lemma size_nat_qms_sub (a b: Bvector ADDR_WIDTH) : + (Bv2N b < Bv2N a)%N -> + N.size_nat (N.of_nat QUEUE_MAX_SIZE - (Bv2N a - Bv2N b)) <= ADDR_WIDTH. + Proof. + intros Hlt; apply /leP. + destruct (Bv2N b) eqn:Hb0, (Bv2N a) eqn:Ha0; try done; + apply N.size_nat_le; unfold ADDR_WIDTH; rewrite QUEUE_MAX_SIZE_PW2_N; try rewrite N.sub_0_r. + { apply N.sub_lt; [ | done]. + unfold ADDR_WIDTH in a,b. + specialize (@Bv2N_upper_bound_nat (Nat.log2 QUEUE_MAX_SIZE) a) as Ha. + rewrite QUEUE_MAX_SIZE_PW2 in Ha. + rewrite Ha0 in Ha. + apply to_nat_lt_of_nat in Ha. + apply N.le_lteq; left; exact Ha. + } + { apply N.sub_lt. + 2: apply N.lt_add_lt_sub_l; rewrite N.add_0_r; lia. + unfold ADDR_WIDTH in a,b. + specialize (@Bv2N_upper_bound_nat (Nat.log2 QUEUE_MAX_SIZE) a) as Ha. + rewrite QUEUE_MAX_SIZE_PW2 in Ha. + specialize (@Bv2N_upper_bound_nat (Nat.log2 QUEUE_MAX_SIZE) b) as Hb. + rewrite QUEUE_MAX_SIZE_PW2 in Hb. + apply to_nat_lt_of_nat in Ha,Hb; rewrite Ha0 in Ha; rewrite Hb0 in Hb. + apply N.le_sub_le_add_l; rewrite N.add_comm. + apply N.lt_trans with (m := N.of_nat (@QUEUE_MAX_SIZE CAVA_SYS)) (n := N.pos p0) + (p := N.add (N.of_nat (@QUEUE_MAX_SIZE CAVA_SYS)) (N.pos p)) in Ha as H; + [ apply N.le_lteq; by left | ]. + apply N.lt_add_pos_r; done. + } + Qed. + + Definition fullQueue (wa ra : Bvector ADDR_WIDTH) : bool := + let waN := Bv2N wa in + let raN := Bv2N ra in + let qms := N.sub (N.of_nat QUEUE_MAX_SIZE) 1 in + if (raN <= waN)%nat then ((N.sub (Bv2N wa) (Bv2N ra)) =? qms)%N + else (((N.add qms 1) - (raN - waN))%N =? qms)%N. + + Lemma N2Bv_sized_queuemax_neq0 : + N2Bv_sized ADDR_WIDTH 0 <> N2Bv_sized ADDR_WIDTH (N.of_nat QUEUE_MAX_SIZE - 1). + Proof. + apply N2Bv_sized_neq_iff; unfold ADDR_WIDTH. + { rewrite /N.size_nat /Nat.log2 //=. } + { rewrite -N.pred_sub -Nat2N.inj_pred. + apply /leP; apply N.size_nat_le_nat. + rewrite QUEUE_MAX_SIZE_PW2; apply /leP. + rewrite ltn_predL; apply /leP. + exact QUEUE_MAX_SIZE_GT_0. } + { rewrite -N.pred_sub -Nat2N.inj_pred. + specialize QUEUE_MAX_SIZE_DIFF_0 as HH. + move: HH => /N.eqb_spec HH. + by apply /N.eqb_spec. + } + Qed. + + (* -------------- Proofs about FullEmptyLogic ------------------------------- *) + Lemma FEL_emp_equiv (c : circuit_state FullEmptyLogic) wra rda : + wra = rda -> exists c', step FullEmptyLogic c (wra,rda) = (c',(false,true)). + Proof. + intros H; eapply ex_intro. + cbv [FullEmptyLogic FullLogic EmptyLogic Subtractor subtractor dropr EqFULL FullVEC unpackV]; + cbn [step]; simpl_ret; cbn [fst snd]. + apply pair_equal_spec; split; [ reflexivity | ]. + apply pair_equal_spec; split; [ | by rewrite H CavaPreludeProperties.eqb_refl ]. + rewrite inv_correct; cbv [bind]. + rewrite fullAdder_cin; cbv [unpackV]; simpl_ret. + destruct (one) eqn:Hone; [ | discriminate]. + destruct ((Bv2N rda) <= (Bv2N wra)) eqn:Hleq; + [ | by rewrite H leqnn in Hleq ]. + assert (N.sub (Bv2N wra) (Bv2N rda) = N0); [ by rewrite H N.sub_diag | ]. + rewrite H0 !bitvec_literal_correct. + set (N := N.sub _ _). + specialize N2Bv_sized_queuemax_neq0 as H2. + specialize @CavaPreludeProperties.eqb_neq with (t := Vec Bit (@ADDR_WIDTH CAVA_SYS)) + (x := N2Bv_sized ADDR_WIDTH 0) (y := N2Bv_sized ADDR_WIDTH N) as HH. + by apply HH in H2. + Qed. + + Lemma FEL_nemp_wrap1_equiv (c : circuit_state FullEmptyLogic) (wra rda : Bvector ADDR_WIDTH) : + let wrap1 := N2Bv_sized ADDR_WIDTH (Bv2N wra + 1) in + wra = rda -> exists c' f', step FullEmptyLogic c (wrap1,rda) = (c',(f',false)). + Proof. + intros; repeat eapply ex_intro; unfold wrap1. + cbv [FullEmptyLogic FullLogic EmptyLogic Subtractor subtractor dropr EqFULL FullVEC unpackV]; + cbn [step]; simpl_ret; cbn [fst snd]. + apply pair_equal_spec; split; [ reflexivity | ]. + apply pair_equal_spec; split; [ reflexivity | ]. + apply CavaPreludeProperties.eqb_neq; rewrite H. + apply N2Bv_sized_plusone_diff; unfold ADDR_WIDTH. + specialize QUEUE_MAX_SIZE_GT_1 as HQ; apply Nat.log2_pos in HQ. + by move: HQ => /ltP HQ. + Qed. + + Lemma FEL_nemp_NF_equiv (c : circuit_state FullEmptyLogic) (wra rda : Bvector ADDR_WIDTH) : + ~~ (fullQueue wra rda) -> + wra <> rda -> exists c', step FullEmptyLogic c (wra,rda) = (c',(false,false)). + Proof. + intros NF H; eapply ex_intro. + rewrite /fullQueue in NF. + cbv [FullEmptyLogic FullLogic EmptyLogic Subtractor subtractor dropr EqFULL FullVEC unpackV]; + cbn [step]; simpl_ret; cbn [fst snd]. + apply pair_equal_spec; split; [ reflexivity | ]. + apply pair_equal_spec; split; [ | by apply CavaPreludeProperties.eqb_neq ]. + rewrite bitvec_literal_correct. + rewrite fullAdder_cin; destruct (one) eqn:Hbug; try discriminate; clear Hbug. + cbv [unpackV]. + destruct (_ <= _) eqn:Hleq; apply CavaPreludeProperties.eqb_neq. + { set (xx := N.sub (Bv2N wra) (Bv2N rda)); fold xx in NF. + set (yy := N.sub (N.of_nat QUEUE_MAX_SIZE) 1); fold yy in NF. + assert (N.size_nat xx <= ADDR_WIDTH); + [ unfold xx; apply size_nat_sub_leq; lia | ]. + assert (N.size_nat yy <= ADDR_WIDTH); + [ unfold ADDR_WIDTH, yy; by apply size_nat_qms | ]. + apply N2Bv_sized_neq_iff; try done; lia. + } + { rewrite {3}/ADDR_WIDTH QUEUE_MAX_SIZE_PW2; apply N2Bv_sized_neq_iff. + { assert (Bv2N rda > Bv2N wra); [ lia | ]. + by apply size_nat_qms_sub. + } + { unfold ADDR_WIDTH; by apply size_nat_qms. } + specialize add_1_sub1 with (x := N.of_nat (@QUEUE_MAX_SIZE CAVA_SYS)) as HH. + rewrite HH in NF; [ | exact QUEUE_MAX_SIZE_GT_0_N]; lia. + } + Qed. + + Lemma FEL_NF_equiv (c : circuit_state FullEmptyLogic) (wra rda : Bvector ADDR_WIDTH) : + ~~ (fullQueue wra rda) -> + exists c' e', step FullEmptyLogic c (wra,rda) = (c',(false,e')). + Proof. + intros NF; unfold fullQueue in NF; repeat eapply ex_intro. + cbv [FullEmptyLogic]; cbn [step]; simpl_ret; cbn [fst snd]. + apply pair_equal_spec; split; [reflexivity | ]. + apply pair_equal_spec; split; [ | reflexivity ]. + cbv [dropr subtractor EqFULL FullVEC unpackV]; simpl_ident. + destruct ((Bv2N rda) <= (Bv2N wra)) eqn:Hleq; + destruct (one) eqn:Hone; try discriminate; + rewrite fullAdder_cin Hleq; + apply CavaPreludeProperties.eqb_neq; move: NF => /eqP NF. + { set (xx := N.sub (Bv2N wra) (Bv2N rda)); fold xx in NF. + set (yy := N.sub (N.of_nat QUEUE_MAX_SIZE) 1); fold yy in NF. + assert (N.size_nat xx <= ADDR_WIDTH); + [ unfold xx; apply size_nat_sub_leq; lia | ]. + assert (N.size_nat yy <= ADDR_WIDTH); + [ unfold ADDR_WIDTH, yy; by apply size_nat_qms | ]. + apply N2Bv_sized_neq_iff; try done; lia. + } + { rewrite {3}/ADDR_WIDTH QUEUE_MAX_SIZE_PW2; apply N2Bv_sized_neq_iff. + { assert (Bv2N rda > Bv2N wra) as H; [ lia | ]. + by apply size_nat_qms_sub. + } + { unfold ADDR_WIDTH; by apply size_nat_qms. } + specialize add_1_sub1 with (x := N.of_nat (@QUEUE_MAX_SIZE CAVA_SYS)) as HH; lia. + } + Qed. + + (* ------------------------------------------------------------------ *) + Lemma incrn_pointr_true_equiv (c : circuit_state incr_pointr) ad : + step incr_pointr c (ad,true) = + (tt,N2Bv_sized ADDR_WIDTH (Bv2N ad + 1)). + Proof. + cbv [incr_pointr step] ; by simpl_ident. + Qed. + + Lemma incrn_pointr_false_equiv (c : circuit_state incr_pointr) ad : + step incr_pointr c (ad,false) = (tt,ad). + Proof. + cbv [incr_pointr step] ; by simpl_ident. + Qed. + + Definition get_mem_RequestQueue (c : circuit_state RequestQueue') := + let '(_,(_,(_,_, _,memqueue_state,_,_,_,_,_),_)) := c in memqueue_state. + + Definition get_addr_RequestQueue (c : circuit_state RequestQueue') := + let '(_,(_,(_,_, _,_,_,_,_,_,rda),wra)) := c in (wra,rda). + + Definition get_memcells (s : circuit_state memqueue') := + let '(_,memcells_state,_) := s in memcells_state. + + Definition get_memcells_RequestQueue (c : circuit_state RequestQueue') := + get_memcells (get_mem_RequestQueue c). + + Lemma test {W} (t : combType (Vec Bit W)) : forall n : nat, + (N.to_nat (Bv2N t) =? n)%N = false -> + indexConst (decode true t) n = constant false. + + (* ----------------------- Proofs about the Queue ---------------------- *) + Lemma Queue_NF_WR_fst (c : circuit_state RequestQueue') c_req : + let '(wra,rda) := get_addr_RequestQueue c in + let S := get_memcells_RequestQueue c in + let wra_idx := N.to_nat (Bv2N wra) in + let memcells_spec := Cells_read true wra_idx c_req S in + ~~ (fullQueue wra rda) -> exists c', + ((Cells_data (get_memcells_RequestQueue c') = memcells_spec) /\ + (fst (get_addr_RequestQueue c')) = (N2Bv_sized ADDR_WIDTH (Bv2N wra + 1)) /\ + (snd (get_addr_RequestQueue c')) = rda) /\ + fst (step RequestQueue' c (true,c_req,false)) = c'. + Proof. + simpl in c; destruct_products. + unfold get_addr_RequestQueue; intros Hfull; eapply ex_intro; split; [ | reflexivity]. + set (p := step RequestQueue' _ _). + cbv [RequestQueue' LoopInit fork2] in p. + cbn [step] in p; cbn [fst snd] in p; simpl_ret_H p; cbv [fst snd] in p. + specialize FEL_NF_equiv with (c := (u17, (u19, u20, u18), u16)) + (rda := t0) (wra := t) as H; apply H in Hfull; clear H. + destruct Hfull as [cs_FEL' [empty_o Hfull]]. + unfold p; clear p; rewrite Hfull. + cbn [fst snd bind inv and2 or2]; fast_simpl_bool. + rewrite (surjective_pairing (step memqueue' _ _)). + rewrite incrn_pointr_true_equiv incrn_pointr_false_equiv. + rewrite (surjective_pairing (step FullEmptyLogic _ _)). + set (fel := step FullEmptyLogic _ _). + split. + { simpl in fel; unfold fel; cbv [snd fst]. + cbv [get_memcells_RequestQueue get_mem_RequestQueue get_memcells]. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end. + cbv [memqueue' Memory' mem_write mem_read]; cbn [step fst snd]; simpl_ident; cbv [fst snd]. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end. + cbv [fst snd]. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end. + specialize @Cells_matchX with (T := Vec Bit (@REQUEST_WIDTH CAVA_SYS)) + (W := @ADDR_WIDTH CAVA_SYS) (N := (Nat.pow 2 (@ADDR_WIDTH CAVA_SYS))) (I := InitMem) + (S0 := c) (we := true) (wd := c_req) (wa := (N.to_nat (Bv2N t))) as HH. + rewrite -HH; [reflexivity | | ]. + { intros. + rewrite /indexConst; simpl_ident. + rewrite /decode; simpl_ident. + induction ADDR_WIDTH. + + rewrite /decode_. + admit. + } + { rewrite /indexConst; simpl_ident. + rewrite /decode; simpl_ident. + admit. + } + } + split; by simpl. + Admitted. *) + + Lemma Queue_WR_NF_NE_fst (c : circuit_state RequestQueue') c_req pop : + let '(wra,rda) := get_addr_RequestQueue c in + let S := get_memcells_RequestQueue c in + let wra_idx := N.to_nat (Bv2N wra) in + let memcells_spec := Cells_read true wra_idx c_req S in + ~~ (fullQueue wra rda) -> wra <> rda -> exists c', + ((Cells_data (get_memcells_RequestQueue c') = memcells_spec) /\ + (fst (get_addr_RequestQueue c')) = (N2Bv_sized ADDR_WIDTH (Bv2N wra + 1)) /\ + (snd (get_addr_RequestQueue c')) = (if pop then (N2Bv_sized ADDR_WIDTH (Bv2N rda + 1)) else rda)) /\ + fst (step RequestQueue' c (true,c_req,pop)) = c'. + Admitted. + (* Proof. + simpl in c; destruct_products. + unfold get_addr_RequestQueue; intros Hfull Hdiff; eapply ex_intro; split; [ | reflexivity]. + set (p := step RequestQueue' _ _). + cbv [RequestQueue' LoopInit fork2] in p. + cbn [step] in p; cbn [fst snd] in p; simpl_ret_H p; cbv [fst snd] in p. + specialize FEL_nemp_NF_equiv with (c := (u17, (u19, u20, u18), u16)) + (rda := t0) (wra := t) as H; apply H in Hfull; clear H; [ | done]. + destruct Hfull as [cs_FEL' Hfull]. + unfold p; clear p; rewrite Hfull. + cbn [fst snd bind inv and2 or2]; fast_simpl_bool. + rewrite (surjective_pairing (step memqueue' _ _)). + rewrite incrn_pointr_true_equiv. + rewrite incrn_pointr_true_equiv. + rewrite (surjective_pairing (step FullEmptyLogic _ _)). + set (fel := step FullEmptyLogic _ _). + split. + { simpl in fel; unfold fel; cbv [snd fst]. + cbv [get_memcells_RequestQueue get_mem_RequestQueue get_memcells]. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end. + cbv [memqueue' Memory' mem_write mem_read]; cbn [step fst snd]; simpl_ident; cbv [fst snd]. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end. + cbv [fst snd]. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end. + fold mem_cells_. + specialize @Cells_matchX with (T := Vec Bit (@REQUEST_WIDTH CAVA_SYS)) + (W := @ADDR_WIDTH CAVA_SYS) (N := (Nat.pow 2 (@ADDR_WIDTH CAVA_SYS))) (I := InitMem) + (S0 := c) (we := true) (wd := c_req) (wa := (N.to_nat (Bv2N t))) as HH. + rewrite -HH; [reflexivity | | ]. + { intros. + rewrite /indexConst; simpl_ident. + rewrite /decode; simpl_ident. + admit. + } + { rewrite /indexConst; simpl_ident. + rewrite /decode; simpl_ident. + admit. + } + } + split; by simpl. + Admitted. *) + + Lemma Queue_WR_NF_E_fst (c : circuit_state RequestQueue') c_req pop : + let '(wra,rda) := get_addr_RequestQueue c in + let S := get_memcells_RequestQueue c in + let wra_idx := N.to_nat (Bv2N wra) in + let memcells_spec := Cells_read true wra_idx c_req S in + ~~ (fullQueue wra rda) -> wra = rda -> exists c', + ((Cells_data (get_memcells_RequestQueue c') = memcells_spec) /\ + (fst (get_addr_RequestQueue c')) = (N2Bv_sized ADDR_WIDTH (Bv2N wra + 1)) /\ + (snd (get_addr_RequestQueue c')) = rda) /\ + fst (step RequestQueue' c (true,c_req,pop)) = c'. + Admitted. + + (* Ignoring the full signal because it just goes to the output *) + Lemma Queue_WR_E_snd (c : circuit_state RequestQueue') c_req pop : + let '(wra,rda) := get_addr_RequestQueue c in + let S := get_memcells_RequestQueue c in + let rda_idx := N.to_nat (Bv2N rda) in + let wra_idx := N.to_nat (Bv2N wra) in + let memcells' := Cells_read true wra_idx c_req S in + let mem_val := nth_default (req_null) rda_idx memcells' in + wra = rda -> exists f', + snd (step RequestQueue' c (true,c_req,pop)) = (f',mem_val,true). + Admitted. + (* simpl in c; destruct_products; rename t0 into rda, t into wra. + autounfold with get_state; intros. + cbv [RequestQueue' LoopInit fork2]; simpl_ret; cbn [step fst snd]. + eapply FEL_emp_equiv with (c := (u17,(u19,u20,u18), u16)) in H as HH. + destruct HH as [cs_FEL HH]; rewrite HH. + cbn [fst snd bind inv and2 or2]. + rewrite (surjective_pairing (step memqueue' (u12,c,u11) _)). + cbv [fst snd]; fast_simpl_bool. + rewrite incrn_pointr_true_equiv if_same incrn_pointr_false_equiv; clear HH. + eapply FEL_nemp_wrap1_equiv with (c := (u4, (u6, u7, u5), u3)) in H as HH. + destruct HH as [cs_FELL [full_o HH]]; rewrite HH; clear HH. + eapply ex_intro. + apply pair_equal_spec; split; [ | reflexivity ]. + apply pair_equal_spec; split; [ reflexivity | ]. + cbv [memqueue' Memory' mem_write mem_read]. + cbn [step fst snd]; simpl_ret. + rewrite (surjective_pairing (step (mem_cells _ _ _ _) c _)). + specialize @Cells_data_match with (T := Vec Bit (@REQUEST_WIDTH CAVA_SYS)) + (W := @ADDR_WIDTH CAVA_SYS) (N := (Nat.pow 2 (@ADDR_WIDTH CAVA_SYS))) (I := InitMem) + (S0 := c) (we := true) (wa := (N.to_nat (Bv2N wra))) (wd := c_req) as HH. + rewrite -HH. + { cbv [indexAt indexConst defaultCombValue]. + cbv [unpackV bind]; simpl_ret. + rewrite nth_0; simpl; unfold req_null. + reflexivity. + } + all: admit. + Admitted. *) + + Lemma Queue_WR_NF_NE_snd (c : circuit_state RequestQueue') c_req pop : + let '(wra,rda) := get_addr_RequestQueue c in + let S := get_memcells_RequestQueue c in + let rda_idx := N.to_nat (Bv2N rda) in + let wra_idx := N.to_nat (Bv2N wra) in + let memcells' := Cells_read true wra_idx c_req S in + let mem_val := nth_default (req_null) rda_idx memcells' in + ~~ (fullQueue wra rda) -> wra <> rda -> exists full_o, + snd (step RequestQueue' c (true,c_req,pop)) = (full_o,mem_val,false). + Admitted. + (* simpl in c; destruct_products; rename t0 into rda, t into wra. + autounfold with get_state; intros. + cbv [RequestQueue' LoopInit fork2]; simpl_ret; cbn [step fst snd]. + apply FEL_nemp_NF_equiv with (c := (u17,(u19,u20,u18), u16)) in H as HH; [ | done]. + destruct HH as [cs_FEL HH]; rewrite HH. + cbn [fst snd bind inv and2 or2]; fast_simpl_bool. + rewrite (surjective_pairing (step memqueue' (u12,c,u11) _)). + cbv [fst snd]; fast_simpl_bool. + rewrite incrn_pointr_true_equiv. + rewrite (surjective_pairing (step incr_pointr u9 _)). + (* rewrite incrn_pointr_false_equiv; clear HH. *) + (* The second logic doesn't really matter much *) + rewrite (surjective_pairing (step FullEmptyLogic _ _)). + eapply ex_intro. + apply pair_equal_spec; split; [ | reflexivity]. + apply pair_equal_spec; split; [ reflexivity | ]. + destruct_pair_let. + cbv [memqueue' Memory' mem_write mem_read]. + cbn [step fst snd]; simpl_ret. + rewrite (surjective_pairing (step (mem_cells _ _ _ _) c _)); clear HH. + specialize @Cells_data_match with (T := Vec Bit (@REQUEST_WIDTH CAVA_SYS)) + (W := @ADDR_WIDTH CAVA_SYS) (N := (Nat.pow 2 (@ADDR_WIDTH CAVA_SYS))) (I := InitMem) + (S0 := c) (we := true) (wa := (N.to_nat (Bv2N wra))) (wd := c_req) as HH. + rewrite -HH //=. + all: admit. + Admitted. *) + +End CavaReqQueueProperties. \ No newline at end of file diff --git a/framework/CavaDRAM/CavaSMExtraction.v b/framework/CavaDRAM/CavaSMExtraction.v index f856dd3..e9e8a0f 100644 --- a/framework/CavaDRAM/CavaSMExtraction.v +++ b/framework/CavaDRAM/CavaSMExtraction.v @@ -1,6 +1,6 @@ Set Warnings "-notation-overridden,-parsing". -Require Import CavaFIFOREF CavaTDMREF. +Require Import CavaFIFOREF. Require Import Extraction. Require Import ExtrHaskellBasic. @@ -18,6 +18,8 @@ Cd "fifo_gencode". Recursive Extraction Library CavaFIFOREF. Cd "..". +(* Cd "tdm_gencode". Recursive Extraction Library CavaTDMREF. -Cd "..". +Cd "..". +*) diff --git a/framework/CavaDRAM/CavaSubtractor.v b/framework/CavaDRAM/CavaSubtractor.v index 890d2de..8416e03 100644 --- a/framework/CavaDRAM/CavaSubtractor.v +++ b/framework/CavaDRAM/CavaSubtractor.v @@ -1,7 +1,12 @@ -Require Export Cava.Cava. -Require Export Cava.CavaProperties. +Require Import Cava.Cava. +Require Import Cava.CavaProperties. +Require Import Cava.Util.Vector. -From CavaDRAM Require Import CavaSystem. +From CavaDRAM Require Import CavaSystem UtilSM. +From mathcomp Require Import ssreflect ssrnat ssrbool seq eqtype. +From mathcomp Require Import ssrZ zify ring. +From Coq Require Import NArith. +From CoqDRAM Require Import Util. Import Circuit.Notations. @@ -10,28 +15,103 @@ Section CavaSubtractor. Context {signal : SignalType -> Type} {semantics : Cava signal}. Definition subtractor {n : nat} - (inputs : signal (Vec Bit n) * signal (Vec Bit n)) - : cava (signal (Vec Bit n) * signal Bit) - := let '(a,b) := inputs in - not_b <- Vec.inv b ;; - aV <- unpackV a ;; - bV <- unpackV not_b ;; - col fullAdder one (vcombine aV bV). + (inputs : signal (Vec Bit n) * signal (Vec Bit n)) + : cava (signal (Vec Bit n) * signal Bit) + := let '(a,b) := inputs in + not_b <- Vec.inv b ;; + aV <- unpackV a ;; + bV <- unpackV not_b ;; + col fullAdder one (vcombine aV bV). Definition Subtractor {n : nat} - : Circuit (signal (Vec Bit n) * (* N-bit Minued *) - signal (Vec Bit n)) (* N-bit Subtrahend *) - (signal (Vec Bit n) * (* N-bit Difference*) - signal Bit) + : Circuit _ (signal (Vec Bit n) * signal Bit) := Comb subtractor. - Check addC. +End CavaSubtractor. - Definition SubtractorAddC {n : nat} - (inputs : signal (Vec Bit n) * signal (Vec Bit n)) : - cava (signal (Vec Bit n) * signal Bit) - := let '(a,b) := inputs in - not_b <- Vec.inv b ;; - addC (a,not_b,one). +Section CavaSubtractorProperties. -End CavaSubtractor. + Lemma case1 (x y : N) (z : nat) : + N.to_nat x < z -> + N.to_nat y < z -> + (y < x) = false -> + let t := N.of_nat z in + (2 * (t - (y - x) - 1) + 1)%N = + (2 * t - (2 * y + 1 - (2 * x + 1)) - 1)%N. + Proof. + lia. + Qed. + + Lemma case2 (x y : N) (z : nat) : + N.to_nat x < z -> + N.to_nat y < z -> + (y <= x) = false -> + let t := N.of_nat z in + (2 * (t - (y - x)) + 1)%N = + (2 * t - (2 * y - (2 * x + 1)))%N. + Proof. + lia. + Qed. + + Lemma case3 (x y : N) (z : nat) : + N.to_nat x < z -> + N.to_nat y < z -> + (y < x) = false -> + let t := N.of_nat z in + (2 * (t - (y - x) - 1) + 1)%N = + (2 * t - (2 * y + 1 - 2 * x))%N. + Proof. + lia. + Qed. + + Lemma case4 (x y : N) (z : nat) : + N.to_nat x < z -> + N.to_nat y < z -> + (y < x) = false -> + let t := N.of_nat z in + (2 * (t - (y - x) - 1) + 1)%N = + (2 * t - (2 * y - 2 * x) - 1)%N. + Proof. + lia. + Qed. + + Lemma fullAdder_cin {n} (x y : Vector.t bool n) cin: + let xN := Bv2N x in + let yN := Bv2N y in + let out := if cin + then (if (yN <= xN)%nat then (xN - yN)%N else ((N.of_nat (Nat.pow 2 n)) - (yN - xN))%N) + else (if (yN < xN)%nat then (xN - yN - 1)%N else ((N.of_nat (Nat.pow 2 n)) - (yN - xN) - 1)%N) in + fst (col fullAdder cin (vcombine x (Vector.map negb y))) = N2Bv_sized n out. + Proof. + intros out; unfold out; clear out. + revert x y cin. + induction n; intros; + [ apply Vector.case0 with (v:=x); apply Vector.case0 with (v:=y); + destruct cin; reflexivity | ]. + rewrite col_step fullAdder_correct; cbn [fst snd]. + rewrite (Vector.eta x) (Vector.eta y); simpl; rewrite IHn; clear IHn; + destruct (Vector.hd x) eqn:Hx, (Vector.hd y) eqn:Hy, cin eqn:Hcin; simpl; + repeat match goal with + | |- context [?y <= ?x] => + let H := fresh "x" in destruct (y <= x) eqn:H + | |- context [?y < ?x] => + let H := fresh "x" in destruct (y < x) eqn:H + end; + set xx := Bv2N (Vector.tl x); set yy := Bv2N (Vector.tl y); fold xx yy in x0, x1. + all: try (rewrite -N2Bv_sized_double || rewrite -N2Bv_sized_succ_double); apply f_equal. + all: try (rewrite Nat.add_0_r; + match goal with + | |- context [Nat.pow 2 ?n] => set z := Nat.pow 2 n + end; rewrite of_nat_add_double). + all: try (rewrite !N.double_spec); try (rewrite !N.succ_double_spec); try lia. + all: try (rewrite !N.succ_double_spec in x1); try (rewrite !N.double_spec in x1). + all: try (contradict x1; lia); + specialize (@Bv2N_upper_bound_nat n (Vector.tl x)) as Hxb; fold xx in Hxb; + specialize (@Bv2N_upper_bound_nat n (Vector.tl y)) as Hyb; fold yy in Hyb. + all: try apply case1; try done. + all: try apply case2; try done. + all: try apply case3; try done. + all: try apply case4; try done. + Qed. + +End CavaSubtractorProperties. diff --git a/framework/CavaDRAM/CavaSubtractorProperties.v b/framework/CavaDRAM/CavaSubtractorProperties.v index ed4d0e4..471d25e 100644 --- a/framework/CavaDRAM/CavaSubtractorProperties.v +++ b/framework/CavaDRAM/CavaSubtractorProperties.v @@ -1,7 +1,7 @@ Require Import CavaSubtractor. Require Import Coq.micromega.Lia. -From DRAM Require Import Util. +From CoqDRAM Require Import Util. Section CavaSubtractorProperties. diff --git a/framework/CavaDRAM/CavaSystem.v b/framework/CavaDRAM/CavaSystem.v index 0e3bfa5..f487878 100644 --- a/framework/CavaDRAM/CavaSystem.v +++ b/framework/CavaDRAM/CavaSystem.v @@ -1,3 +1,4 @@ +Set Warnings "-notation-overridden,-parsing". Require Import Coq.NArith.NArith. From mathcomp Require Import ssreflect ssrnat ssrbool seq eqtype. @@ -6,11 +7,23 @@ Section CavaSystem. Class CavaSystem := { DRAM_CMD_WIDTH : nat; - FE_ADDR_WIDTH : nat; - FE_CMD_WIDTH : nat; - FE_ID_WIDTH : nat; + + (* FE_ID_WIDTH : nat; *) + (* FE_ADDR_WIDTH : nat; *) + ROW_ADDR_WIDTH : nat; (* 17 *) + COL_ADDR_WIDTH : nat; (* 10 *) + BANK_ADDR_WIDTH : nat; (* 4 *) + FE_CMD_WIDTH : nat; (* 1 *) + QUEUE_MAX_SIZE : nat; - QUEUE_MAX_SIZE_GT_0 : 0 < QUEUE_MAX_SIZE ; + (* Constrint for easing proofs *) + QUEUE_MAX_SIZE_PW2 : Nat.pow 2 (Nat.log2 QUEUE_MAX_SIZE) = QUEUE_MAX_SIZE; + QUEUE_MAX_SIZE_PW2_N : N.pow 2 (N.of_nat (Nat.log2 QUEUE_MAX_SIZE)) = N.of_nat QUEUE_MAX_SIZE; + (* Two versions of the same *) + QUEUE_MAX_SIZE_GT_0 : (0 < QUEUE_MAX_SIZE)%coq_nat ; + QUEUE_MAX_SIZE_GT_0_N : (0 < N.of_nat QUEUE_MAX_SIZE) ; + QUEUE_MAX_SIZE_GT_1 : (1 < QUEUE_MAX_SIZE)%coq_nat ; + QUEUE_MAX_SIZE_DIFF_0 : (N0 <> N.of_nat (QUEUE_MAX_SIZE.-1)) }. End CavaSystem. \ No newline at end of file diff --git a/framework/CavaDRAM/CavaTDMREF.v b/framework/CavaDRAM/CavaTDMREF.v index 3cd89e8..27d5a29 100644 --- a/framework/CavaDRAM/CavaTDMREF.v +++ b/framework/CavaDRAM/CavaTDMREF.v @@ -1,6 +1,8 @@ -From CavaDRAM Require Import CavaReqQueue CavaSM CavaCommonInstances. -From DRAM Require Import TDM. +Set Warnings "-notation-overridden,-parsing". +From CavaDRAM Require Import CavaReqQueue CavaCommonInstances CavaSystem. +From CoqDRAM Require Import TDM. From Coq Require Import BinaryString HexString NArith. +From Cava Require Import Cava. Section CavaTDMREF. @@ -8,20 +10,15 @@ Section CavaTDMREF. Context {CAVA_SYS : CavaSystem}. (* From Cava *) Context {signal : SignalType -> Type} {semantics : Cava signal}. - (* From DRAM *) + (* From CoqDRAM *) Context {SYS_CFG : System_configuration} {TDM_CFG : TDM_configuration}. Definition NR := BANKS. Definition STATE_WIDTH := 2. - Definition SLOT_WIDTH := - if (powerOfTwo NR) then Nat.log2 NR else (Nat.log2 NR + 1). - - Definition COUNTER_WIDTH := - if (powerOfTwo SL) then Nat.log2 SL else (Nat.log2 SL + 1). - - Definition COUNTER_REF_WIDTH := - if (powerOfTwo PREA_date) then Nat.log2 PREA_date else (Nat.log2 PREA_date + 1). + Definition SLOT_WIDTH := Nat.log2 NR. + Definition COUNTER_WIDTH := Nat.log2 SL. + Definition COUNTER_REF_WIDTH := Nat.log2 PREA_date. Definition state := Vec Bit STATE_WIDTH. Definition slot := Vec Bit SLOT_WIDTH. @@ -34,7 +31,7 @@ Section CavaTDMREF. Definition counter_t := signal counter. Definition counter_ref_t := signal counter_ref. - Import CavaSM.DataNotation. + Import CavaReqQueue.DataNotation. Open Scope ds. Definition SLOT_SN := Vec.bitvec_literal (#D (N.of_nat (SN - 1)) | SLOT_WIDTH). @@ -116,10 +113,10 @@ Section CavaTDMREF. CavaPrelude.eqb (input,SLOT_SN). (* Cuts FE_ID_WIDTH to be just the SLOT_WIDTH lsb *) - Definition RequestId : Circuit + (* Definition RequestId : Circuit (request_t) (signal (Vec Bit SLOT_WIDTH)) := Comb (fun r => rV <- unpackV r ;; - packV (slice_default defaultSignal rV 0 SLOT_WIDTH)). + packV (slice_default defaultSignal rV 0 SLOT_WIDTH)). *) (* Will not depend on the slot *) Definition NextCR : Circuit @@ -144,6 +141,7 @@ Section CavaTDMREF. ret (mux2_out,mux2_out) )). + (* Definition CmdGen : Circuit (state_t * empty_t * counter_t * counter_ref_t * request_t) (command_t) := Comb (fun '(s,e,c,cref,req) => @@ -173,7 +171,8 @@ Section CavaTDMREF. t1 <- and2 (c_prea',cz);; pre_mux_sel <- and2 (t0,t1) ;; mux2 pre_mux_sel (act_mux_out,PRE) - ). + ). + *) (* Will not depend on the slot *) Definition Update_s (input : state_t * empty_t * counter_t * counter_ref_t) : @@ -201,17 +200,6 @@ Section CavaTDMREF. mux_ref_sel <- or2 (t3,t4) ;; mux2 mux_ref_sel (mux_idle_run_out,STATE_REF). - Definition Update_e (input : state_t * empty_t * counter_t * counter_ref_t) : - cava (empty_t) := let '(s,e,c,cref) := input in - s_idle <- Sidle s ;; - c_service <- CrefPREA_lt cref ;; - ne <- inv e ;; - cz <- CeqZ c ;; - t0 <- and2 (c_service,ne) ;; - t1 <- and2 (s_idle,cz) ;; - mux_sel <- and2 (t0,t1) ;; - mux2 mux_sel (zero,one). - Definition Update_c (input : state_t * empty_t * counter_t * counter_ref_t) : cava (counter_t) := let '(_,_,c,_) := input in c_sl <- CeqSL c ;; @@ -240,14 +228,13 @@ Section CavaTDMREF. Definition Update : Circuit (state_t * slot_t * empty_t * counter_t * counter_ref_t) - (state_t * slot_t * empty_t * counter_t * counter_ref_t) := + (state_t * slot_t * counter_t * counter_ref_t) := Comb (fun '(s,sl,e,c,cref) => s' <- Update_s (s,e,c,cref) ;; sl' <- Update_slot (s,sl,e,c,cref) ;; - e' <- Update_e (s,e,c,cref) ;; c' <- Update_c (s,e,c,cref) ;; cref' <- Update_cref (s,e,c,cref) ;; - ret (s',sl',e',c',cref') + ret (s',sl',c',cref') ). Definition Idx {W A} n @@ -279,17 +266,17 @@ Section CavaTDMREF. end. (* A 1:N 1-bit demultiplexer *) - Fixpoint demux_bit N : Circuit - (signal Bit * signal (Vec Bit SLOT_WIDTH)) (signal (Vec Bit N)) := + Fixpoint demux_bit W N : Circuit + (signal Bit * signal (Vec Bit W)) (signal (Vec Bit N)) := match N with | 0 => Comb (fun '(_,_) => Vec.const zero 0) | S n => Comb (fun '(Rp,sel) => - let i := (#D (N.of_nat (NR - (n + 1))) | SLOT_WIDTH) in + let i := (#D (N.of_nat (NR - (n + 1))) | W) in i_vec <- Vec.bitvec_literal i ;; eq_sel <- CavaPrelude.eqb(sel,i_vec) ;; t <- mux2 eq_sel (zero,Rp) ;; ret (t,(Rp,sel))) - >==> Second (demux_bit n) >==> + >==> Second (demux_bit W n) >==> Comb (fun '(t,t0) => Vec.cons t t0) end. @@ -311,42 +298,72 @@ Section CavaTDMREF. ret (f,d,e) ). + (* push, pop, bank, slot, request -> slot, push_vec, req_vec, pop_vec *) Definition DemuxInputs : Circuit - (signal Bit * request_t * signal Bit * slot_t) + (signal Bit * signal Bit * request_t * bank_t * slot_t ) (slot_t * signal (Vec Bit NR) * signal(Vec request NR) * signal (Vec Bit NR)) := - Comb (fun '(Rp,Rd,p,sl) => ret (p,sl,Rp,(Rd))) - >==> Second (Comb (fork2) >==> First (RequestId) >==> Second (repeatF (A := request) NR)) >==> - (* Uses slot to demux the pop signal into the queues *) - Comb (fun '(p,sl,Rp,(id,Rd_vec)) => ret (sl,Rp,Rd_vec,id,(p,sl))) - >==> Second (demux_bit NR) >==> - (* Uses FE_ID to demux the push signal into the queques *) - Comb (fun '(sl,Rp,Rd_vec,id,pop_vec) => ret (sl,Rd_vec,pop_vec,(Rp,id))) - >==> Second (demux_bit NR) >==> - (* Applies the demux'd vectors into the queues *) - Comb (fun '(sl,Rd_vec,pop_vec,Rp_vec) => ret (sl,(Rp_vec,Rd_vec,pop_vec))) - >==> Second (Queues NR) >==> - Comb (fun '(sl,(f_vec,d_vec,e_vec)) => ret (sl,f_vec,d_vec,e_vec)). - - Definition DemuxInputs' : Circuit - (signal Bit * request_t * signal Bit * slot_t) - (signal (Vec Bit NR) * signal(Vec request NR) * signal (Vec Bit NR)) := - Comb (fun '(Rp,Rd,p,sl) => ret (p,sl,Rp,(Rd))) - >==> Second (Comb (fork2) >==> First (RequestId) >==> Second (repeatF (A := request) NR)) >==> - (* Uses slot to demux the pop signal into the queues *) - Comb (fun '(p,sl,Rp,(id,Rd_vec)) => ret (sl,Rp,Rd_vec,id,(p,sl))) - >==> Second (demux_bit NR) >==> - (* Uses FE_ID to demux the push signal into the queques *) - Comb (fun '(sl,Rp,Rd_vec,id,pop_vec) => ret (sl,Rd_vec,pop_vec,(Rp,id))) - >==> Second (demux_bit NR) >==> - (* Applies the demux'd vectors into the queues *) - Comb (fun '(sl,Rd_vec,pop_vec,Rp_vec) => ret (Rp_vec,Rd_vec,pop_vec)). - - Definition MuxQueues : Circuit - (signal Bit * request_t * signal Bit * slot_t) - (signal Bit * request_t * empty_t) := - DemuxInputs >==> - Comb (fun '(sl,f_vec,d_vec,e_vec) => ret (f_vec,d_vec,e_vec,sl)) >==> - mux_sigs NR. + Comb (fun '(push,pop,req,bank,sl) => ret (push,pop,bank,sl,(req))) + (* Repeats req to all queues *) + >==> Second (repeatF (A := request) NR) + (* Use the slot to demux the pop signal into the queus*) + >==> Comb (fun '(push,pop,bank,sl,req_vec) => ret (sl,push,bank,req_vec,(pop,sl))) + >==> Second (demux_bit SLOT_WIDTH NR) + (* Use the bank to demux the push signal into the queues *) + >==> Comb (fun '(sl,push,bank,req_vec,pop_vec) => ret (sl,req_vec,pop_vec,(push,bank))) + >==> Second (demux_bit BANK_ADDR_WIDTH NR) + (* Return *) + >==> Comb (fun '(sl,req_vec,pop_vec,push_vec) => ret (sl,push_vec,req_vec,pop_vec)). + + Definition TDMSM_v3 : Circuit + (signal Bit * request_t) (signal Bit * command_t * request_t) := + let slot_init : combType (slot) := SLOT_NIL_VEC in + let s_init : combType (state) := STATE_IDLE_VEC in + let cnt_init : combType (counter) := CNT_NIL_VEC in + let cref_init : combType (counter_ref) := CNT_REF_NIL_VEC in + Second (Comb (fork2) >==> Second (StripRequest)) >==> + Comb (fun '(push,(req,(_,_,bank,type))) => ret (push,bank,type,req)) >==> + LoopInit slot_init ( + LoopInit s_init ( + LoopInit cnt_init ( + LoopInit cref_init ( (* push, bank, type, slot, s, cnt, cref *) + Comb (fun '(push,bank,type,req,sl,s,cnt,cref) => + s_idle <- Sidle s ;; + c_service <- CrefPREA_lt cref ;; + pop <- and2 (s_idle,c_service) ;; + ret(type,req,s,cnt,cref,(push,pop,req,bank,sl))) + >==> Second (DemuxInputs) + >==> Comb (fun '(type,req,s,cnt,cref,(sl,push_vec,reqin_vec,pop_vec)) => + ret (type,req,s,cnt,cref,sl,(push_vec,reqin_vec,pop_vec))) + >==> Second (Queues NR) + >==> Comb (fun '(type,req,s,cnt,cref,sl,(full_vec,data_vec,empty_vec)) => + ret (one,NOP,REQUEST_NIL,SLOT_NIL,STATE_IDLE,CNT_NIL,CNT_REF_NIL)))))). + + (* Definition TDMSM_ : Circuit + (signal Bit * request_t) (signal Bit * command_t * request_t) := + let slot_init : combType (slot) := SLOT_NIL_VEC in + let s_init : combType (state) := STATE_IDLE_VEC in + let cnt_init : combType (counter) := CNT_NIL_VEC in + let cref_init : combType (counter_ref) := CNT_REF_NIL_VEC in + LoopInit slot_init ( + LoopInit s_init ( + LoopInit cnt_init ( + LoopInit cref_init ( (* Rp, Rd, sl, st, cnt, cref *) + Comb (fun '(Rp,Rd,sl,s,cnt,cref) => + s_idle <- Sidle s ;; + c_service <- CrefPREA_lt cref ;; + pop <- and2 (s_idle,c_service) ;; + ret(s,cnt,cref,(Rp,Rd,pop,sl)) + ) >==> + Second (DemuxInputs) >==> + Comb (fun '(s,cnt,cref,(sl,f_vec,d_vec,e_vec)) => ret(s,cnt,cref,sl,(f_vec,d_vec,e_vec,sl))) + >==> Second (mux_sigs NR) >==> (* s,cnt,cref,sl,(f,d,e) *) + Comb (fun '(s,cnt,cref,sl,(full,data,empty)) => ret(full,sl,s,empty,cnt,cref,(s,empty,cnt,cref,data))) + >==> Second (NextCR) >==> (*full,sl,s,empty,cnt,cref,cr *) + Comb (fun '(full,sl,s,empty,cnt,cref,cr) => ret(full,cr,sl,s,empty,cnt,cref,(s,empty,cnt,cref,cr))) + >==> Second (CmdGen) >==> + Comb (fun '(full,cr,sl,s,empty,cnt,cref,cmd) => ret(full,cmd,cr,(s,sl,empty,cnt,cref))) + >==> Second (Update_) >==> + Comb (fun '(full,cmd,cr,(ns,nsl,nc,ncref)) => ret (full,cmd,cr,nsl,ns,nc,ncref)))))). Definition TDMSM : Circuit (signal Bit * request_t) (signal Bit * command_t * request_t) := @@ -370,7 +387,7 @@ Section CavaTDMREF. >==> Second (CmdGen) >==> Comb (fun '(full,cr,sl,s,empty,cnt,cref,cmd) => ret(full,cmd,cr,(s,sl,empty,cnt,cref))) >==> Second (Update) >==> - Comb (fun '(full,cmd,cr,(ns,nsl,np,nc,ncref)) => ret (full,cmd,cr,np,nsl,ns,nc,ncref))))))). + Comb (fun '(full,cmd,cr,(ns,nsl,np,nc,ncref)) => ret (full,cmd,cr,np,nsl,ns,nc,ncref))))))). *) End CavaTDMREF. @@ -381,10 +398,13 @@ Section CavaTDMREFsim. Existing Instance SYS_CFG. Program Instance TDM_CFG : TDM_configuration := { - SL := 25; + SL := 32; SN := 8 }. + (* 2 banks -> slot_width *) + (* Compute circuit_state TDMSM. *) + Definition tdm_interface := sequentialInterface "tdm_interface" "clk" PositiveEdge "rst" PositiveEdge @@ -392,8 +412,10 @@ Section CavaTDMREFsim. [mkPort "full_o" Bit; mkPort "cmd_o" (Vec Bit DRAM_CMD_WIDTH); mkPort "CR" (Vec Bit REQUEST_WIDTH)]. Definition tdm_netlist := makeCircuitNetlist tdm_interface TDMSM. - - (* Import CavaSM.DataNotation. + + (* + + Import CavaSM.DataNotation. Open Scope data_scope. Definition Rsim1_wr := #H "00fe468b00000" | REQUEST_WIDTH. Definition Rsim1_rd := #H "00fe468b10000" | REQUEST_WIDTH. @@ -403,6 +425,36 @@ Section CavaTDMREFsim. Definition Rsim3_rd := #H "033f91a210001" | REQUEST_WIDTH. Definition Rsim5_wr := #H "00467f2300007" | REQUEST_WIDTH. + Definition test (e : seq (bool * Bvector REQUEST_WIDTH * bool)) := + map (fun '(f,d,e) => (f,HexString.of_N (Bv2N d),e)) e. + + Compute (test (simulate RequestQueue [ + (* wra = 0, rda = 0*) + (true,Rsim1_wr,false); + (* wra = 1, rda = 0*) + (false,Rsim2_wr,true); + (* wra = 1 ,rda = 1 *) + (true,Rsim1_wr,false) + ])). + + Compute simulate memqueue [ + (* Rsim1_wr @0 *) + (Rsim1_wr,(#D 0 | ADDR_WIDTH), (#D 0 | ADDR_WIDTH),true); + (* Reads Rsim_wr @0 *) + ((#D 1 | REQUEST_WIDTH),(#D 0 | ADDR_WIDTH), (#D 0 | ADDR_WIDTH),true); + (* Reads R1 @0 *) + ((#D 2 | REQUEST_WIDTH),(#D 0 | ADDR_WIDTH), (#D 0 | ADDR_WIDTH),true) + ]. + + (* + Definition Rsim1_wr := #H "00fe468b00000" | REQUEST_WIDTH. + Definition Rsim1_rd := #H "00fe468b10000" | REQUEST_WIDTH. + Definition Rsim2_wr := #H "027f234500001" | REQUEST_WIDTH. + Definition Rsim2_rd := #H "027f234510001" | REQUEST_WIDTH. + Definition Rsim3_wr := #H "033f91a200001" | REQUEST_WIDTH. + Definition Rsim3_rd := #H "033f91a210001" | REQUEST_WIDTH. + Definition Rsim5_wr := #H "00467f2300007" | REQUEST_WIDTH. + Definition SM_out := (bool * Vector.t bool DRAM_CMD_WIDTH * Vector.t bool REQUEST_WIDTH)%type. Definition cmd2string (cmd : Vector.t bool DRAM_CMD_WIDTH) : string := @@ -470,4 +522,6 @@ Section CavaTDMREFsim. Compute (map_out (simulate TDMSM sm_inputs)). *) + *) + End CavaTDMREFsim. diff --git a/framework/CavaDRAM/CavaTDMREFProperties.v b/framework/CavaDRAM/CavaTDMREFProperties.v new file mode 100644 index 0000000..e84159a --- /dev/null +++ b/framework/CavaDRAM/CavaTDMREFProperties.v @@ -0,0 +1,111 @@ +Set Printing Projections. +Set Warnings "-notation-overridden,-parsing". + +From CavaDRAM Require Import CavaTDMREF CavaSM CavaReqQueue CavaCommonInstances CavaSubtractor Step CavaSystem Memory Util UtilSM. +From CoqDRAM Require Import TDM. +From Coq Require Import Program BinaryString HexString NArith. +From Cava Require Import Cava CavaProperties Util.Vector Util.Tactics. +From mathcomp Require Import fintype ssrZ zify ring. + +Section CavaFIFOREFProperties. + (* From Cava *) + Existing Instance CombinationalSemantics. + (* From CavaDRAM*) + Context {CAVA_SYS : CavaSystem}. + (* From CoqDRAM *) + Existing Instance REQESTOR_CFG. + Context {SYS_CFG : System_configuration}. + Context {TDM_CFG : TDM_configuration}. + Context {HAF : HW_Arrival_function_t}. + Existing Instance ARBITER_CFG. + Existing Instance TDM_implementation. + + Import Memory.Properties BvectorNotations. + Open Scope Bvector_scope. + + Definition State_t := circuit_state TDMSM. + + Definition get_state (s : State_t) : combType (CavaTDMREF.state) := + let '(_,(_,(_,_,_,_,_,_,_,_,_,_,_,_,(_,(_,_,st)),_),_)) := s in st. + + Definition get_slot (s : State_t) : combType (Vec Bit SLOT_WIDTH) := + let '(_,(_,(_,_, _,_,_,_,_,_,_,_,_,_,_,slot),_)) := s in slot. + + Definition get_pop (s : State_t) : combType Bit := + let '(_,(_,_,pop)) := s in pop. + + Definition get_cnt (s : State_t) : combType (Vec Bit COUNTER_WIDTH) := + let '(_,(_,(_,_,_,_,_,_,_,_,_,_,_,_,(_,(_,(_,_,cnt),_)),_),_)) := s in cnt. + + Definition get_cref (s : State_t) : combType (Vec Bit COUNTER_REF_WIDTH) := + let '(_,(_,(_,_,_,_,_,_,_,_,_,_,_,_,(_,(_,(_,(_,_,_,_,_,_,_,cref),_),_)),_),_)) := s in cref. + + Definition get_req (s : State_t) : combType (Vec Bit REQUEST_WIDTH) := + let '(_,(_,(_,_,_,_,_,_,_,_,_,_,_,_,(_,(_,(_,(_,(_, (_,req)),_,_,_,_,_,_),_),_)),_),_)) := s in req. + + Definition cnt2Bv (cnt : Counter_t) := + N2Bv_sized COUNTER_WIDTH (N.of_nat (nat_of_ord cnt)). + + Definition cref2Bv (cref : Counter_ref_t) := + N2Bv_sized COUNTER_REF_WIDTH (N.of_nat (nat_of_ord cref)). + + Definition slot2Bv (slot : Slot_t) := + N2Bv_sized SLOT_WIDTH (N.of_nat (nat_of_ord slot)). + + Definition get_mem (s : State_t) : circuit_state (Queues NR) := + let '(_,(_,(_,_,_,_,_,_,_,mem,_,_,_,_,_,_),_)) := s in mem. + + (* Think about this *) + Definition MemPred (P : Requests_t) (mem : circuit_state (Queues NR)) : bool. + Admitted. + + Definition EqReq (r : Request_t) (r' : Bvector REQUEST_WIDTH) : bool. + Admitted. + + (* Think about EqMem and EqQueues *) + Definition State_Eq (fs : TDM_state_t) (cs : State_t) : bool := + let cs_state := get_state cs in + let cs_sl := get_slot cs in + let cs_cnt := get_cnt cs in + let cs_cref := get_cref cs in + let cs_mem := get_mem cs in + let cs_pop := get_pop cs in + let cs_req := get_req cs in + match fs with + | IDLE sl cnt cref P => (cs_state =? STATE_IDLE_VEC) + && (cs_sl =? slot2Bv sl) && (cs_cnt =? cnt2Bv cnt) && (cs_cref =? cref2Bv cref) + && (MemPred P cs_mem) && (cs_pop == false) + | RUNNING sl cnt cref P r => (cs_state =? STATE_RUN_VEC) + && (cs_sl =? slot2Bv sl) && (cs_cnt =? cnt2Bv cnt) && (cs_cref =? cref2Bv cref) + && (MemPred P cs_mem) && (cs_pop == (nat_of_ord cnt == 1)) && (EqReq r cs_req) + | REFRESHING sl cnt cref P => (cs_state =? STATE_REF_VEC) + && (cs_sl =? slot2Bv sl) && (cs_cnt =? cnt2Bv cnt) && (cs_cref =? cref2Bv cref) + && (MemPred P cs_mem) && (cs_pop == false) + end. + + Theorem TS_Bisimulation (c_req : Bvector REQUEST_WIDTH) : + forall c_state t, + let f_state := (HW_Default_arbitrate t).(Implementation_State) in + let R := HW_Arrival_at t in + State_Eq f_state c_state -> EqReq R c_req -> + let '(f_nextstate,(f_cmd_o,f_req_o)) := Next_state R f_state in + exists c_nextstate, (c_nextstate = fst (step TDMSM c_state (true,c_req))) /\ + State_Eq f_nextstate c_nextstate. + Proof. + intros c_state t f_state R H Hreq. + repeat destruct_pair_let. + eapply ex_intro; split; [reflexivity | ]. + unfold State_t in c_state; simpl in c_state; destruct_products. + rename t4 into cr, t3 into cref, t2 into cnt, t1 into state, t0 into slot, b into pop. + unfold State_Eq in H; cbv [get_state get_slot get_cnt get_cref get_pop get_mem] in H. + destruct f_state eqn:Hf_state. + { move: H => /andP [/andP [/andP [/andP [/andP [EqS EqSlot] EqCnt] EqCref] EqMem] EqPop]. + apply BVEq_iff_eq in EqS, EqSlot, EqCnt, EqCref; move: EqPop => /eqP EqPop; + subst state slot cnt cref pop. + cbv [TDMSM LoopInit]. + cbn [step fst snd]; simpl_ret. + admit. + } + Admitted. + +End CavaFIFOREFProperties. \ No newline at end of file diff --git a/framework/CavaDRAM/Lib/CavaCounter.v b/framework/CavaDRAM/Lib/CavaCounter.v index b2f24fa..b261b5a 100644 --- a/framework/CavaDRAM/Lib/CavaCounter.v +++ b/framework/CavaDRAM/Lib/CavaCounter.v @@ -15,7 +15,7 @@ Require Export CavaMemory. Require Export Lia. Require Export Omega. -From DRAM Require Export FIFO. +From CoqDRAM Require Export FIFO. Section CavaCounter. diff --git a/framework/CavaDRAM/Lib/CavaFIFO.v b/framework/CavaDRAM/Lib/CavaFIFO.v index 0a94dcd..af6dd3b 100644 --- a/framework/CavaDRAM/Lib/CavaFIFO.v +++ b/framework/CavaDRAM/Lib/CavaFIFO.v @@ -12,7 +12,7 @@ From CavaDRAM Require Export CavaSystem. From CavaDRAM Require Export CavaMemory. From CavaDRAM Require Export CavaSubtractor. -From DRAM Require Export FIFO. +From CoqDRAM Require Export FIFO. Infix "++" := Vector.append. diff --git a/framework/CavaDRAM/Lib/CavaFIFOREFProperties.v b/framework/CavaDRAM/Lib/CavaFIFOREFProperties.v new file mode 100644 index 0000000..1e336a4 --- /dev/null +++ b/framework/CavaDRAM/Lib/CavaFIFOREFProperties.v @@ -0,0 +1,1630 @@ +Set Printing Projections. +Set Warnings "-notation-overridden,-parsing". + +From CavaDRAM Require Import CavaFIFOREF CavaSM CavaReqQueue CavaCommonInstances CavaSubtractor Step CavaSystem Memory Util UtilSM. +From CoqDRAM Require Import FIFO. +From Coq Require Import Program BinaryString HexString NArith. +From Cava Require Import Cava CavaProperties Util.Vector Util.Tactics. +From mathcomp Require Import fintype ssrZ zify ring. + +Section CavaFIFOREFProperties. + + Context {signal : SignalType -> Type} {semantics : Cava signal}. + (* From Cava *) + Existing Instance CombinationalSemantics. + (* From CavaDRAM*) + Context {CAVA_SYS : CavaSystem}. + (* From CoqDRAM *) + Existing Instance REQESTOR_CFG. + Context {SYS_CFG : System_configuration}. + Context {FIFO_CFG : FIFO_configuration}. + Context {HAF : HW_Arrival_function_t}. + Existing Instance ARBITER_CFG. + Existing Instance FIFO_implementation. + + Import Memory.Properties BvectorNotations. + Open Scope Bvector_scope. + + Lemma leq_Nle (a b : N) : + leq (nat_of_bin a) (nat_of_bin b) -> (a <= b)%N. + Proof. + lia. + Qed. + + Lemma ltn_Ntn (a b : N) : + leq (S (nat_of_bin a)) (nat_of_bin b) -> (a < b)%N. + Proof. + lia. + Qed. + + Lemma log2_eq1_pw2 (n : nat) : + Nat.pow 2 (Nat.log2 n) = n -> + Nat.log2 n = 1 -> n = 2. + Proof. + intros. by rewrite H0 in H. + Qed. + + Lemma Bv_eq_translation {n} (a b : Bvector n) : + (nat_of_bin (Bv2N a) = nat_of_bin (Bv2N b)) -> + (Bv2N a = Bv2N b)%N. + Proof. + lia. + Qed. + + Lemma Bv_ltn_translation {n} (a b : Bvector n) : + (nat_of_bin (Bv2N a) < nat_of_bin (Bv2N b)) -> + (Bv2N a < Bv2N b)%N. + Proof. + lia. + Qed. + + Lemma lt_trans_le (n m p : N): + (m < n)%N -> (n < p)%N -> (m + 1 < p)%N. + Proof. + lia. + Qed. + + Lemma to_nat_lt_of_nat (a : N) (n : nat) : + N.to_nat a < n -> (a < N.of_nat n)%N. + Proof. + intros. + induction n; [ discriminate | ]. + rewrite leq_eqVlt in H; move: H => /orP [/eqP H | H]. + { rewrite -H Nat2N.inj_succ N2Nat.id; by specialize (N.lt_succ_diag_r a). } + assert (N.to_nat a < n). + { specialize (ltn_add2r 1 (N.to_nat a) n) as S; rewrite !addn1 in S; by rewrite S in H. } + apply IHn in H0. + apply N.lt_trans with (m := N.of_nat n); [ done | ]. + rewrite Nat2N.inj_succ; by specialize (N.lt_succ_diag_r (N.of_nat n)). + Qed. + + Lemma to_nat_lt_pow a b: + N.to_nat a < Nat.pow 2 b -> (a < 2 ^ N.of_nat b)%N. + Proof. + intros; apply to_nat_lt_of_nat in H. + rewrite -Nat2N.inj_pow in H. + by simpl (N.of_nat 2) in H. + Qed. + + Lemma length_to_list_shiftin {A N} (v : Vector.t A N) (e : A) : + Datatypes.length (Vector.to_list (Vector.shiftin e v)) = N + 1. + Proof. + induction v; [ rewrite //= | ]. + unfold Vector.shiftin; fold @Vector.shiftin. + rewrite to_list_cons cons_length IHv; lia. + Qed. + + Lemma last_shiftin {A N} (v : Vector.t A N) (def e : A) : + last (Vector.to_list (Vector.shiftin e v)) def = e. + Proof. + induction v; [ rewrite //= | ]. + unfold Vector.shiftin; fold @Vector.shiftin. + rewrite to_list_cons //=. + destruct (Vector.to_list (Vector.shiftin e v)) eqn:Hbug; + [ contradict Hbug; induction v; simpl; done | ]. + done. + Qed. + + Lemma Bv2N_upper_bound {n : nat} (bv : Bvector n) : + (N.to_nat (Bv2N bv) < (Nat.pow 2 n)). + Proof. + induction bv; [ by simpl | ]; destruct h; rewrite Bv2N_cons. + { rewrite N.succ_double_spec. + set z := Bv2N _; fold z in IHbv. + rewrite N2Nat.inj_add N2Nat.inj_mul. + vm_compute (N.to_nat 1); vm_compute (N.to_nat 2). + assert ((2 * N.to_nat z)%coq_nat = (2 * N.to_nat z)%nat); try done; rewrite H; clear H. + assert ((2 * N.to_nat z + 1)%coq_nat = (2 * N.to_nat z + 1)%nat); try done; rewrite H; clear H. + apply ltn_mul_add1 in IHbv. + rewrite Nat.pow_succ_r; [ | apply /leP; by rewrite leq0n ]. + assert ((2 * (2 ^ n))%coq_nat = (2 * (2 ^ n))%nat); try done; rewrite H; clear H. } + { rewrite N.double_spec N2Nat.inj_mul; set z := Bv2N _; fold z in IHbv; vm_compute (N.to_nat 2). + assert ((2 * N.to_nat z)%coq_nat = (2 * N.to_nat z)%nat); try done; rewrite H; clear H. + have aux : (0 < 2); [ done | ]. + have H := (ltn_pmul2l aux); rewrite -H in IHbv. + rewrite Nat.pow_succ_r; [ | apply /leP; by rewrite leq0n ]; clear H. + assert ((2 * (2 ^ n))%coq_nat = (2 * (2 ^ n))%nat); try done; rewrite H; clear H. + } + Qed. + + Lemma size_nat_sub_leq {n} (a b : Bvector n): + (Bv2N b <= Bv2N a)%N -> + N.size_nat (Bv2N a - Bv2N b) <= n. + Proof. + intros; apply /leP; apply N.size_nat_le. + specialize (@Bv2N_upper_bound n a) as Ha. + specialize (@Bv2N_upper_bound n b) as Hb. + destruct (Bv2N b) eqn:Hb0, (Bv2N a) eqn:Ha0; try discriminate. + { simpl in *; by apply to_nat_lt_pow. } + { rewrite N.sub_0_r; by apply to_nat_lt_pow in Ha. } + { by contradict H. } + { apply to_nat_lt_pow in Ha,Hb. + apply (N.lt_trans (N.pos p0 - N.pos p) (N.pos p0) (2 ^ N.of_nat n)%N); [ | done]. + apply N.sub_lt; done. + } + Qed. + + Lemma N2Bv_sized_eq_p1_false {W} (v : Bvector W): + W > 0 -> (N2Bv_sized W (Bv2N v + 1) =? v) = false. + Proof. + intros; apply BVEq_iff_neq. + rewrite N.add_1_r. + specialize (N2Bv_sized_Bv2N W v) as H0; rewrite -{2}H0. + by apply N2Bv_sized_neq_succ. + Qed. + + Lemma cons_eq {n} (x : bool) (a b : Vector.t bool n): + (x :: a)%vector =? (x :: b)%vector -> + BVeq n n a b. + Proof. + Admitted. + + Lemma Bvector_wrap {W} (v : Bvector W) : + W > 0 -> N2Bv_sized W (Bv2N (N2Bv_sized W (Bv2N v + 1)) + 1) =? v -> + W = 1. + Proof. + intros Hpos H. + induction v; intros; try discriminate. + rewrite ltnS leq_eqVlt in Hpos; move: Hpos => /orP [/eqP Heq | Hpos]; + [ by subst n | ]. + apply (IHv) in Hpos as IH; clear IHv. + 2: { + destruct h; simpl in H; [ + rewrite N.succ_double_succ N2Bv_sized_double Bv2N_cons N.double_succ_double + N2Bv_sized_succ_double N2Bv_sized_Bv2N in H | + rewrite N.double_succ_double N2Bv_sized_succ_double Bv2N_cons N.succ_double_succ + N2Bv_sized_double N2Bv_sized_Bv2N in H ]; + apply cons_eq in H; + specialize (@N2Bv_sized_eq_p1_false n v) as HH; apply HH in Hpos; + by rewrite Hpos in H. + } + revert H; generalize v; clear v; rewrite IH; intros. + simpl in H; destruct h; rewrite (Vector.eta v) in H; + specialize (@tl_0 bool v) as H0; rewrite H0 in H; + destruct (VectorDef.hd v); simpl in H; discriminate H. + Qed. + + (* --------------------------------------------------------------- *) + (* Start of FIFO specific proofs *) + Lemma N2Bv_sized_queuemax_neq0 : + N2Bv_sized ADDR_WIDTH 0 <> N2Bv_sized ADDR_WIDTH (N.of_nat QUEUE_MAX_SIZE - 1). + Proof. + apply N2Bv_sized_neq_iff; unfold ADDR_WIDTH. + { rewrite /N.size_nat /Nat.log2 //=. } + { rewrite -N.pred_sub -Nat2N.inj_pred. + apply /leP; apply N.size_nat_le_nat. + rewrite QUEUE_MAX_SIZE_PW2; apply /leP. + rewrite ltn_predL; apply /leP. + exact QUEUE_MAX_SIZE_GT_0. } + { rewrite -N.pred_sub -Nat2N.inj_pred. + specialize QUEUE_MAX_SIZE_DIFF_0 as HH. + move: HH => /N.eqb_spec HH. + by apply /N.eqb_spec. + } + Qed. + + Definition mem_cells_ := + mem_cells (Vec Bit REQUEST_WIDTH) ADDR_WIDTH (Nat.pow 2 ADDR_WIDTH) InitMem. + + Lemma shiftin_nth_default {A} (def : A) (a : A) n (v: Vector.t A n) (k1 k2 : nat) (eq: k1 = k2): + k1 < n -> + nth_default def k1 (Vector.shiftin a v) = nth_default def k2 v. + Admitted. + + (* --------------------------------------------------------------- *) + (* Solving the memory problem *) + + Lemma nth_cells_read {T W I} (ad : Bvector W) c_req def + (c : circuit_state (mem_cells T W (2 ^ W) I)) : + nth_default def (N.to_nat (Bv2N ad)) (Cells_read true (N.to_nat (Bv2N ad)) c_req c) = c_req. + Admitted. + + Lemma nth_cells_read_ {T W I N} (ad : Bvector (Nat.log2 N)) c_req def + (c : circuit_state (mem_cells T W N I)) : N > 0 -> + nth_default def (N.to_nat (Bv2N ad)) (Cells_read true (N.to_nat (Bv2N ad)) c_req c) = c_req. + Proof. + intros Hpos; rewrite nth_default_to_list. + induction N; intros; [ discriminate | ]. + rewrite leq_eqVlt in Hpos; move: Hpos => /orP [/eqP Heq | Hpos]. + { assert (N = 0); [ lia | ]; clear IHN Heq; subst N. + revert ad; rewrite Nat.log2_1; intros. + apply Vector.case0 with (v := ad). + simpl in c; destruct_products. + rewrite /Cells_read //= andb_true_r. + } + assert (0 < N); [ lia | ]; clear Hpos. + simpl in c; destruct_products; rewrite //= andb_true_r. + specialize (Nat.log2_succ_or N) as Hor; destruct Hor as [Hor | Hor]. + { revert ad; rewrite Hor; intros. + destruct (Nat.eqb (N.to_nat (Bv2N ad)) N) eqn:HH; set memvec := Cells_read true _ _ _. + { assert (N.to_nat (Bv2N ad) = N) as H0; [ lia | ]; clear HH; + rewrite H0. + specialize (@length_to_list_shiftin (combType T) N memvec c_req) as HH. + assert (N = (Datatypes.length (Vector.to_list (Vector.shiftin c_req memvec))) - 1)%coq_nat; [ lia | ]. + apply nth_last with (d := def) in H1; rewrite H1. + by rewrite last_shiftin. } + { unfold memvec. + specialize (IHN (VectorDef.tl ad) c0); apply IHN in H as IH; clear IHN. + rewrite (Vector.eta ad) Bv2N_cons. + destruct (Vector.hd ad). + { rewrite N2Nat.inj_succ_double //= !Nat.add_0_r. + rewrite -nth_tl. + set adtl := N.to_nat (Bv2N (VectorDef.tl ad)). + fold adtl in IH. + admit. } + { admit. } + Admitted. + (*-----------------------------------------------------------------------------------*) + + Lemma memcell_nch (c: circuit_state mem_cells_) (wra rda : Bvector ADDR_WIDTH) c_req def: + wra <> rda -> + nth_default def (N.to_nat (Bv2N rda)) (Cells_data c) = + nth_default def (N.to_nat (Bv2N rda)) (Cells_read true (N.to_nat (Bv2N wra)) c_req c). + Admitted. + + (* Need a to be bigger than b *) + Lemma size_nat_qms_sub (a b: Bvector ADDR_WIDTH) : + (Bv2N b < Bv2N a)%N -> + N.size_nat (N.of_nat QUEUE_MAX_SIZE - (Bv2N a - Bv2N b)) <= ADDR_WIDTH. + Proof. + intros Hlt; apply /leP. + destruct (Bv2N b) eqn:Hb0, (Bv2N a) eqn:Ha0; try done; + apply N.size_nat_le; unfold ADDR_WIDTH; rewrite QUEUE_MAX_SIZE_PW2_N; try rewrite N.sub_0_r. + { apply N.sub_lt; [ | done]. + unfold ADDR_WIDTH in a,b. + specialize (@Bv2N_upper_bound (Nat.log2 QUEUE_MAX_SIZE) a) as Ha. + rewrite QUEUE_MAX_SIZE_PW2 in Ha. + rewrite Ha0 in Ha. + apply to_nat_lt_of_nat in Ha. + apply N.le_lteq; left; exact Ha. + } + { apply N.sub_lt; [ | apply N.lt_add_lt_sub_l; by rewrite N.add_0_r ]. + unfold ADDR_WIDTH in a,b. + specialize (@Bv2N_upper_bound (Nat.log2 QUEUE_MAX_SIZE) a) as Ha. + rewrite QUEUE_MAX_SIZE_PW2 in Ha. + specialize (@Bv2N_upper_bound (Nat.log2 QUEUE_MAX_SIZE) b) as Hb. + rewrite QUEUE_MAX_SIZE_PW2 in Hb. + apply to_nat_lt_of_nat in Ha,Hb; rewrite Ha0 in Ha; rewrite Hb0 in Hb. + apply N.le_sub_le_add_l; rewrite N.add_comm. + apply N.lt_trans with (m := N.of_nat (@QUEUE_MAX_SIZE CAVA_SYS)) (n := N.pos p0) + (p := N.add (N.of_nat (@QUEUE_MAX_SIZE CAVA_SYS)) (N.pos p)) in Ha as H; + [ apply N.le_lteq; by left | ]. + apply N.lt_add_pos_r; done. + } + Qed. + + Lemma size_nat_qms : + N.size_nat (N.of_nat QUEUE_MAX_SIZE - 1) <= Nat.log2 QUEUE_MAX_SIZE. + Proof. + rewrite N.sub_1_r -Nat2N.inj_pred. + apply /leP; apply N.size_nat_le_nat. + rewrite QUEUE_MAX_SIZE_PW2. + apply /ltP; rewrite ltn_predL; apply /ltP. + exact QUEUE_MAX_SIZE_GT_0. + Qed. + + Definition State_t := circuit_state FIFOSM. + + Definition get_mem (s : State_t) : circuit_state memqueue' := + let '(_,(_,(_,(_,_,_,memqueue_state,_,_,_,_,_),_),_,_)) := s in memqueue_state. + + Definition get_pop (s : State_t) := + let '(_,(_,_,_,pop)) := s in pop. + + Definition get_st (s : State_t) := + let '(_,(_,_,(_,(_,_,st)),_)) := s in st. + + Definition get_cnt (s : State_t) := + let '(_,(_,_,(_,(_,(_,_,cnt),_)),_)) := s in cnt. + + Definition get_cref (s : State_t) := + let '(_,(_,_,(_,(_,(_,(_,_,_,_,_,_,_,cref),_),_)),_)) := s in cref. + + Definition get_cr (s : State_t) := + let '(_,(_,_,(_,(_,(_,(_,(_,(_,cr)),_,_,_,_,_,_),_),_)),_)) := s in cr. + + Definition get_wra (s : State_t) := + let '(_,(_,(_,_,wra),_,_)) := s in wra. + + Definition get_rda (s : State_t) := + let '(_,(_,(_,(_,_,_,_,_,_,_,_,rda),_),_,_)) := s in rda. + + Definition get_reqqueue (s : State_t) : circuit_state RequestQueue' := + let '(_,(cs_requeue,_,_)) := s in cs_requeue. + + Definition get_mem_RequestQueue (c : circuit_state RequestQueue') := + let '(_,(_,(_,_, _,memqueue_state,_,_,_,_,_),_)) := c in memqueue_state. + + Definition get_addr_RequestQueue (c : circuit_state RequestQueue') := + let '(_,(_,(_,_, _,_,_,_,_,_,rda),wra)) := c in (wra,rda). + + Definition get_memcells (s : circuit_state memqueue') := + let '(_,memcells_state,_) := s in memcells_state. + + Definition get_memcells_RequestQueue (c : circuit_state RequestQueue') := + get_memcells (get_mem_RequestQueue c). + + (* --------------------------Bounding the counter ------------------- *) + Lemma cnt_bounded (cnt : Bvector COUNTER_WIDTH) : + N.to_nat (Bv2N cnt) < WAIT. + Proof. + specialize @Bv2N_upper_bound with (bv := cnt) as H. + by rewrite /COUNTER_WIDTH WAIT_PW_2 in H. + Qed. + + Definition Bv2cnt (cnt : Bvector COUNTER_WIDTH) : Counter_t := + Ordinal (cnt_bounded cnt). + + Definition cnt2Bv (cnt : Counter_t) := + N2Bv_sized COUNTER_WIDTH (N.of_nat (nat_of_ord cnt)). + (* ------------------------------------------------------------------ *) + + (* --------------------------Bounding cref counter ------------------- *) + Lemma cref_bounded (cref : Bvector COUNTER_REF_WIDTH) : + N.to_nat (Bv2N cref) < WAIT_REF. + Proof. + specialize @Bv2N_upper_bound with (bv := cref) as H. + by rewrite /COUNTER_REF_WIDTH WAIT_REF_PW2 in H. + Qed. + + Definition Bv2cref (cnt : Bvector COUNTER_REF_WIDTH) : Counter_ref_t := + Ordinal (cref_bounded cnt). + + Definition cref2Bv (cref : Counter_ref_t) := + N2Bv_sized COUNTER_REF_WIDTH (N.of_nat (nat_of_ord cref)). + (* ------------------------------------------------------------------ *) + + Lemma cref_preadate_false (c : Counter_ref_t) : + (cref2Bv c =? CNT_REF_PREA) = false <-> + (nat_of_ord c == PREA_date - 1) = false. + Proof. + split. { + unfold cref2Bv, CNT_REF_PREA; intros. + apply BVEq_iff_neq in H; rewrite bitvec_literal_correct in H. + apply N2Bv_sized_neq_if in H. + apply of_nat_neq in H. + by apply /eqP. + } + { intros. + apply BVEq_iff_neq. + rewrite /cref2Bv /CNT_REF_PREA bitvec_literal_correct. + apply N2Bv_sized_neq_iff; [ | | move: H => /eqP H; by rewrite Nat2N.inj_iff ]; + apply /leP; apply N.size_nat_le_nat; unfold COUNTER_REF_WIDTH; apply /leP; + rewrite WAIT_REF_PW2; [ by destruct c | specialize WAIT_REF_PREA_date as HH; by lia ]. + } + Qed. + + Lemma cref_preadate_true (c : Counter_ref_t) : + (cref2Bv c =? CNT_REF_PREA) = true <-> + (nat_of_ord c == PREA_date - 1) = true. + Proof. + split. + { unfold cref2Bv, CNT_REF_PREA; intros. + apply BVEq_iff_eq in H; rewrite bitvec_literal_correct in H. + apply N2Bv_sized_eq_iff in H. + { apply Nat2N.inj in H; rewrite H; by apply /eqP. } + { apply N.size_nat_le_nat. + destruct c; simpl in *; rewrite /COUNTER_REF_WIDTH; apply /ltP. + by rewrite WAIT_REF_PW2. } + { apply N.size_nat_le_nat; unfold COUNTER_REF_WIDTH. + rewrite WAIT_REF_PW2 subn1; apply /ltP. + specialize WAIT_REF_PREA_date as HH. + apply ltn_trans with (m := PREA_date.-1) in HH; [ exact HH | ]. + by rewrite ltn_predL PREA_date_pos. + } + } + { intros Href_prea; move: Href_prea => /eqP Href_prea; apply BVEq_iff_eq. + rewrite /cref2Bv /CNT_REF_PREA bitvec_literal_correct; f_equal. + by rewrite Href_prea. + } + Qed. + + Definition fullQueue (wa ra : Bvector ADDR_WIDTH) : bool := + let waN := Bv2N wa in + let raN := Bv2N ra in + let qms := N.sub (N.of_nat QUEUE_MAX_SIZE) 1 in + if (raN <= waN)%nat then ((Bv2N wa - Bv2N ra)%N == qms) + else (((N.add qms 1) - (raN - waN))%N == qms). + + Hypothesis HaltIfFull : forall t c, + let wra := get_wra c in + let rda := get_rda c in + if (HW_Arrival_at t != []) then ~~ fullQueue wra rda else true. + + Program Definition EqReq (r : Request_t) (r' : Bvector REQUEST_WIDTH) : bool. + Admitted. + + Lemma EqReqNil : EqReq nullreq REQUEST_NIL = true. + Admitted. + + Definition EqCmd (f_cmd : Command_kind_t) (c_cmd : Bvector DRAM_CMD_WIDTH) : bool := + match f_cmd with + | ACT => (c_cmd =? ACT_VEC) + | PRE => (c_cmd =? PRE_VEC) + | PREA => (c_cmd =? PREA_VEC) + | CRD => (c_cmd =? RD_VEC) + | CWR => (c_cmd =? WR_VEC) + | REF => (c_cmd =? REF_VEC) + | NOP => (c_cmd =? NOP_VEC) + end. + + Fixpoint EqQueue (P : Requests_t) (wra rda : Bvector ADDR_WIDTH) := + match P with + | [::] => (wra =? rda) + | x :: x0 => negb (wra =? rda) && (EqQueue x0 wra (N2Bv_sized ADDR_WIDTH (Bv2N rda + 1))) + end. + + Lemma EqQueue_diff_adr r0 r1 wra rda: + EqQueue (r0 :: r1) wra rda -> wra <> rda. + Proof. + simpl; intros; move: H => /andP [Hd H]; + by move: Hd => /negPf Hd; apply BVEq_iff_neq in Hd. + Qed. + + Lemma EqQueue_aux wra rda r0 r1 r: + ~~ fullQueue wra rda -> wra <> rda -> + EqQueue (r0 :: r1)%SEQ wra rda -> + EqQueue ((r0 :: r1)%SEQ ++ [r])%SEQ (N2Bv_sized ADDR_WIDTH (Bv2N wra + 1)) rda. + Proof. + intros NFULL Hadr HQ; rewrite //=. + simpl in HQ; move: HQ => /andP [_ HQ]. + revert HQ Hadr NFULL; generalize wra rda; induction r1; intros; simpl in HQ. + { apply /andP; split. + { unfold fullQueue in NFULL. + move: NFULL; apply contraPN; intros; apply /negP; rewrite negb_involutive. + specialize ADDR_WIDTH_pos as Hawp; move: Hawp => /ltP Hawp. + destruct (Bv2N rda0 <= _) eqn:Hleq. + { apply BVEq_iff_eq in HQ as HQ'; rewrite HQ' in H; clear HQ'. + apply Bvector_wrap in H; [ | apply /ltP; exact ADDR_WIDTH_pos ]. + apply log2_eq1_pw2 in H as H2 ; [ | by rewrite QUEUE_MAX_SIZE_PW2 ]; clear H. + rewrite H2; simpl ((N.of_nat 2 - 1)%N); simpl (N.add (Npos _) (Npos _)). + apply BVEq_iff_eq in HQ; rewrite HQ Bv2N_N2Bv_sized; [ lia | ]. + apply /N.ltb_spec0. + destruct ((Bv2N rda0 + 1 <? 2 ^ N.of_nat ADDR_WIDTH)%N) eqn:Hcont; [ done | ]. + move: Hcont => /negP /negP Hcont; rewrite -N.leb_antisym in Hcont. + move: Hcont => /N.leb_spec0 Hcont. + unfold ADDR_WIDTH in Hcont; rewrite QUEUE_MAX_SIZE_PW2_N in Hcont. + rewrite leq_eqVlt in Hleq; move: Hleq => /orP [/eqP Hbug | Hltn]. + { specialize (@Bv2N_inj ADDR_WIDTH rda0 wra0) as HH. + apply Bv_eq_translation in Hbug; apply HH in Hbug; by rewrite Hbug in Hadr. } + apply N.le_lteq in Hcont; destruct Hcont as [Hcont0 | Hcont1]; + specialize (@Bv2N_upper_bound ADDR_WIDTH wra0) as H; + apply Bv_ltn_translation in Hltn; + apply to_nat_lt_pow in H; + rewrite /ADDR_WIDTH QUEUE_MAX_SIZE_PW2_N in H; + apply lt_trans_le with (p := N.of_nat QUEUE_MAX_SIZE) in Hltn; try done. + { contradict Hcont0; by apply N.lt_asymm. } + { contradict Hcont1; apply N.neq_sym; by apply N.lt_neq. } + } + { apply BVEq_iff_eq in H; rewrite -H Bv2N_N2Bv_sized; [ lia | ]. + move: Hleq => /negP /negP Hleq; rewrite -ltnNge in Hleq. + apply /N.ltb_spec0. + destruct ((Bv2N wra0 + 1 <? 2 ^ N.of_nat ADDR_WIDTH)%N) eqn:Hcont; [ done | ]. + unfold ADDR_WIDTH in Hcont; rewrite QUEUE_MAX_SIZE_PW2_N in Hcont. + move: Hcont => /negP /negP Hcont; rewrite -N.leb_antisym in Hcont; move: Hcont => /N.leb_spec0 Hcont. + apply N.le_lteq in Hcont; destruct Hcont as [Hcont0 | Hcont1]. + { (* use rda bound*) admit. (* proof on page 11 of FIFO notebook *) } + { specialize (@Bv2N_upper_bound ADDR_WIDTH rda0) as Hu. + unfold ADDR_WIDTH in Hu; rewrite QUEUE_MAX_SIZE_PW2 in Hu. + assert (QUEUE_MAX_SIZE = N.to_nat (Bv2N wra0 + 1)). + { specialize (N2Nat.id (Bv2N wra0 + 1)) as H_; rewrite -H_ in Hcont1. + by apply Nat2N.inj in Hcont1. } + admit. + (* finish proof by rewriting H1 in Hu, which results in + (Bv2N rda < Bv2N wra + 1) -> (Bv2N rda <= Bv2N wra), which contradicts + Bv2N wra < Bv2N rda *) + } + } + } + { simpl; apply BVEq_iff_eq in HQ; apply /andP; split. + { admit. (* should be easy *) } + { rewrite HQ; by apply BVEq_iff_eq. } + } + } + move: HQ => /andP [neq HQ]. + specialize (IHr1 wra0 (N2Bv_sized ADDR_WIDTH (Bv2N rda0 + 1))); apply IHr1 in HQ as IH; clear IHr1. + 3: { + (* Don't know how to prove that *) + (* holds logically (page 12 FIFO notebook) *) + unfold fullQueue; unfold fullQueue in NFULL. + admit. + } + 2: by move: neq => /negPf neq; apply BVEq_iff_neq in neq. + simpl; apply /andP; split. + { move: IH => /andP [neq_ IH]. + admit. (* holds logically (page 12 FIFO notebook )*) } + exact IH. + Admitted. + + Check nth_default. + + Fixpoint EqMem_ {W} (P : Requests_t) (rda : Bvector W) + (memcells_vec : Vector.t (Bvector REQUEST_WIDTH) (Nat.pow 2 W)) : bool := + match P with + | [::] => true + | x :: x0 => + let nrda := N2Bv_sized W (Bv2N rda + 1) in + let s := nth_default REQUEST_NIL (N.to_nat (Bv2N rda)) memcells_vec in + (EqReq x s) && (EqMem_ x0 nrda memcells_vec) + end. + + Lemma EqMem_rcons r1 (rda wra : Bvector ADDR_WIDTH) c R (c_req : combType (Vec Bit REQUEST_WIDTH)) : + EqQueue r1 wra rda -> + EqMem_ r1 rda (@Cells_data (Vec Bit REQUEST_WIDTH) ADDR_WIDTH (Nat.pow 2 ADDR_WIDTH) InitMem c) -> + EqReq R c_req -> + EqMem_ (r1 ++ [R])%SEQ rda (Cells_read true (N.to_nat (Bv2N wra)) c_req c). + Proof. + intros HQ Mem EqR; fold mem_cells_ in c; rewrite cats1. + revert Mem HQ; generalize wra rda; induction r1; intros. + { simpl; rewrite andb_true_r; simpl in HQ; apply BVEq_iff_eq in HQ; rewrite HQ. + rewrite VectorSpec.map_id. + unfold ADDR_WIDTH in wra,rda. + specialize (@nth_cells_read (Vec Bit REQUEST_WIDTH) ADDR_WIDTH InitMem + rda0 c_req REQUEST_NIL) as HH; rewrite /REQUEST_NIL bitvec_literal_correct //= in HH; + unfold mem_cells_ in c; by rewrite HH. } + simpl in Mem,HQ; simpl. + move: Mem => /andP [EqR_ Mem]; apply /andP; split. + { move: HQ => /andP [/negPf Heq HQ]; + apply BVEq_iff_neq in Heq; rewrite VectorSpec.map_id; rewrite VectorSpec.map_id in EqR_. + rewrite -memcell_nch; done. + } + { move: HQ => /andP [neq HQ]. + specialize (IHr1 wra0 (N2Bv_sized ADDR_WIDTH (Bv2N rda0 + 1))); apply IHr1; done. + } + Qed. + + (* Just use the circuit directly <-> circuit does the work directly *) + Definition EqMem (P : Requests_t) rda (mem : circuit_state RequestQueue') := + let memcells_vec := Cells_data (get_memcells_RequestQueue mem) in + EqMem_ P rda memcells_vec. + + Definition State_Eq (fram_state : FIFO_state_t) (cava_state : State_t) : bool := + let s := get_st cava_state in + let c' := get_cnt cava_state in + let cref' := get_cref cava_state in + let r' := get_cr cava_state in + let RQ := get_reqqueue cava_state in + let wra := fst (get_addr_RequestQueue RQ) in + let rda := snd (get_addr_RequestQueue RQ) in + let pop := get_pop cava_state in + match fram_state with + | IDLE c cref P => + (s =? STATE_IDLE_VEC) && (c' =? cnt2Bv c) && (cref' =? cref2Bv cref) && (EqMem P rda RQ) && + (EqQueue P wra rda) && (pop == false) + | RUNNING c cref P r => + (s =? STATE_RUN_VEC) && (c' =? cnt2Bv c) && (cref' =? cref2Bv cref) && (EqMem P rda RQ) && + (EqQueue P wra rda) && (EqReq r r') && (pop == (c == OCycle0)) + | REFRESHING cref P => + (s =? STATE_REF_VEC) && (cref' =? cref2Bv cref) && (EqMem P rda RQ) && + (EqQueue P wra rda) && (pop == false) + end. + + (* -------------- Proofs about CmdGen ------------------------------- *) + Lemma CmdGen_equiv_idle_to_idle (c : circuit_state CmdGen) cnt cref: + (cref =? CNT_REF_PREA) = false -> + exists c', step CmdGen c (STATE_IDLE_VEC,true,cnt,cref,REQUEST_NIL) = + (c',NOP_VEC). + Proof. + intros H; simpl in c; destruct_products. + eapply ex_intro. + cbv [CmdGen]; cbn [step fst snd]. + simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + fast_simpl_bool; simpl. + cbv [CrefPREA_eq]. + apply BVEq_iff_neq in H. + specialize @CavaPreludeProperties.eqb_neq with (t := Vec Bit (@COUNTER_REF_WIDTH SYS_CFG FIFO_CFG)) as HH. + apply HH in H; rewrite H VectorSpec.map_id; reflexivity. + Qed. + + Lemma CrefPREA_lt_CNT_REF_PREA: + CrefPREA_lt CNT_REF_PREA = false. + Proof. + cbv [CrefPREA_lt]; simpl_ident. + unfold greaterThanOrEqual; simpl_ident; unfold greaterThanOrEqualBool. + apply /negbF. + rewrite {1}/CNT_REF_PREA; rewrite !bitvec_literal_correct. + apply /N.leb_spec0; rewrite /CNT_REF_PREA /CNT_REF_WAIT !bitvec_literal_correct. + rewrite !Bv2N_N2Bv_sized. { apply N.le_add_r. } + all: rewrite /COUNTER_REF_WIDTH WAIT_REF_PW_N. + all: try apply N_lt_inj. + all: specialize WAIT_REF_PREA_date_WAIT as H; lia. + Qed. + + Lemma CmdGen_equiv_idle_to_ref (c : circuit_state CmdGen) cnt cref e: + (cref =? CNT_REF_PREA) = true -> + exists c', step CmdGen c (STATE_IDLE_VEC,e,cnt,cref,REQUEST_NIL) = (c',PREA_VEC). + Proof. + intros; simpl in c; destruct_products; eapply ex_intro. + cbv [CmdGen]; cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + fast_simpl_bool; simpl; rewrite VectorSpec.map_id. + apply BVEq_iff_eq in H; subst cref; rewrite CrefPREA_lt_CNT_REF_PREA !VectorSpec.map_id. + rewrite andb_false_r; rewrite /CrefPREA_eq. + specialize @CavaPreludeProperties.eqb_eq with (t := Vec Bit (@COUNTER_REF_WIDTH SYS_CFG FIFO_CFG)) as HH. + assert (CNT_REF_PREA = CNT_REF_PREA); [done | ]; apply HH in H; by rewrite H. + Qed. + + Lemma CrefPREA_lt_CNT_REF_WAIT cref: + (cref2Bv cref =? CNT_REF_PREA) = false -> (cref + WAIT < PREA_date) = true -> + CrefPREA_lt (cref2Bv cref) = true. + Proof. + intros Href_prea Href_service. + rewrite /CrefPREA_lt; simpl_ident; rewrite /greaterThanOrEqual; simpl_ident. + rewrite /greaterThanOrEqualBool /CNT_REF_WAIT /CNT_REF_PREA !bitvec_literal_correct !Bv2N_N2Bv_sized. + { destruct (~~ _) eqn:Hbug; [ done | ]. + apply negbFE in Hbug; move: Hbug => /N.leb_spec0 Hbug. + assert (cref + (WAIT - 1) < (PREA_date - 1)). + { rewrite addnBA; [ | exact WAIT_pos]. + rewrite subn1 -ltnS prednK; [ | by rewrite addn_gt0 WAIT_pos orb_true_r ]. + rewrite subn1 prednK; [ | exact PREA_date_pos]. + by rewrite Href_service. + } + move: H => /ltP H; apply N_lt_inj in H. + contradict Hbug; apply N.nle_gt; by rewrite -Nat2N.inj_add. + } + all: unfold COUNTER_REF_WIDTH; rewrite WAIT_REF_PW_N. + all: try rewrite -Nat2N.inj_add; apply N_lt_inj; apply /ltP. + all: destruct cref; simpl in *; try done. + all: specialize WAIT_REF_PREA_date_WAIT; lia. + Qed. + + Lemma CmdGen_equiv_idle_to_running (c : circuit_state CmdGen) cnt cref tr: + (cref2Bv cref =? CNT_REF_PREA) = false -> + (cref + WAIT < PREA_date) = true -> + exists c', step CmdGen c (STATE_IDLE_VEC,false,cnt,(cref2Bv cref),tr) = (c',PRE_VEC). + Proof. + intros; simpl in c; destruct_products; eapply ex_intro. + cbv [CmdGen]; cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + fast_simpl_bool; simpl; rewrite !VectorSpec.map_id. + rewrite CrefPREA_lt_CNT_REF_WAIT; done. + Qed. + (* ------------------------------------------------------------------ *) + + (* -------------- Proofs about NextCR ------------------------------- *) + Lemma NextCR_equiv (c : circuit_state NextCR) cnt cref tr: + exists c', step NextCR c (STATE_IDLE_VEC,true,cnt,cref,tr) = + (c',REQUEST_NIL). + Proof. + simpl in c; destruct_products. + eapply ex_intro. + cbv [NextCR LoopInit]; cbn [step fst snd]. + simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + fast_simpl_bool; by simpl. + Qed. + + Lemma NextCR_equiv_IDLE_NE_PREA c cnt cref tr: + (cref =? CNT_REF_PREA) = true -> + exists c', step NextCR c (STATE_IDLE_VEC,false,cnt,cref,tr) = + (c',REQUEST_NIL). + Proof. + intros; simpl in c; destruct_products; eapply ex_intro. + cbv [NextCR LoopInit]; cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + rewrite negb_false andb_true_l; rewrite /Srun //= VectorSpec.map_id. + apply BVEq_iff_eq in H; subst cref. + by rewrite CrefPREA_lt_CNT_REF_PREA. + Qed. + + Lemma NextCR_equiv_IDLE_RUNNING c cnt (cref : Counter_ref_t) tr: + (cref2Bv cref =? CNT_REF_PREA) = false -> + (cref + WAIT < PREA_date) = true -> + exists c', + step NextCR c (STATE_IDLE_VEC,false,cnt,cref2Bv cref,tr) = (c',tr) /\ + (snd (snd c')) = tr. + Proof. + intros Href_service Href_prea; simpl in c; destruct_products; eapply ex_intro. + cbv [NextCR LoopInit]; cbn [step fst snd]; simpl_ident. + rewrite negb_false andb_true_l; rewrite /Srun //= VectorSpec.map_id. + rewrite CrefPREA_lt_CNT_REF_WAIT; done. + Qed. + + (* Lemma NextCR_equiv_IDLE_RUNNING c cnt (cref : Counter_ref_t) tr: + (cref2Bv cref =? CNT_REF_PREA) = false -> + (cref + WAIT < PREA_date) = true -> + exists c', step NextCR c (STATE_IDLE_VEC,false,cnt,cref2Bv cref,tr) = + (c',tr). + Proof. + intros Href_service Href_prea; simpl in c; destruct_products; eapply ex_intro. + cbv [NextCR LoopInit]; cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + rewrite negb_false andb_true_l; rewrite /Srun //= VectorSpec.map_id. + rewrite CrefPREA_lt_CNT_REF_WAIT; done. + Qed. *) + (* ------------------------------------------------------------------ *) + + Create HintDb update. + Lemma Sidle_true : + Sidle STATE_IDLE_VEC = true. + Proof. + apply CavaPreludeProperties.eqb_refl. + Qed. + Hint Rewrite @Sidle_true : update. + + Lemma Sref_idle_false : + Sref STATE_IDLE_VEC = false. + Proof. + by apply CavaPreludeProperties.eqb_neq. + Qed. + Hint Rewrite @Sref_idle_false : update. + + Lemma cnt_equiv (cnt : Bvector COUNTER_WIDTH) : + (if CeqWAIT cnt then Bvect_false COUNTER_WIDTH + else N2Bv_sized COUNTER_WIDTH (Bv2N cnt + 1)) = cnt2Bv (Next_cycle (Bv2cnt cnt)). + Proof. + cbv [CeqWAIT]. + destruct (CavaPrelude.eqb (cnt, CNT_WAIT)) eqn:Heq; rewrite Heq. + { specialize @CavaPreludeProperties.eqb_eq with (t := Vec Bit COUNTER_WIDTH) (x := cnt) as H. + apply H in Heq; clear H. + unfold Next_cycle; set (Hc := (Bv2cnt cnt).+1 < WAIT); dependent destruction Hc; + apply Logic.eq_sym in x; move : Logic.eq_refl; rewrite {2 3} x; simpl; intro. + { rewrite /CNT_WAIT bitvec_literal_correct in Heq. + rewrite Heq /Bv2cnt //= Bv2N_N2Bv_sized in x. + 2: { + rewrite /COUNTER_WIDTH; have id := (N2Nat.id 2). + rewrite -id Nat2N.inj_pow //= /Pos.to_nat //= WAIT_PW_2. + apply: N_lt_inj; apply /ltP; by rewrite subn1 ltn_predL WAIT_pos. + } + rewrite Nat2N.id subn1 prednK in x; [ | exact WAIT_pos ]; by rewrite ltnn in x. + } + { unfold cnt2Bv,OCycle0; by simpl. }} + { unfold Next_cycle; set (Hc := (Bv2cnt cnt).+1 < WAIT); dependent destruction Hc; + apply Logic.eq_sym in x; move : Logic.eq_refl; rewrite {2 3} x; simpl; intro. + { unfold cnt2Bv; apply f_equal; simpl. + rewrite N.add_1_r -(N.succ_pos_pred (Pos.of_succ_nat (N.to_nat (Bv2N cnt)))). + apply f_equal; by rewrite predN_of_succ_nat. } + { apply ltn_gt in e,x. + rewrite leq_eqVlt in e; move: e => /orP [/eqP e | e]. + { have HH := (@eqb_iff_neq (Vec Bit (@COUNTER_WIDTH SYS_CFG FIFO_CFG))). + apply HH in Heq. rewrite /CNT_WAIT bitvec_literal_correct in Heq; + rewrite -(N2Bv_sized_Bv2N (@COUNTER_WIDTH SYS_CFG FIFO_CFG) cnt) in Heq. + apply N2Bv_sized_neq_if in Heq. + by rewrite e subn1 -pred_Sn N2Nat.id in Heq. } + { specialize ltn_ord with (n := @WAIT SYS_CFG FIFO_CFG) (i := Ordinal (cnt_bounded cnt)) as H. + rewrite //= in H. + contradict H; apply /negP; by rewrite -ltnNge. + } + } + } + Qed. + + (* -------------- Proofs about Update ------------------------------- *) + Lemma Update_equiv_idle_idle (c : circuit_state Update) cnt cref : + (cref =? CNT_REF_PREA) = false -> + let nc := cnt2Bv (Next_cycle (Bv2cnt cnt)) in + let ncref := N2Bv_sized COUNTER_REF_WIDTH (Bv2N cref + 1) in + exists c', step Update c (STATE_IDLE_VEC,true,cnt,cref) = + (c',(STATE_IDLE_VEC,false,nc,ncref)). + Proof. + intros Hcref Hcnt; simpl in c; eapply ex_intro. + cbv [cnt2Bv]; unfold Hcnt; clear Hcnt. + cbv [Update Update_s Update_e Update_c Update_cref]. + cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + autorewrite with update; vm_compute (false && _). + apply BVEq_iff_neq in Hcref. + specialize @CavaPreludeProperties.eqb_neq with (t := Vec Bit (@COUNTER_REF_WIDTH SYS_CFG FIFO_CFG)) as HH. + apply pair_equal_spec; split. + 2: { + rewrite orb_false_l andb_true_l. + rewrite /CrefPREA_eq; apply HH in Hcref; by rewrite Hcref. + } + cbv [CrefPREA_eq]; apply HH in Hcref as Hcref'; rewrite Hcref'; + vm_compute (false || true && false); simpl; rewrite !VectorSpec.map_id andb_false_r. + apply pair_equal_spec; split; [ + apply pair_equal_spec; split; [ by unfold STATE_IDLE_VEC | reflexivity] | ]. + vm_compute (orb false false); rewrite orb_false_r; by specialize (cnt_equiv cnt). + Qed. + + Lemma Update_equiv_idle_ref (c : circuit_state Update) cnt cref e: + (cref =? CNT_REF_PREA) = true -> + let nc := cnt2Bv (Next_cycle (Bv2cnt cnt)) in + let ncref := CNT_REF_NIL in + exists c', (step Update c (STATE_IDLE_VEC,e,cnt,cref)) = + (c',(STATE_REF_VEC,false,nc,ncref)). + Proof. + intros Hcref Hcnt; simpl in c; eapply ex_intro. + cbv [cnt2Bv]; unfold Hcnt; clear Hcnt. + cbv [Update Update_s Update_e Update_c Update_cref]. + cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + autorewrite with update; vm_compute (false && _). + apply BVEq_iff_eq in Hcref. + specialize @CavaPreludeProperties.eqb_eq with (t := Vec Bit (@COUNTER_REF_WIDTH SYS_CFG FIFO_CFG)) as HH. + apply pair_equal_spec; split. + 2: { + rewrite orb_false_l andb_true_l. + rewrite /CrefPREA_eq; apply HH in Hcref; by rewrite Hcref. + } + cbv [CrefPREA_eq]; apply HH in Hcref as Hcref'; rewrite Hcref'; + vm_compute (false || true && false); simpl; rewrite !VectorSpec.map_id. + apply pair_equal_spec; split. + 2: { + vm_compute (orb false false); rewrite orb_false_r. + destruct e; [rewrite negb_true | rewrite negb_false]. + { rewrite andb_false_r orb_false_r; by specialize (cnt_equiv cnt). } + { rewrite andb_true_r. + destruct (CrefPREA_lt cref) eqn:Hbug. + { by rewrite Hcref CrefPREA_lt_CNT_REF_PREA in Hbug. } + { rewrite orb_false_r; by specialize (cnt_equiv cnt). } + } + } + apply pair_equal_spec; split; [ done | ]. + rewrite Hcref CrefPREA_lt_CNT_REF_PREA; by rewrite andb_false_l. + Qed. + + Lemma Update_equiv_idle_running (c : circuit_state Update) cnt + (cref : Counter_ref_t) : + (cref2Bv cref =? CNT_REF_PREA) = false -> + (cref + WAIT < PREA_date) = true -> + let nc := CNT_NIL in + let ncref := N2Bv_sized COUNTER_REF_WIDTH (Bv2N (cref2Bv cref) + 1) in + exists c', step Update c (STATE_IDLE_VEC,false,cnt,(cref2Bv cref)) = + (c',(STATE_RUN_VEC,true,nc,ncref)). + Proof. + intros Href_prea Href_service Hcnt; + simpl in c; destruct_products; eapply ex_intro. + cbv [cnt2Bv]; unfold Hcnt; clear Hcnt. + cbv [Update Update_s Update_e Update_c Update_cref]. + cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + autorewrite with update; fast_simpl_bool; + rewrite !orb_false_l !andb_true_l /CrefPREA_eq. + specialize @CavaPreludeProperties.eqb_neq with (t := Vec Bit (@COUNTER_REF_WIDTH SYS_CFG FIFO_CFG)) as HH. + apply BVEq_iff_neq in Href_prea as Haux; apply HH in Haux. + rewrite Haux //= !orb_false_r andb_true_r !VectorSpec.map_id; clear Haux. + apply pair_equal_spec; split; [ | done]. + apply pair_equal_spec; split; rewrite CrefPREA_lt_CNT_REF_WAIT; try done. + by rewrite orb_true_r. + Qed. + (* ------------------------------------------------------------------ *) + + (* -------------- Proofs about FullEmptyLogic ------------------------------- *) + Lemma FEL_emp_equiv (c : circuit_state FullEmptyLogic) wra rda : + wra = rda -> exists c', step FullEmptyLogic c (wra,rda) = (c',(false,true)). + Proof. + intros H; eapply ex_intro. + cbv [FullEmptyLogic FullLogic EmptyLogic Subtractor subtractor dropr EqFULL FullVEC unpackV]; + cbn [step]; simpl_ret; cbn [fst snd]. + apply pair_equal_spec; split; [ reflexivity | ]. + apply pair_equal_spec; split; [ | by rewrite H CavaPreludeProperties.eqb_refl ]. + rewrite inv_correct; cbv [bind]. + rewrite fullAdder_cin; cbv [unpackV]; simpl_ret. + destruct (one) eqn:Hone; [ | discriminate]. + destruct ((Bv2N rda) <= (Bv2N wra)) eqn:Hleq; + [ | by rewrite H leqnn in Hleq ]. + assert (N.sub (Bv2N wra) (Bv2N rda) = 0%N); [ by rewrite H N.sub_diag | ]. + rewrite H0 !bitvec_literal_correct. + set (N := N.sub _ _). + specialize N2Bv_sized_queuemax_neq0 as H2. + specialize @CavaPreludeProperties.eqb_neq with (t := Vec Bit (@ADDR_WIDTH CAVA_SYS)) + (x := N2Bv_sized ADDR_WIDTH 0) (y := N2Bv_sized ADDR_WIDTH N) as HH. + by apply HH in H2. + Qed. + + Lemma FEL_nemp_wrap1_equiv (c : circuit_state FullEmptyLogic) (wra rda : Bvector ADDR_WIDTH) : + let wrap1 := N2Bv_sized ADDR_WIDTH (Bv2N wra + 1) in + wra = rda -> exists c' f', step FullEmptyLogic c (wrap1,rda) = (c',(f',false)). + Proof. + intros; repeat eapply ex_intro; unfold wrap1. + cbv [FullEmptyLogic FullLogic EmptyLogic Subtractor subtractor dropr EqFULL FullVEC unpackV]; + cbn [step]; simpl_ret; cbn [fst snd]. + apply pair_equal_spec; split; [ reflexivity | ]. + apply pair_equal_spec; split; [ reflexivity | ]. + apply CavaPreludeProperties.eqb_neq; rewrite H. + apply N2Bv_sized_plusone_diff; unfold ADDR_WIDTH. + specialize QUEUE_MAX_SIZE_GT_1 as HQ; apply Nat.log2_pos in HQ. + by move: HQ => /ltP HQ. + Qed. + + Lemma FEL_nemp_NF_equiv (c : circuit_state FullEmptyLogic) (wra rda : Bvector ADDR_WIDTH) : + ~~ (fullQueue wra rda) -> + wra <> rda -> exists c', step FullEmptyLogic c (wra,rda) = (c',(false,false)). + Proof. + intros NF H; eapply ex_intro. + rewrite /fullQueue in NF. + cbv [FullEmptyLogic FullLogic EmptyLogic Subtractor subtractor dropr EqFULL FullVEC unpackV]; + cbn [step]; simpl_ret; cbn [fst snd]. + apply pair_equal_spec; split; [ reflexivity | ]. + apply pair_equal_spec; split; [ | by apply CavaPreludeProperties.eqb_neq ]. + rewrite bitvec_literal_correct. + rewrite fullAdder_cin; destruct (one) eqn:Hbug; try discriminate; clear Hbug. + cbv [unpackV]. + destruct (_ <= _) eqn:Hleq; apply CavaPreludeProperties.eqb_neq. + { set (xx := (Bv2N wra - Bv2N rda)%N); fold xx in NF. + set (yy := ((N.of_nat QUEUE_MAX_SIZE - 1)%N)); fold yy in NF. + assert (N.size_nat xx <= ADDR_WIDTH); + [ apply size_nat_sub_leq; by apply leq_Nle in Hleq | ]. + assert (N.size_nat yy <= ADDR_WIDTH); + [ unfold ADDR_WIDTH, yy; by apply size_nat_qms | ]. + apply N2Bv_sized_neq_iff; try done; by apply /eqP. + } + { rewrite {3}/ADDR_WIDTH QUEUE_MAX_SIZE_PW2; apply N2Bv_sized_neq_iff. + { assert (Bv2N rda > Bv2N wra); [ lia | ]. + apply size_nat_qms_sub; by apply ltn_Ntn in H0. + } + { unfold ADDR_WIDTH; by apply size_nat_qms. } + specialize add_1_sub1 with (x := N.of_nat (@QUEUE_MAX_SIZE CAVA_SYS)) as HH. + rewrite HH in NF; [ | exact QUEUE_MAX_SIZE_GT_0_N]. + apply /eqP; exact NF. + } + Qed. + + Lemma FEL_NF_equiv (c : circuit_state FullEmptyLogic) (wra rda : Bvector ADDR_WIDTH) : + ~~ (fullQueue wra rda) -> + exists c' e', step FullEmptyLogic c (wra,rda) = (c',(false,e')). + Proof. + intros NF; unfold fullQueue in NF; repeat eapply ex_intro. + cbv [FullEmptyLogic]; cbn [step]; simpl_ret; cbn [fst snd]. + apply pair_equal_spec; split; [reflexivity | ]. + apply pair_equal_spec; split; [ | reflexivity ]. + cbv [dropr subtractor EqFULL FullVEC unpackV]; simpl_ident. + destruct ((Bv2N rda) <= (Bv2N wra)) eqn:Hleq; + destruct (one) eqn:Hone; try discriminate; + rewrite fullAdder_cin Hleq; + apply CavaPreludeProperties.eqb_neq; move: NF => /eqP NF. + { set (xx := (Bv2N wra - Bv2N rda)%N); fold xx in NF. + set (yy := ((N.of_nat QUEUE_MAX_SIZE - 1)%N)); fold yy in NF. + assert (N.size_nat xx <= ADDR_WIDTH); + [ apply size_nat_sub_leq; by apply leq_Nle in Hleq | ]. + assert (N.size_nat yy <= ADDR_WIDTH); + [ unfold ADDR_WIDTH, yy; by apply size_nat_qms | ]. + apply N2Bv_sized_neq_iff; try done; by apply /eqP. + } + { rewrite {3}/ADDR_WIDTH QUEUE_MAX_SIZE_PW2; apply N2Bv_sized_neq_iff. + { assert (Bv2N rda > Bv2N wra) as H; [ lia | ]. + apply size_nat_qms_sub; by apply ltn_Ntn in H. + } + { unfold ADDR_WIDTH; by apply size_nat_qms. } + specialize add_1_sub1 with (x := N.of_nat (@QUEUE_MAX_SIZE CAVA_SYS)) as HH. + by rewrite HH in NF; [ | exact QUEUE_MAX_SIZE_GT_0_N]. + } + Qed. + (* ------------------------------------------------------------------ *) + + Lemma incrn_pointr_true_equiv (c : circuit_state incr_pointr) ad : + step incr_pointr c (ad,true) = + (tt,N2Bv_sized ADDR_WIDTH (Bv2N ad + 1)). + Proof. + cbv [incr_pointr step] ; by simpl_ident. + Qed. + + Lemma incrn_pointr_false_equiv (c : circuit_state incr_pointr) ad : + step incr_pointr c (ad,false) = (tt,ad). + Proof. + cbv [incr_pointr step] ; by simpl_ident. + Qed. + + Create HintDb get_state. + Hint Unfold get_st get_cnt get_cref get_reqqueue get_addr_RequestQueue get_pop get_mem + get_memcells_RequestQueue get_mem_RequestQueue get_memcells get_cr : get_state. + + (* the not full could come either be satisfies from the not full hypothesis + or from wra = rda *) + Lemma RQ_fst_pushT_popF_NF (c : circuit_state RequestQueue') c_req : + let '(wra,rda) := get_addr_RequestQueue c in + let S := get_memcells_RequestQueue c in + let wra_idx := N.to_nat (Bv2N wra) in + let memcells_spec := Cells_read true wra_idx c_req S in + ~~ (fullQueue wra rda) -> exists c', + ((Cells_data (get_memcells_RequestQueue c') = memcells_spec) /\ + (fst (get_addr_RequestQueue c')) = (N2Bv_sized ADDR_WIDTH (Bv2N wra + 1)) /\ + (snd (get_addr_RequestQueue c')) = rda) /\ + fst (step RequestQueue' c (true,c_req,false)) = c'. + Admitted. + (* Proof. + simpl in c; destruct_products. + unfold get_addr_RequestQueue; intros Hfull; eapply ex_intro; split; [ | reflexivity]. + set (p := step RequestQueue' _ _). + cbv [RequestQueue' LoopInit fork2] in p. + cbn [step] in p; cbn [fst snd] in p; simpl_ret_H p; cbv [fst snd] in p. + specialize FEL_NF_equiv with (c := (u17, (u19, u20, u18), u16)) + (rda := t0) (wra := t) as H; apply H in Hfull; clear H. + destruct Hfull as [cs_FEL' [empty_o Hfull]]. + unfold p; clear p; rewrite Hfull. + cbn [fst snd bind inv and2 or2]; fast_simpl_bool. + rewrite (surjective_pairing (step memqueue' _ _)). + rewrite incrn_pointr_true_equiv incrn_pointr_false_equiv. + rewrite (surjective_pairing (step FullEmptyLogic _ _)). + set (fel := step FullEmptyLogic _ _). + split. + { simpl in fel; unfold fel; cbv [snd fst]. + cbv [get_memcells_RequestQueue get_mem_RequestQueue get_memcells]. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end. + cbv [memqueue' Memory' mem_write mem_read]; cbn [step fst snd]; simpl_ident; cbv [fst snd]. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end. + cbv [fst snd]. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end. + fold mem_cells_. + specialize @Cells_matchX with (T := Vec Bit (@REQUEST_WIDTH CAVA_SYS)) + (W := @ADDR_WIDTH CAVA_SYS) (N := (Nat.pow 2 (@ADDR_WIDTH CAVA_SYS))) (I := InitMem) + (S0 := c) (we := true) (wd := c_req) (wa := (N.to_nat (Bv2N t))) as HH. + rewrite -HH; [reflexivity | | ]. + { intros. + rewrite /indexConst; simpl_ident. + rewrite /decode; simpl_ident. + admit. + } + { rewrite /indexConst; simpl_ident. + rewrite /decode; simpl_ident. + admit. + } + } + split; by simpl. + Admitted. *) + + (* Ignoring the full signal because it just goes to the output *) + Lemma RQ_snd_pushT_empty (c : circuit_state RequestQueue') c_req pop : + let '(wra,rda) := get_addr_RequestQueue c in + let S := get_memcells_RequestQueue c in + let rda_idx := N.to_nat (Bv2N rda) in + let wra_idx := N.to_nat (Bv2N wra) in + let memcells' := Cells_read true wra_idx c_req S in + let mem_val := nth_default (req_null) rda_idx memcells' in + wra = rda -> exists f', + snd (step RequestQueue' c (true,c_req,pop)) = (f',mem_val,true). + Admitted. + (* simpl in c; destruct_products; rename t0 into rda, t into wra. + autounfold with get_state; intros. + cbv [RequestQueue' LoopInit fork2]; simpl_ret; cbn [step fst snd]. + eapply FEL_emp_equiv with (c := (u17,(u19,u20,u18), u16)) in H as HH. + destruct HH as [cs_FEL HH]; rewrite HH. + cbn [fst snd bind inv and2 or2]. + rewrite (surjective_pairing (step memqueue' (u12,c,u11) _)). + cbv [fst snd]; fast_simpl_bool. + rewrite incrn_pointr_true_equiv if_same incrn_pointr_false_equiv; clear HH. + eapply FEL_nemp_wrap1_equiv with (c := (u4, (u6, u7, u5), u3)) in H as HH. + destruct HH as [cs_FELL [full_o HH]]; rewrite HH; clear HH. + eapply ex_intro. + apply pair_equal_spec; split; [ | reflexivity ]. + apply pair_equal_spec; split; [ reflexivity | ]. + cbv [memqueue' Memory' mem_write mem_read]. + cbn [step fst snd]; simpl_ret. + rewrite (surjective_pairing (step (mem_cells _ _ _ _) c _)). + specialize @Cells_data_match with (T := Vec Bit (@REQUEST_WIDTH CAVA_SYS)) + (W := @ADDR_WIDTH CAVA_SYS) (N := (Nat.pow 2 (@ADDR_WIDTH CAVA_SYS))) (I := InitMem) + (S0 := c) (we := true) (wa := (N.to_nat (Bv2N wra))) (wd := c_req) as HH. + rewrite -HH. + { cbv [indexAt indexConst defaultCombValue]. + cbv [unpackV bind]; simpl_ret. + rewrite nth_0; simpl; unfold req_null. + reflexivity. + } + all: admit. + Admitted. *) + + Lemma RQ_snd_pushT_popF_NF_nempty (c : circuit_state RequestQueue') c_req: + let '(wra,rda) := get_addr_RequestQueue c in + let S := get_memcells_RequestQueue c in + let rda_idx := N.to_nat (Bv2N rda) in + let wra_idx := N.to_nat (Bv2N wra) in + let memcells' := Cells_read true wra_idx c_req S in + let mem_val := nth_default (req_null) rda_idx memcells' in + ~~ (fullQueue wra rda) -> wra <> rda -> exists full_o, + snd (step RequestQueue' c (true,c_req,false)) = (full_o,mem_val,false). + Admitted. + (* + simpl in c; destruct_products; rename t0 into rda, t into wra. + autounfold with get_state; intros. + cbv [RequestQueue' LoopInit fork2]; simpl_ret; cbn [step fst snd]. + apply FEL_nemp_NF_equiv with (c := (u17,(u19,u20,u18), u16)) in H as HH; [ | done]. + destruct HH as [cs_FEL HH]; rewrite HH. + cbn [fst snd bind inv and2 or2]; fast_simpl_bool. + rewrite (surjective_pairing (step memqueue' (u12,c,u11) _)). + cbv [fst snd]; fast_simpl_bool. + rewrite incrn_pointr_true_equiv. + rewrite incrn_pointr_false_equiv; clear HH. + (* The second logic doesn't really matter much *) + rewrite (surjective_pairing (step FullEmptyLogic _ _)). + eapply ex_intro. + apply pair_equal_spec; split; [ | reflexivity]. + apply pair_equal_spec; split; [ reflexivity | ]. + destruct_pair_let. + cbv [memqueue' Memory' mem_write mem_read]. + cbn [step fst snd]; simpl_ret. + rewrite (surjective_pairing (step (mem_cells _ _ _ _) c _)). + specialize @Cells_data_match with (T := Vec Bit (@REQUEST_WIDTH CAVA_SYS)) + (W := @ADDR_WIDTH CAVA_SYS) (N := (Nat.pow 2 (@ADDR_WIDTH CAVA_SYS))) (I := InitMem) + (S0 := c) (we := true) (wa := (N.to_nat (Bv2N wra))) (wd := c_req) as HH. + rewrite -HH //=. + all: admit. + Admitted. *) + + (* IDLE -> RUNNING *) + Theorem SM_Eq_2b (t : nat) (c_state : State_t) c0 r0 r1 + (c1 : Counter_ref_t) (c_req : Bvector REQUEST_WIDTH) r : + (c1 + WAIT < PREA_date) = true -> + (nat_of_ord c1 == PREA_date - 1) = false -> + let f_state := (HW_Default_arbitrate t).(Implementation_State) in + let R := HW_Arrival_at t in + R == [:: r] -> EqReq r c_req -> State_Eq (IDLE c0 c1 (r0 :: r1)) c_state -> + let '(f_nextstate,(f_cmd_o,f_req_o)) := Next_state R (IDLE c0 c1 (r0 :: r1)) in + let '(c_nextstate,(_,c_cmd_o,c_req_o)) := step FIFOSM c_state (true,c_req) in + (State_Eq f_nextstate c_nextstate) && + (EqCmd f_cmd_o c_cmd_o) && (EqReq f_req_o c_req_o). + Proof. + intros Href_service Href_prea f_state R NF EqR H; unfold FIFOSM. + unfold R in NF; specialize (HaltIfFull t c_state) as NFULL; move: NF => /eqP NF. + unfold State_t in c_state; simpl in c_state; destruct_products. + rewrite NF //= in NFULL. + rename t0 into s, t1 into cnt, t2 into cref, t3 into cr, t4 into wra, t5 into rda, b into pop. + rewrite /State_Eq /EqMem in H; autounfold with get_state in H; cbn [fst snd] in H. + move: H => /andP [/andP [/andP [/andP [/andP [EqS EqCnt] EqCref] Mem] HQ] /eqP EqPop]. + apply EqQueue_diff_adr in HQ as Hadr. + + apply BVEq_iff_eq in EqS, EqCnt, EqCref; subst s cnt cref pop. + cbv [LoopInit]; cbn [step fst snd]; simpl_ret. + + rewrite (surjective_pairing (step RequestQueue' _ _)). + specialize (RQ_snd_pushT_popF_NF_nempty ((u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21), (u14, (u16, (u18, u19, u17), u15)),u13, rda), wra))) c_req) as S. + cbv [get_addr_RequestQueue get_memcells_RequestQueue get_mem_RequestQueue get_memcells] in S. + apply S in NFULL as S'; [ | done]; clear S; destruct S' as [full_o H]. + rewrite H. clear H; cbn [fst snd]. + + set tr := nth_default req_null (N.to_nat (Bv2N rda)) _. + apply NextCR_equiv_IDLE_RUNNING with (c := (u9, (u10, cr))) (cnt := cnt2Bv c0) + (cref := c1) (tr := tr) in Href_service as H. + 2: by apply cref_preadate_false in Href_prea. + destruct H as [cs_nextcr H]; destruct H as [H Htr]. + rewrite H; clear H; cbv [fst snd]. + + specialize (CmdGen_equiv_idle_to_running u6 (cnt2Bv c0) c1 tr) as S. + specialize Href_service as Href_service_. + apply S in Href_service; clear S; rename Href_service into H. + 2: by apply cref_preadate_false in Href_prea. + destruct H as [cs_CmdGen H]; rewrite H; clear H; cbn [snd]. + + specialize (Update_equiv_idle_running u4 (cnt2Bv c0) c1) as S; + apply S in Href_service_ as S'; clear S. + 2: by apply cref_preadate_false in Href_prea. + destruct S' as [cs_update H]; rewrite H; clear H; cbn [fst snd]. + + rewrite /Next_state Href_prea Href_service_ /State_Eq. + specialize RQ_fst_pushT_popF_NF with (c := (u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21),(u14, (u16, (u18, u19, u17), u15)), u13, rda), wra))) (c_req := c_req) as S. + apply S in NFULL as H; clear S. + destruct H as [cs_requeue' [Hx H]]; destruct Hx as [Hrw [Hwra' Hrda']]. + autounfold with get_state. + + apply /andP; split. + 2: { + unfold tr; simpl in Mem; move: Mem => /andP [EqReq_r0 Mem]. + rewrite {2}/get_memcells_RequestQueue /get_mem_RequestQueue /get_memcells in Hrw. + apply (memcell_nch c wra rda c_req req_null) in Hadr as HH. + rewrite /req_null //= in HH. + rewrite VectorSpec.map_id /Bvect_false HH in EqReq_r0. + by rewrite /req_null //=. + } + apply /andP; split. + 2 : unfold EqCmd; by apply BVEq_iff_eq. + apply /andP; split. + 2: { + rewrite (surjective_pairing (step RequestQueue' _ _)); cbv [get_pop]; + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; simpl; trivial. } + apply /andP; split. + 2 : { + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; rewrite Htr; + unfold tr; simpl in Mem; move: Mem => /andP [EqReq_r0 Mem]. + rewrite {2}/get_memcells_RequestQueue /get_mem_RequestQueue /get_memcells in Hrw. + apply (memcell_nch c wra rda c_req req_null) in Hadr as HH. + rewrite /req_null //= in HH. + rewrite VectorSpec.map_id /Bvect_false HH in EqReq_r0. + by rewrite /req_null //=. + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H Hwra' Hrda'. + simpl; rewrite eq_refl. + rewrite /Enqueue /R NF. + simpl in HQ. + (* specialize (EqQueue_aux wra rda r0 r1 r) as HH; apply HH; done. *) + specialize (EqQueue_aux wra rda r0 r1 r) as HH. + apply HH in NFULL as HH'; clear HH; try done. + (* move: HH' => /andP [neqq HH]; fold @EqQueue in HH. *) + move: HH'; simpl; intros HH. + move: HH => /andP [Hadr_neq HH]. + rewrite /EqQueue in HH'. + + simpl; rewrite Hadr; unfold R; rewrite NF //=. + + } + + 2 : { + rewrite /Enqueue (surjective_pairing (step RequestQueue' _ _)) H. + autounfold with get_state in Hrda',Hwra'; cbn [fst snd]; rewrite Hwra' Hrda'; clear Hwra' Hrda'. + unfold R; rewrite NF. + specialize (EqQueue_aux wra rda r0 r1 r) as HH; apply HH; done. + } + + + + + + + + + Theorem SM_Eq_2a (t : nat) (c_state : State_t) c0 + (c1 : Counter_ref_t) (c_req : Bvector REQUEST_WIDTH) r : + (c1 + WAIT < PREA_date) = true -> + (nat_of_ord c1 == PREA_date - 1) = false -> + let f_state := (HW_Default_arbitrate t).(Implementation_State) in + let R := HW_Arrival_at t in + R == [:: r] -> EqReq r c_req -> State_Eq (IDLE c0 c1 []) c_state -> + let '(f_nextstate,(f_cmd_o,f_req_o)) := Next_state R (IDLE c0 c1 []) in + let '(c_nextstate,(_,c_cmd_o,c_req_o)) := step FIFOSM c_state (true,c_req) in + (State_Eq f_nextstate c_nextstate) && + (EqCmd f_cmd_o c_cmd_o) && (EqReq f_req_o c_req_o). + Proof. + intros Href_service Href_prea f_state R NF EqR H; unfold FIFOSM. + unfold R in NF; specialize (HaltIfFull t c_state) as NFULL; move: NF => /eqP NF. + unfold State_t in c_state; simpl in c_state; destruct_products. + rewrite NF //= in NFULL. + rename t0 into s, t1 into cnt, t2 into cref, t3 into cr, t4 into wra, t5 into rda, b into pop. + rewrite /State_Eq /EqMem in H; autounfold with get_state in H; cbn [fst snd] in H. + move: H => /andP [/andP [/andP [/andP [/andP [EqS EqCnt] EqCref] Mem] Hadr] /eqP EqPop]. + simpl in Hadr. + + apply BVEq_iff_eq in EqS, EqCnt, EqCref, Hadr; subst s cnt cref pop. + cbv [LoopInit]; cbn [step fst snd]; simpl_ret. + + rewrite (surjective_pairing (step RequestQueue' _ _)). + specialize (RQ_snd_pushT_empty ((u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21), (u14, (u16, (u18, u19, u17), u15)),u13, rda), wra))) c_req false) as S. + cbv [get_addr_RequestQueue get_memcells_RequestQueue get_mem_RequestQueue get_memcells] in S. + apply S in Hadr as H; clear S; destruct H as [full_o H]. + rewrite H; clear H; cbn [fst snd]. + + set tr := nth_default req_null (N.to_nat (Bv2N rda)) _. + specialize NextCR_equiv with (c := (u9, (u10, cr))) (cnt := cnt2Bv c0) + (cref := cref2Bv c1) (tr := tr) as [cs_nextcr H]. + rewrite H; cbv [fst]; clear H. cbn [snd]. + + apply cref_preadate_false in Href_prea as Href_prea_. + apply (CmdGen_equiv_idle_to_idle u6 (cnt2Bv c0) (cref2Bv c1)) in Href_prea_ as H. + destruct H as [cs_CmdGen H]; rewrite H; clear H; cbn [snd]. + + apply (Update_equiv_idle_idle u4 (cnt2Bv c0) (cref2Bv c1)) in Href_prea_ as H. + destruct H as [cs_update H]; rewrite H; clear H; cbn [fst snd]. + + rewrite /Next_state Href_prea /State_Eq. + specialize RQ_fst_pushT_popF_NF with (c := (u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21),(u14, (u16, (u18, u19, u17), u15)), u13, rda), wra))) (c_req := c_req) as S. + apply S in NFULL as H; clear S. + destruct H as [cs_requeue' [Hx H]]; destruct Hx as [Hrw [Hwra' Hrda']]. + autounfold with get_state. + rewrite Href_service. + + apply /andP; split. + 2 : exact EqReqNil. + apply /andP; split. + 2 : unfold EqCmd; by apply BVEq_iff_eq. + apply /andP; split. + 2: { + rewrite (surjective_pairing (step RequestQueue' _ _)); cbv [get_pop]; + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; simpl; trivial. } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H Hwra' Hrda'. + simpl; rewrite Hadr; unfold R; rewrite NF //=. + apply /andP; split. + { apply /negPf; apply (@N2Bv_sized_eq_p1_false ADDR_WIDTH rda); + specialize ADDR_WIDTH_pos as Hpos; by move: Hpos => /ltP Hpos. } + by apply BVEq_iff_eq. + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H Hrda'. + simpl; unfold R; rewrite NF //= /EqMem //= andb_true_r. + rewrite Hrw; autounfold with get_state; rewrite Hadr. + specialize (@nth_cells_read (Vec Bit REQUEST_WIDTH) ADDR_WIDTH InitMem rda c_req c) as H'. + rewrite H'; exact EqR. + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H //=. + destruct_pair_let. + rewrite /Next_cycle_ref. + set Hc := c1.+1 < WAIT_REF; dependent destruction Hc; + apply Logic.eq_sym in x; move : Logic.eq_refl; rewrite {2 3} x; simpl; intro. + { rewrite /cref2Bv //= Bv2N_N2Bv_sized. + 2: { + unfold COUNTER_REF_WIDTH; rewrite WAIT_REF_PW_N. + destruct c1; simpl; apply N_lt_inj; by apply /ltP. + } + rewrite /N2Bv_sized. + destruct (N.of_nat c1 + 1)%N eqn:Hbug; + [ rewrite N.add_1_r in Hbug; contradict Hbug; apply N.neq_succ_0 | ]. + apply BVEq_iff_eq; f_equal; lia. + } + { destruct c1; simpl in x,e,Hc0,Href_prea_,Href_service,Href_prea. + rewrite /cref2Bv VectorSpec.map_id //= in Href_prea_. + apply ltn_gt in x; rewrite leq_eqVlt in x; move: x => /orP [/eqP x | x]. + { assert (m = WAIT_REF.-1); [ lia | ]. + rewrite H0 addnC -ltn_subRL in Href_service. + rewrite -subn1 ltn_subLR in Href_service; [ | exact WAIT_REF_pos ]. + contradict Href_service; apply /negP. + rewrite -leqNgt leq_eqVlt addnC. + specialize WAIT_REF_PREA_date as HH. + apply ltn_trans with (m := PREA_date - WAIT + 1) in HH; + [ by rewrite HH orb_true_r | ]. + rewrite -subnA. + { by rewrite ltn_subrL subn_gt0 WAIT_gt_one PREA_date_pos. } + { exact WAIT_pos. } + { by rewrite leq_eqVlt PREA_date_WAIT orb_true_r. } + } + { rewrite ltnS in x; contradict x; apply /negP; by rewrite -ltnNge. } + } + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H //=. + destruct_pair_let. + rewrite /cnt2Bv; apply BVEq_iff_eq; f_equal. + apply Nat2N.inj_iff. + rewrite /Bv2cnt /Next_cycle //= Bv2N_N2Bv_sized //=. + 2: { + destruct c0; rewrite //= /COUNTER_WIDTH. + rewrite WAIT_PW_2_N; apply N_lt_inj; by apply /ltP. + } + set (Hc := _ < WAIT); dependent destruction Hc; + apply Logic.eq_sym in x; move : Logic.eq_refl; rewrite {2 3} x; simpl; intro; try rewrite Nat2N.id; + try by rewrite Nat2N.id in x; move: Logic.eq_refl; rewrite {2 3}x; simpl; intro. + } + cbv [get_st]; rewrite (surjective_pairing (step RequestQueue' _ _)) H //=; destruct_pair_let. + by []. + Qed. + + + (* Assuming a non-full regime, i.e., the front-end has yielded a valid request *) + (* If R is non empty than the queue is not full *) + Theorem SM_Eq_1b (t : nat) (c_state : State_t) c0 c1 (c_req : Bvector REQUEST_WIDTH) r0 r1 (r : Request_t) : + (nat_of_ord c1 == PREA_date - 1) = true -> + let f_state := (HW_Default_arbitrate t).(Implementation_State) in + let R := HW_Arrival_at t in + R == [:: r] -> EqReq r c_req -> State_Eq (IDLE c0 c1 (r0 :: r1)) c_state -> + let '(f_nextstate,(f_cmd_o,f_req_o)) := Next_state R (IDLE c0 c1 (r0 :: r1)) in + let '(c_nextstate,(_,c_cmd_o,c_req_o)) := step FIFOSM c_state (true,c_req) in + (State_Eq f_nextstate c_nextstate) && + (EqCmd f_cmd_o c_cmd_o) && (EqReq f_req_o c_req_o). + Admitted. + (* Proof. + intros Href_prea f_state R NF EqR H; unfold FIFOSM. + unfold R in NF; specialize (HaltIfFull t c_state) as NFULL; move: NF => /eqP NF. + unfold State_t in c_state; simpl in c_state; destruct_products. + rewrite NF //= in NFULL. + rename t0 into s, t1 into cnt, t2 into cref, t3 into cr, t4 into wra, t5 into rda, b into pop. + rewrite /State_Eq /EqMem in H; autounfold with get_state in H; cbn [fst snd] in H. + move: H => /andP [/andP [/andP [/andP [/andP [EqS EqCnt] EqCref] Mem] HQ] /eqP EqPop]. + apply EqQueue_diff_adr in HQ as Hadr. + + apply BVEq_iff_eq in EqS, EqCnt, EqCref; subst s cnt cref pop. + cbv [LoopInit]; cbn [step fst snd]; simpl_ret. + + rewrite (surjective_pairing (step RequestQueue' _ _)). + specialize (RQ_snd_pushT_popF_NF_nempty ((u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21), (u14, (u16, (u18, u19, u17), u15)),u13, rda), wra))) c_req) as S. + cbv [get_addr_RequestQueue get_memcells_RequestQueue get_mem_RequestQueue get_memcells] in S. + apply S in NFULL as S'; [ | done]; clear S; destruct S' as [full_o H]. + rewrite H. clear H; cbn [fst snd]. + + set tr := nth_default req_null (N.to_nat (Bv2N rda)) _. + specialize (NextCR_equiv_IDLE_NE_PREA (u9, (u10, cr)) (cnt2Bv c0) (cref2Bv c1) tr) as S. + apply cref_preadate_true in Href_prea as Href_prea_. + apply S in Href_prea_ as S'; clear S; destruct S' as [cs_nextcr H]; rewrite H. + + cbn [fst snd]; clear H. + apply (CmdGen_equiv_idle_to_ref u6 (cnt2Bv c0) (cref2Bv c1) false) in Href_prea_ as H. + destruct H as [cs_CmdGen H]; rewrite H; clear H; cbn [snd]. + + apply (Update_equiv_idle_ref u4 (cnt2Bv c0) (cref2Bv c1) false) in Href_prea_ as H. + destruct H as [cs_update H]; rewrite H; clear H; cbn [fst snd]. + + rewrite /Next_state Href_prea /State_Eq. + specialize RQ_fst_pushT_popF_NF with (c := (u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21),(u14, (u16, (u18, u19, u17), u15)), u13, rda), wra))) (c_req := c_req) as S. + apply S in NFULL as H; clear S. + destruct H as [cs_requeue' [Hx H]]; destruct Hx as [Hrw [Hwra' Hrda']]. + autounfold with get_state. + + apply /andP; split. + 2 : exact EqReqNil. + apply /andP; split. + 2 : unfold EqCmd; by apply BVEq_iff_eq. + apply /andP; split. + 2: { + rewrite (surjective_pairing (step RequestQueue' _ _)); cbv [get_pop]; + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; simpl; trivial. } + apply /andP; split. + 2 : { + rewrite /Enqueue (surjective_pairing (step RequestQueue' _ _)) H. + autounfold with get_state in Hrda',Hwra'; cbn [fst snd]; rewrite Hwra' Hrda'; clear Hwra' Hrda'. + unfold R; rewrite NF. + specialize (EqQueue_aux wra rda r0 r1 r) as HH; apply HH; done. + } + apply /andP; split. + 2 : { + rewrite /EqMem (surjective_pairing (step RequestQueue' _ _)) H Hrw /Enqueue. + autounfold with get_state in Hrda'; cbn [fst snd]; rewrite Hrda'; clear Hrda'. + autounfold with get_state; unfold R; rewrite NF. + apply EqMem_rcons; done. + } + apply /andP; split. + 2 : { + cbv [get_cref]. + rewrite (surjective_pairing (step RequestQueue' _ _)) H //= VectorSpec.map_id. + destruct_pair_let. + rewrite /cref2Bv /OCycle0REF //=; by apply BVEq_iff_eq. + } + cbv [get_st]; rewrite (surjective_pairing (step RequestQueue' _ _)) H //=; destruct_pair_let. + by []. + Qed. *) + + Theorem SM_Eq_1a (t : nat) (c_state : State_t) c0 c1 (c_req : Bvector REQUEST_WIDTH) r : + (nat_of_ord c1 == PREA_date - 1) = true -> + let f_state := (HW_Default_arbitrate t).(Implementation_State) in + let R := HW_Arrival_at t in + R == [:: r] -> EqReq r c_req -> State_Eq (IDLE c0 c1 []) c_state -> + let '(f_nextstate,(f_cmd_o,f_req_o)) := Next_state R (IDLE c0 c1 []) in + let '(c_nextstate,(_,c_cmd_o,c_req_o)) := step FIFOSM c_state (true,c_req) in + (State_Eq f_nextstate c_nextstate) && + (EqCmd f_cmd_o c_cmd_o) && (EqReq f_req_o c_req_o). + Admitted. + (* Proof. + intros Href_prea f_state R NF EqR H; unfold FIFOSM. + unfold R in NF; specialize (HaltIfFull t c_state) as NFULL; move: NF => /eqP NF. + unfold State_t in c_state; simpl in c_state; destruct_products. + rewrite NF //= in NFULL. + rename t0 into s, t1 into cnt, t2 into cref, t3 into cr, t4 into wra, t5 into rda, b into pop. + rewrite /State_Eq /EqMem in H; autounfold with get_state in H; cbn [fst snd] in H. + move: H => /andP [/andP [/andP [/andP [/andP [EqS EqCnt] EqCref] Mem] Hadr] /eqP EqPop]. + simpl in Hadr. + + apply BVEq_iff_eq in EqS, EqCnt, EqCref, Hadr; subst s cnt cref pop. + cbv [LoopInit]; cbn [step fst snd]; simpl_ret. + + rewrite (surjective_pairing (step RequestQueue' _ _)). + specialize (RQ_snd_pushT_empty ((u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21), (u14, (u16, (u18, u19, u17), u15)),u13, rda), wra))) c_req false) as S. + cbv [get_addr_RequestQueue get_memcells_RequestQueue get_mem_RequestQueue get_memcells] in S. + apply S in Hadr as H; clear S; destruct H as [full_o H]. + rewrite H; clear H; cbn [fst snd]. + + set tr := nth_default req_null (N.to_nat (Bv2N rda)) _. + specialize NextCR_equiv with (c := (u9, (u10, cr))) (cnt := cnt2Bv c0) + (cref := cref2Bv c1) (tr := tr) as [cs_nextcr H]. + rewrite H; cbv [fst]; clear H. + + apply cref_preadate_true in Href_prea as Href_prea_; cbn [fst snd]. + apply (CmdGen_equiv_idle_to_ref u6 (cnt2Bv c0) (cref2Bv c1) true) in Href_prea_ as H. + destruct H as [cs_CmdGen H]; rewrite H; clear H; cbn [snd]. + + apply (Update_equiv_idle_ref u4 (cnt2Bv c0) (cref2Bv c1) true) in Href_prea_ as H. + destruct H as [cs_update H]; rewrite H; clear H. + + rewrite /Next_state Href_prea /State_Eq. + specialize RQ_fst_pushT_popF_NF with (c := (u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21),(u14, (u16, (u18, u19, u17), u15)), u13, rda), wra))) (c_req := c_req) as S. + apply S in NFULL as H; clear S. + destruct H as [cs_requeue' [Hx H]]; destruct Hx as [Hrw [Hwra' Hrda']]. + autounfold with get_state. + + apply /andP; split. + 2 : exact EqReqNil. + apply /andP; split. + 2 : unfold EqCmd; by apply BVEq_iff_eq. + apply /andP; split. + 2: { + rewrite (surjective_pairing (step RequestQueue' _ _)); cbv [get_pop]; + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; simpl; trivial. } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H Hwra' Hrda'. + simpl; rewrite Hadr; unfold R; rewrite NF //=. + apply /andP; split. + { apply /negPf; apply (@N2Bv_sized_eq_p1_false ADDR_WIDTH rda); + specialize ADDR_WIDTH_pos as Hpos; by move: Hpos => /ltP Hpos. } + by apply BVEq_iff_eq. + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H Hrda'. + simpl; unfold R; rewrite NF //= /EqMem //= andb_true_r. + rewrite Hrw; autounfold with get_state; rewrite Hadr. + specialize (@nth_cells_read (Vec Bit REQUEST_WIDTH) ADDR_WIDTH InitMem rda c_req c) as H'. + rewrite H'; exact EqR. + } + apply /andP; split. + 2 : { + cbv [get_cref]. + rewrite (surjective_pairing (step RequestQueue' _ _)) H //= VectorSpec.map_id. + destruct_pair_let. + rewrite /cref2Bv /OCycle0REF //=; by apply BVEq_iff_eq. + } + cbv [get_st]; rewrite (surjective_pairing (step RequestQueue' _ _)) H //=; destruct_pair_let. + by []. + Qed. *) + + (* Have to add the full case *) + (* REF bounded with PREA_date or arbitrary parameter *) + (* if REF is bounded with PREA_date, a problem with cref + WAIT *) + (* try bound with random parameter, but will not be correspondent to Next_cycle *) + Theorem SM_Eq_NFULL (t : nat) (c_state : State_t) (f_req: Request_t) + (c_req : Bvector REQUEST_WIDTH) (push : bool) : + let f_state := (HW_Default_arbitrate t).(Implementation_State) in + let R := HW_Arrival_at t in + R == [:: f_req] -> EqReq f_req c_req -> State_Eq f_state c_state -> + let '(f_nextstate,(f_cmd_o,f_req_o)) := Next_state R f_state in + let '(c_nextstate,(_,c_cmd_o,c_req_o)) := step FIFOSM c_state (true,c_req) in + (State_Eq f_nextstate c_nextstate) && + (EqCmd f_cmd_o c_cmd_o) && (EqReq f_req_o c_req_o). + Proof. + destruct (f_state) eqn:Hf_state. + { destruct (nat_of_ord c0 == PREA_date - 1) eqn:Hcref_prea; move: Hcref_prea. + { destruct r eqn:HR. + { apply SM_Eq_1a. } + { apply SM_Eq_1b. } + } + { destruct (c0 + WAIT < PREA_date) eqn:Hcref_service; move: Hcref_service. + { destruct r eqn:HR. + { apply SM_Eq_2a. } + { admit. (* Case 2b: IDLE -> RUNNING (non-empty queue) *)} + } + { destruct r eqn:HR. + { admit. (* Case 3a: IDLE -> IDLE (empty queue )*)} + { admit. (* Case 3b: IDLE -> IDLE (non empty queue) *) } + } + } + } + { destruct (nat_of_ord c0 == OACT_date) eqn:Hact_date. + { destruct r eqn:HR. + { admit. (* Case 4a : RUNNING -> RUNNING (ACT) (empty queue) *) } + { admit. (* Case 4b : RUNNING -> RUNNING (ACT) (non empty queue) *)} + } + { destruct (nat_of_ord c0 == OCAS_date) eqn:Hcas_date. + { destruct r eqn:HR. + { admit. (* Case 5a : RUNNING -> RUNNING (CAS) (empty queue )*) } + { admit. (* Case 5b : RUNNING -> RUNNING (CAS) (non-empty queue) *)} + } + { destruct (nat_of_ord c0 == WAIT.-1) eqn:Hend_date. + { destruct r eqn:HR. + { admit. (* Case 6a : RUNNING -> IDLE (empty queue) *) } + { admit. (* Case 6b : RUNNING -> IDLE (non empty queue) *)} + } + { destruct r eqn:HR. + { admit. (* Case 7a : RUNNING -> RUNNING (empty queue) *) } + { admit. (* Case 7b : RUNNING -> RUNNING (non empty queue) *) } + } + } + } + } + { destruct (nat_of_ord c0 == OREF_date) eqn:Href_date. + { destruct r eqn:HR. + { admit. } + { admit. } + } + { destruct (nat_of_ord c0 == OENDREF_date) eqn:Hendref_date. + + } + + } + +End EquivalenceProof. \ No newline at end of file diff --git a/framework/CavaDRAM/Lib/CavaFIFOREFProperties2.v b/framework/CavaDRAM/Lib/CavaFIFOREFProperties2.v new file mode 100644 index 0000000..949d7ab --- /dev/null +++ b/framework/CavaDRAM/Lib/CavaFIFOREFProperties2.v @@ -0,0 +1,311 @@ +Set Printing Projections. +From CavaDRAM Require Import CavaFIFOREF. +Require Import Program. + +Ltac destruct_products := + repeat match goal with + | p: _ * _ |- _ => destruct p + | H: _ /\ _ |- _ => let Hl := fresh H "l" in let Hr := fresh H "r" in destruct H as [Hl Hr] + | E: exists y, _ |- _ => let yf := fresh y in destruct E as [yf E] + end. + +Ltac simplify_step := + first [ destruct_pair_let + | rewrite eqb_nat_to_bitvec_sized; by Lia.lia + | rewrite nat_to_bitvec_to_nat; by Lia.lia + | progress simpl_ident + | progress autorewrite with to_spec + | progress cbn [fst snd map] ]. + +Ltac simplify := repeat simplify_step. +Ltac simpl_ret := cbv [ret monad CombinationalSemantics Identity.Monad_ident]. + +Section CavaSMProperties2. + (* From Cava *) + Existing Instance CombinationalSemantics. + (* From CavaDRAM*) + Context {CAVA_SYS : CavaSystem}. + (* From CoqDRAM *) + Existing Instance REQESTOR_CFG. + Context {SYS_CFG : System_configuration}. + Context {FIFO_CFG : FIFO_configuration}. + Context {AF : Arrival_function_t}. + Existing Instance FIFO_implementation. + + Definition State_t := circuit_state FIFOSM. + + Definition get_mem (s : State_t) := + let '(_,(_,(_,(_,(_, (_, (_,_, _),_)),_,mem_state,_, + (_, _),(_, (_, (_, _, _),_)),_,_),_),(_,(_,(_,(_, + (_, (_,_)),_, _, _,_, _,_),_),_)),_)) := s in mem_state. + + Definition get_pop (s : State_t) := + let '(_,(_,(_,(_,(_,(_,(_, _, _),_)),_,_,_, + (_,_),(_,(_,(_,_,_),_)),_,_),_),(_,(_,(_,(_, + (_, (_,_)),_,_,_,_,_,_),_),_)),pop)) := s in pop. + + Definition get_st (s : State_t) := + let '(_,(_,(_,(_,(_,(_,(_, _, _),_)),_,_,_, + (_,_),(_,(_,(_,_,_),_)),_,_),_),(_,(_,(_,(_, + (_, (_,_)),_,_,_,_,_,_),_),st)),_)) := s in st. + + Definition get_cnt (s : State_t) := + let '(_,(_,(_,(_,(_,(_,(_, _, _),_)),_,_,_, + (_,_),(_,(_,(_,_,_),_)),_,_),_),(_,(_,(_,(_, + (_, (_,_)),_,_,_,_,_,_),cnt),_)),_)) := s in cnt. + + Definition get_cref (s : State_t) := + let '(_,(_,(_,(_,(_,(_,(_, _, _),_)),_,_,_, + (_,_),(_,(_,(_,_,_),_)),_,_),_),(_,(_,(_,(_, + (_, (_,_)),_,_,_,_,_,cref),_),_)),_)) := s in cref. + + Definition get_cr (s : State_t) := + let '(_,(_,(_,(_,(_,(_,(_, _, _),_)),_,_,_, + (_,_),(_,(_,(_,_,_),_)),_,_),_),(_,(_,(_,(_, + (_, (_,cr)),_,_,_,_,_,_),_),_)),_)) := s in cr. + + Definition get_wra (s : State_t) := + let '(_,(_,(_,(_,(_,(_,(_, _, _),_)),_,_,_, + (_,_),(_,(_,(_,_,_),_)),_,_),wra),(_,(_,(_,(_, + (_, (_,_)),_,_,_,_,_,_),_),_)),_)) := s in wra. + + Definition get_rda (s : State_t) := + let '(_,(_,(_,(_,(_,(_,(_, _, _),_)),_,_,_, + (_,_),(_,(_,(_,_,_),_)),_,rda),_),(_,(_,(_,(_, + (_, (_,_)),_,_,_,_,_,_),_),_)),_)) := s in rda. + + Definition cnt2Bv (cnt : Counter_t) := + N2Bv_sized COUNTER_WIDTH (N.of_nat (nat_of_ord cnt)). + + Definition cref2Bv (cref : nat) := + N2Bv_sized COUNTER_REF_WIDTH (N.of_nat cref). + + Program Definition EqArrival (r : Requests_t) (r' : Bvector REQUEST_WIDTH) : bool. + Admitted. + + Program Definition EqReq (r : Request_t) (r' : Bvector REQUEST_WIDTH) : bool. + Admitted. + + (* Write this *) + Program Definition EqMem (P : Requests_t) (mem : circuit_state memqueue) : bool. + Admitted. + + (* Rewrite the predicate *) + Import BvectorNotations. + Open Scope Bvector_scope. + Definition State_Eq' (fram_state : FIFO_state_t) (cava_state : State_t) : bool := + let s := get_st cava_state in + let c' := get_cnt cava_state in + let cref' := get_cref cava_state in + let r' := get_cr cava_state in + let wra := get_wra cava_state in + let rda := get_rda cava_state in + let pop := get_pop cava_state in + let mem := get_mem cava_state in + match fram_state with + | IDLE c cref P => + (s =? STATE_IDLE_VEC) && (cnt2Bv c =? c') && (cref2Bv cref =? cref') && ( + match P with + | [::] => (wra =? rda) + | x :: x0 => EqMem (x :: x0) mem + end) + | RUNNING c cref P r => + (s =? STATE_RUN_VEC) && (cnt2Bv c =? c') && (cref2Bv cref =? cref') && ( + match P with + | [::] => (wra =? rda) + | x0 :: xS => EqMem (x0 :: xS) mem + end) && + (EqReq r r') + | REFRESHING cref P => + (s =? STATE_REF_VEC) && (cref2Bv cref =? cref') && + ((wra =? rda) == (P == [::])) + end. + + Definition State_Eq (fram_state : FIFO_state_t) (cava_state : State_t) : bool := + let s := get_st cava_state in + let c' := get_cnt cava_state in + let cref' := get_cref cava_state in + let r' := get_cr cava_state in + let wra := get_wra cava_state in + let rda := get_rda cava_state in + let pop := get_pop cava_state in + match fram_state with + | IDLE c cref P => + (s =? STATE_IDLE_VEC) && (cnt2Bv c =? c') && (cref2Bv cref =? cref') && + ((wra =? rda) == (P == [::])) + | RUNNING c cref P r => + (s =? STATE_RUN_VEC) && (cnt2Bv c =? c') && (cref2Bv cref =? cref') && (EqReq r r') && + ((wra =? rda) == (P == [::])) + | REFRESHING cref P => + (s =? STATE_REF_VEC) && (cref2Bv cref =? cref') && + ((wra =? rda) == (P == [::])) + end. + + Lemma BVEq_eq {N} (a b : Bvector N) : + (a =? b) = true -> a = b. + Proof. + intros. + specialize VectorEq.eqb_eq with (A_beq := Bool.eqb) (v1 := a) (v2 := b) as HH. + unfold BVeq in H. + apply HH in H; [exact H | exact Bool.eqb_true_iff ]. + Qed. + + (* NOT IMPORTANT FOR FULL PROOF -> FOR FALSE SIGNAL *) + Lemma fullAdder_cin {n} (x y : Vector.t bool n) cin: + let c := N.to_nat (Bv2N y) <= N.to_nat (Bv2N x) in + let out := if cin + then (if c then (N.sub (Bv2N x) (Bv2N y)) else Bv2N (Vec.xor (x,y))) + else (if c then Bv2N (Vector.map negb (Vec.xor (x,y))) else N.add (Bv2N x) (Bv2N (Vector.map negb y))) in + fst (col fullAdder cin (vcombine x (Vector.map negb y))) = + Vec.bitvec_literal (N2Bv_sized n out). + Admitted. + + (* NOT IMPORTANT FOR FULL PROOF -> FOR FALSE SIGNAL *) + Lemma P2Bv_sized_neq_iff (n : nat) (x y : positive) : + (Pos.size_nat x <= n) -> + (Pos.size_nat y <= n) -> + (P2Bv_sized n x <> P2Bv_sized n y) <-> x <> y. + Proof. + revert x y; induction n; intros. + { split; intros. + { simpl in H1. contradict H1. reflexivity. } + { pose proof (Pos_size_nat_nonzero x). + contradict H. apply /negP. rewrite -ltnNge. + apply /ltP; exact H2. } + } + { split; try congruence; []. + cbn [P2Bv_sized]. + destruct x,y; try congruence; [ | | | ]. + all: cbn [Pos.size_nat] in *. + all: admit. + } + Admitted. + + (* NOT IMPORTANT FOR FULL PROOF -> FOR FALSE SIGNAL *) + Lemma N2Bv_sized_neq_iff: forall (n : nat) (x y : N), + (N.size_nat x <= n)%coq_nat -> (N.size_nat y <= n)%coq_nat -> + N2Bv_sized n x <> N2Bv_sized n y <-> x <> y. + Proof. + destruct x, y; cbn [N.size_nat N2Bv_sized]; intros; split; intros. + 8: { + rewrite P2Bv_sized_neq_iff; try congruence. + all: apply /leP; try (exact H || exact H0). + } + all: try discriminate. + all: try (cbv [Bvect_false] in H1; done). + all: try (apply P2Bv_nonzero in H0; apply ssrfun.nesym in H0). + all: try exact H0. + all: try by apply P2Bv_nonzero in H. + all: try (congruence). + Qed. + + (* NOT IMPORTANT FOR FULL PROOF -> FOR FALSE SIGNAL *) + Lemma FullEmptyLogic_equiv (c : circuit_state FullEmptyLogic) wra rda : + wra = rda -> exists c', step FullEmptyLogic c (wra,rda) = (c',(false,true)). + Proof. + intro H; evar (c' : circuit_state FullEmptyLogic); exists c'. + cbv [FullEmptyLogic FullLogic EmptyLogic Subtractor subtractor dropr EqFULL subtractor FullVEC]; + cbn [step fst snd]. + rewrite H CavaPreludeProperties.eqb_refl. + rewrite fullAdder_cin. + assert ((N.to_nat (Bv2N rda) <= N.to_nat (Bv2N rda)) = true); [by rewrite leqnn | ]. + rewrite H0. + assert (N.sub (Bv2N rda) (Bv2N rda) = 0%N); [ by rewrite N.sub_diag | ]b_neq; + [ instantiate (c' := ((), ((), (), ()), ())); by unfold c' | ]. + rewrite !bitvec_literal_correct. + apply N2Bv_sized_neq_iff. + { apply Nat.le_0_l. } + { rewrite N.sub_1_r -Nat2N.inj_pred. + apply N.size_nat_le_nat; unfold ADDR_WIDTH. + specialize QUEUE_MAX_SIZE_GT_0 as Hq0. + apply Nat.log2_spec in Hq0 as [H2 H2_]. + admit. (* lt / log2 / pow 2*) + } + { specialize QUEUE_MAX_SIZE_GT_1 as Hq1. + apply Lt.lt_0_neq in Hq1. + admit. (* Nat / nat*) + } + Admitted. + + Definition get_addr (c : circuit_state RequestQueue) := + let '(_,(_,(_,(_,(_,(_,_,_),_)),_,_,_, + (_,_),(_,(_,(_,_,_),_)),_,rda),wra)) := c in (rda,wra). + + (* if address are the same -> modify the RequestQueue circuit : send back REQUEST_nil *) + (* if addresses are different -> step through the queue will read whatever is stored in rda + is that used in the circuit ? -> yes + cr will be taken from the queue when (Sidle /\ ~~ empty /\ Cprea) + *) + + (* make a lemma for diff address + step RequestQueue c (true,c_req,pop) = (c',(f',MemRead@rda,p')) + *) + + (* EMPTY OR NOT, data_o is always what is in rda *) + + Lemma RequestQueue_equiv (c : circuit_state RequestQueue) c_req pop : + let '(rda,wra) := get_addr c in wra = rda -> exists c', + step RequestQueue c (true,c_req,pop) = (c',(false,REQUEST_NIL,true)). + Proof. + simpl in c; destruct_products. + rename t0 into rda, t into wra. + cbv [get_addr]; intros. + evar (c' : circuit_state RequestQueue); exists c'. + cbv [RequestQueue LoopInit fork2]. + cbn [step fst snd]. + simpl_ret. + + specialize FullEmptyLogic_equiv with (c := (u15, (u17, u18, u16), u14)) (wra := wra) (rda := rda) + as Hequiv1; apply Hequiv1 in H as HH; clear Hequiv1; destruct HH as [cequiv1 Hequiv1]. + rewrite Hequiv1. + cbn [fst snd bind inv and2 or2]. + + rewrite negb_false negb_true orbT. + rewrite andb_false_r andb_true_r. + Check memqueue. + rewrite ; simpl (true && true). + + simpl (~~ false). + rewrite orbT. + progress autorewrite with simpl_ident. + simpl_ident. + + simpl in cequiv1. + unfold cequiv1. cbn [cequiv1]. + destruct_products. + fold (memqueue c _). + repeat destruct_pair_let. cbn [step]. + Admitted. + + Theorem SM_Eq (t : nat) (c_state : State_t) (f_req: Request_t) + (c_req : Bvector REQUEST_WIDTH) : + let f_state := (Default_arbitrate t).(Implementation_State) in + let R := Arrival_at t in + State_Eq f_state c_state -> EqArrival R c_req -> + let '(f_nextstate,_) := Next_state R f_state in + let '(c_nextstate,_) := step FIFOSM c_state (true,c_req) in + State_Eq f_nextstate c_nextstate. + Proof. + intros f_state R H Hreq; cbv [FIFOSM] in *. + unfold State_t in c_state; simpl in c_state; destruct_products. + rename t0 into s, t1 into cnt, t2 into cref, t3 into cr, t4 into wra, t5 into rda, b into pop. + cbv [State_Eq get_st get_cnt get_cref get_wra get_rda get_cr] in H. + destruct (f_state) eqn:Hf_state. + { destruct R eqn:HR; [ admit (* impossible, contradicts Hreq *) | ]. + destruct r eqn:HP. + { move: H => /andP [/andP [/andP [Hs Hc] Hcref] /eqP Haddr]; rewrite eq_refl in Haddr. + apply BVEq_eq in Hs,Hc,Hcref,Haddr. + subst s cnt cref wra. + cbv [LoopInit]. + cbn [step fst snd]. + cbv [ret monad CombinationalSemantics Identity.Monad_ident]. + simpl_ident. + cbv [ret ]. + destruct_pair_let. + (* Make a lemma to step through RequestQueue *) + + } + } + + (* Default arbitrate should be equal to the simulate function *) +End EquivalenceProof. \ No newline at end of file diff --git a/framework/CavaDRAM/Lib/CavaSM.v b/framework/CavaDRAM/Lib/CavaSM.v index 32323ac..77f01b7 100644 --- a/framework/CavaDRAM/Lib/CavaSM.v +++ b/framework/CavaDRAM/Lib/CavaSM.v @@ -1,5 +1,5 @@ From CavaDRAM Require Import CavaReqQueue CavaUtil. -From DRAM Require Import System. +From CoqDRAM Require Import System. From Coq Require Import BinaryString HexString NArith. Module DataNotation. diff --git a/framework/CavaDRAM/Lib/CavaSMProperties2.v b/framework/CavaDRAM/Lib/CavaSMProperties2.v index a13d35c..5a637c9 100644 --- a/framework/CavaDRAM/Lib/CavaSMProperties2.v +++ b/framework/CavaDRAM/Lib/CavaSMProperties2.v @@ -110,7 +110,11 @@ Section CavaSMProperties2. rewrite CavaPreludeProperties.eqb_refl. rewrite fullAdder_cin leqnn N.sub_diag CavaPreludeProperties.eqb_neq. 2: { rewrite /FullVEC; simplify. admit. } - instantiate (cs := (tt, (tt, tt, tt), tt)); unfold cs. + instantiate (cs := (tt, (tt, tt, tt), tt)); unfo(CavaPrelude.eqb + (let (x, _) := + not_b <- Vec.inv rda;; + aV <- unpackV rda;; bV <- unpackV not_b;; col fullAdder one (vcombine aV bV) in + x, Vec.bitvec_literal (N2Bv_sized ADDR_WIDTH (N.of_nat QUEUE_MAX_SIZE - 1)))ld cs. reflexivity. Admitted. diff --git a/framework/CavaDRAM/Lib/CavaSMbackup.v b/framework/CavaDRAM/Lib/CavaSMbackup.v index 7c04f1f..8275535 100644 --- a/framework/CavaDRAM/Lib/CavaSMbackup.v +++ b/framework/CavaDRAM/Lib/CavaSMbackup.v @@ -4,7 +4,7 @@ From Coq Require Export Vectors.Fin Bool.Bool Program.Basics. From CavaDRAM Require Export CavaReqQueue. -From DRAM Require Export FIFO. +From CoqDRAM Require Export FIFO. Section CavaSM. diff --git a/framework/CavaDRAM/Lib/CavaTactics.v b/framework/CavaDRAM/Lib/CavaTactics.v index 6a2e86e..e9f52c4 100644 --- a/framework/CavaDRAM/Lib/CavaTactics.v +++ b/framework/CavaDRAM/Lib/CavaTactics.v @@ -17,4 +17,10 @@ Ltac simplify_step := | progress autorewrite with to_spec | progress cbn [fst snd map] ]. -Ltac simplify := repeat simplify_step. \ No newline at end of file +Ltac simplify := repeat simplify_step. + +Ltac destruct_pair_let_ H := + match goal with + | |- context [ match ?p with pair _ _ => _ end ] => + rewrite (surjective_pairing p) + end. \ No newline at end of file diff --git a/framework/CavaDRAM/Memory.v b/framework/CavaDRAM/Memory.v new file mode 100644 index 0000000..04040ae --- /dev/null +++ b/framework/CavaDRAM/Memory.v @@ -0,0 +1,293 @@ +Require Import String NArith PeanoNat Bvector ssreflect. +Require BinaryString Vectors.VectorDef Coq.Arith.Compare. +Global Open Scope string_scope. + +Require Import ExtLib.Structures.Monad. +From Cava Require Import Core Semantics.Simulation Semantics.Combinational Util.Tactics. +From Cava.Lib Require Vec. +From Cava.Lib Require Import CavaPrelude Combinators Multiplexers Decoder DecoderProperties CombinatorsProperties. + +Import MonadNotation Circuit.Notations Init.Logic.EqNotations. +Global Open Scope monad_scope. + +Require Import CavaDRAM.Util CavaDRAM.Step. + +Section WithCava. + Context `{semantics : Cava}. + + (* write data * write enable -> read data*) + Definition mem_cell T I := + DelayInitCE (t := T) I. + + (* read data vector * write data * write enable * read data -> read data vector *) + Definition mem_combine {M N} T (H : S M = N) := + Comb ( + fun (input : signal (Vec T M) * (signal T * signal Bit * signal T)) => + let '(rdV, (wd, we, rd)) := input in + v <- mux2 we (rd, wd);; + x <- Vec.shiftin v rdV;; + r <- Util.vec_cast T H x;; + ret r + ). + + (* write data * write enable vector -> write data * write enable *) + Definition mem_we T W N := + Comb ( + fun input : signal T * signal (Vec Bit (2^W)) => + let '(wd, weV) := input in + we <- indexConst weV (N-1);; + ret (wd, we) + ). + + (* write data * write enable vector -> read data vector *) + Fixpoint mem_cells T W N I: (Circuit (signal T * signal (Vec Bit (2^W))) (signal (Vec T N))) := + match N as X return X = N -> _ with + | 0 => + fun H => + Comb (fun x => + r <- Vec.nil;; + x <- (Util.vec_cast T H r);; + ret x + ) + | S N' => + fun H => + Comb(fork2) + >==> First (mem_cells T W N' I) + >==> Second (mem_we T W N >==> Comb(fork2) >==> Second (mem_cell T (I N'))) + >==> mem_combine T H + end Logic.eq_refl. + + (* write data * write address * write enable -> write data * write enable vector *) + Definition mem_write T W := + Comb ( + fun input : signal T * signal (Vec Bit W) * signal Bit => + let '(wd, wa, we) := input in + weV <- Util.decode we wa;; + ret (wd, weV) + ). + + (* read address * read data vecor -> read data *) + Definition mem_read T W N P (PP : nat) := + Comb ( + fun input : signal (Vec (Vec Bit W) P) * signal (Vec T N) => + '(rdAV, rdV) <- input;; + rdA <- indexConst rdAV PP;; + indexAt rdV rdA + ). + + Definition mem_read_combine {M N} T (H : S M = N) := + Comb ( + fun (input : signal (Vec T M) * (signal T)) => + let '(rdV, rd) := input in + x <- Vec.shiftin rd rdV;; + r <- Util.vec_cast T H x;; + ret r + ). + + Fixpoint mem_reads T W N P PP : (Circuit (signal (Vec (Vec Bit W) P) * signal (Vec T N)) (signal (Vec T PP))) := + match PP as X return X = PP -> _ with + | 0 => + fun H => + Comb (fun x => + r <- Vec.nil;; + x <- (Util.vec_cast T H r);; + ret x + ) + | S PP' => + fun H => + Comb(fork2) + >==> First (mem_reads T W N P PP') + >==> Second (mem_read T W N P PP') + >==> mem_read_combine T H + end Logic.eq_refl. + + (* read addresses * write data * write address * write enable -> read data + T: type of memory cell contents (Vec 32) + W: address width in bits + P: number of read ports + I: initial content of memory + *) + (* Second (mem_write T W >==> mem_cells T W (2^W) I). >==> mem_read T W (2^W) P 1). *) + + Definition Memory T W P I := + Second (mem_write T W >==> mem_cells T W (2^W) I) >==> mem_reads T W (2^W) P P. + + Definition Memory' T W P I := + Second (mem_write T W >==> mem_cells T W (2^W) I) >==> mem_read T W (2^W) P 0. + +End WithCava. + +Module Test. + Import ListNotations Vector.VectorNotations. + Import Cava.Semantics.Simulation. + + Definition Test_input1 := [ + ([N2Bv_sized 3 0; N2Bv_sized 3 2]%vector, (N2Bv_sized 2 0, N2Bv_sized 3 0, false)); + ([N2Bv_sized 3 1; N2Bv_sized 3 3]%vector, (N2Bv_sized 2 0, N2Bv_sized 3 0, false)); + ([N2Bv_sized 3 2; N2Bv_sized 3 0]%vector, (N2Bv_sized 2 0, N2Bv_sized 3 0, false)); + ([N2Bv_sized 3 3; N2Bv_sized 3 1]%vector, (N2Bv_sized 2 0, N2Bv_sized 3 0, false)) + ]%list. + + Definition Test_result1 := + [ + [0%N; 2%N]%vector; + [1%N; 3%N]%vector; + [2%N; 0%N]%vector; + [3%N; 1%N]%vector + ]%list. + + (* Initializes the memory content with the address *) + Definition Init1 (n : nat):= + N2Bv_sized 2 (N.of_nat n). + + Definition Test_run1 := + map (Vector.map Bv2N) (simulate (Memory (Vec Bit 2) 3 2 Init1) Test_input1). + + Lemma Test: Test_run1 = Test_result1. + Proof. + reflexivity. + Qed. + + Definition Test_input2 := + [ + (* writes 0 at @0, reads @0 := 0 and @3 := 0 *) + ([N2Bv_sized 3 0; N2Bv_sized 3 3]%vector, (N2Bv_sized 2 0, N2Bv_sized 3 0, true)); + (* writes 1 at @1, reads @1 := 1 and @2 := 1 *) + ([N2Bv_sized 3 1; N2Bv_sized 3 2]%vector, (N2Bv_sized 2 1, N2Bv_sized 3 1, true)); + (* writes 2 at @2, reads @2 := 2 and @1 := 1*) + ([N2Bv_sized 3 2; N2Bv_sized 3 1]%vector, (N2Bv_sized 2 2, N2Bv_sized 3 2, true)); + ([N2Bv_sized 3 3; N2Bv_sized 3 0]%vector, (N2Bv_sized 2 3, N2Bv_sized 3 3, true)); + ([N2Bv_sized 3 0; N2Bv_sized 3 3]%vector, (N2Bv_sized 2 2, N2Bv_sized 3 1, false)); + ([N2Bv_sized 3 1; N2Bv_sized 3 2]%vector, (N2Bv_sized 2 2, N2Bv_sized 3 1, false)); + ([N2Bv_sized 3 2; N2Bv_sized 3 1]%vector, (N2Bv_sized 2 2, N2Bv_sized 3 1, false)); + ([N2Bv_sized 3 3; N2Bv_sized 3 0]%vector, (N2Bv_sized 2 2, N2Bv_sized 3 1, false)) + ]%list. + + Definition Init2 (n : nat):= + N2Bv_sized 2 (N.of_nat (3-n)). + + Definition Test_run2 := + map (Vector.map Bv2N) (simulate (Memory (Vec Bit 2) 3 2 Init2) Test_input2). + + Definition Test_result2 := + [ + [0%N; 0%N]%vector; + [1%N; 1%N]%vector; + [2%N; 1%N]%vector; + [3%N; 0%N]%vector; + [0%N; 3%N]%vector; + [1%N; 2%N]%vector; + [2%N; 1%N]%vector; + [3%N; 0%N]%vector + ]%list. + + Lemma Test2 : Test_run2 = Test_result2. + reflexivity. + Qed. +End Test. + +Module Properties. + + Definition Cells_state_prod {T W N M I} (H : N = S M) (r : circuit_state (mem_cells T W N I)) : + (unit * circuit_state (mem_cells T W M I) * (unit * unit * circuit_state (mem_cell T (I N))) * unit)%type. + Proof. + destruct N. + - discriminate H. + - rewrite H in r; simpl in r; exact r. + Defined. + + Fixpoint Cells_data {T W N I} (S : circuit_state (mem_cells T W N I)) : Vector.t (combType T) N := + match N as X return N = X -> X = N -> _ with + | 0%nat => + fun H H' => + Vector.nil (combType T) + | S N' => + fun H H'=> + let '(_, s', (_, _, v), _) := Cells_state_prod H S in + let r := Cells_data s' in + Vector.shiftin v r + end Logic.eq_refl Logic.eq_refl. + + Fixpoint Cells_read {T W N I} we wa wd (S : circuit_state (mem_cells T W N I)) : Vector.t (combType T) N := + match N as X return N = X -> X = N -> _ with + | 0%nat => + fun H H' => + Vector.nil (combType T) + | S N' => + fun H H'=> + let '(_, s', (_, _, v), _) := Cells_state_prod H S in + let r := Cells_read we wa wd s' in + if ((wa =? N') && we)%nat then Vector.shiftin wd r + else Vector.shiftin v r + end Logic.eq_refl Logic.eq_refl. + + (* cells data won't change if not writing *) + Lemma Cells_const {T W N I} (S : circuit_state (mem_cells T W N I)) wd we: + (forall n, indexConst we n = constant false) -> + Cells_data S = Cells_data (fst (step (mem_cells T W N I) S (wd, we))). + Proof. + intros Hwe. + induction N. + - reflexivity. + - unfold mem_cells; fold mem_cells; unfold mem_cell. + repeat step_destruct. + rewrite (surjective_pairing (step (mem_cells _ _ _ _) SC3 _)) /=. + rewrite Hwe (surjective_pairing SC2) (surjective_pairing (fst SC2)) IHN. + reflexivity. + Qed. + + (* Other parts of the memory do not change *) + Lemma Cells_match {T W N I} (S : circuit_state (mem_cells T W N I)) wd wa we wev: + (forall n, (wa =? n)%nat = false -> + indexConst wev n = constant false) -> + indexConst wev wa = constant we -> + Cells_read we wa wd S = Cells_read we wa wd (fst (step (mem_cells T W N I) S (wd, wev))). + Proof. + intros Hwde Hwe. + induction N. + - reflexivity. + - unfold mem_cells; fold mem_cells; unfold mem_cell. + repeat step_destruct. + rewrite (surjective_pairing (step (mem_cells _ _ _ _) SC3 _)) /=. + rewrite (surjective_pairing SC2) (surjective_pairing (fst SC2)) IHN. + destruct (wa =? N)%nat eqn:Hwa, we. + + move : Hwa => /Nat.eqb_eq Hwa; subst N; reflexivity. + + move : Hwa => /Nat.eqb_eq Hwa; subst N; rewrite Nat.sub_0_r Hwe; reflexivity. + + rewrite Nat.sub_0_r (Hwde N Hwa); reflexivity. + + rewrite Nat.sub_0_r (Hwde N Hwa); reflexivity. + Qed. + + Lemma Cells_matchX {T W N I} (S : circuit_state (mem_cells T W N I)) wd wa we wev: + (forall n, (wa =? n)%nat = false -> indexConst wev n = constant false) -> + indexConst wev wa = constant we -> + Cells_read we wa wd S = Cells_data (fst (step (mem_cells T W N I) S (wd, wev))). + Proof. + intros Hwde Hwe. + induction N. + - reflexivity. + - unfold mem_cells; fold mem_cells; unfold mem_cell. + repeat step_destruct. + rewrite (surjective_pairing (step (mem_cells _ _ _ _) SC3 _)) /=. + rewrite (surjective_pairing SC2) (surjective_pairing (fst SC2)) IHN. + destruct (wa =? N)%nat eqn:Hwa, we. + + move : Hwa => /Nat.eqb_eq Hwa; subst N; rewrite Nat.sub_0_r Hwe; reflexivity. + + move : Hwa => /Nat.eqb_eq Hwa; subst N; rewrite Nat.sub_0_r Hwe; reflexivity. + + rewrite Nat.sub_0_r (Hwde N Hwa); reflexivity. + + rewrite Nat.sub_0_r (Hwde N Hwa); reflexivity. + Qed. + + (* Fixpoint Mem_read {T W PP} (md : Vector.t (combType T) (2^W)) (rav : VectorDef.t (Bvector W) PP) := + match PP as X return PP = X -> _ with + | 0 => + fun H => + Vector.nil (combType T) + | S PP' => + fun H => + let rav := Vector.cast rav H in + let r := Mem_read md (Vector.tl rav) in + let i := Bv2Fin (Vector.hd rav) in + let v := Vector.nth md i in + Vector.shiftin v r + end Logic.eq_refl. *) + +End Properties. diff --git a/framework/CavaDRAM/README_extraction.md b/framework/CavaDRAM/README_extraction.md new file mode 100644 index 0000000..ba2677b --- /dev/null +++ b/framework/CavaDRAM/README_extraction.md @@ -0,0 +1,9 @@ +## Performing extraction + +- CavaSMExtraction has to be in _CoqProject, this will generate every haskell file from Coq files + +- I added the Data.Char and Data.Bits in two files where they were needed (should be automatic) + +- The script 'cava2sv.sh' will use ghc to compile the top-level 'CavaFIFOSV.hs', which will on its turn call the haskell function 'writeSystemVerilog' from the Cava library. The compiled program will produce a program. + +- Executing ./CavaFIFOSV will generate SystemVerilog code. \ No newline at end of file diff --git a/framework/CavaDRAM/Step.v b/framework/CavaDRAM/Step.v new file mode 100644 index 0000000..ddde91f --- /dev/null +++ b/framework/CavaDRAM/Step.v @@ -0,0 +1,97 @@ +Set Printing Projections. +Require Import String NArith PeanoNat Bvector Vectors.Vector ssreflect. +Require BinaryString Vectors.Vector Coq.Arith.Compare ZArith.BinInt. +Global Open Scope string_scope. + +Require Import ExtLib.Structures.Monad. +Require Import Cava.Core.Core Cava.Semantics.Simulation Cava.Semantics.Combinational Cava.Util.Tactics. +From Cava.Lib Require Vec. +From Cava.Lib Require Import CavaPrelude Combinators. + +Import MonadNotation Circuit.Notations Init.Logic.EqNotations. +Open Scope monad_scope. + +Open Scope vector_scope. + +Lemma step_compose {I M O} (c1 : Circuit I M) (c2 : Circuit M O) i cs : + step (Compose c1 c2) cs i = let (sc1, o1) := (step c1 (fst cs) i) in + let (sc2, o2) := (step c2 (snd cs) o1) in (sc1, sc2, o2). +Proof. + simpl; repeat destruct (step _ _ _); reflexivity. +Qed. + +Lemma step_comb {I O} (f : I -> O) i (cs : circuit_state (Comb f)): + step (Comb f) cs i = (tt, f i). +Proof. + reflexivity. +Qed. + +Lemma step_second {I T O} (i : T * I) (c : Circuit I O) (cs : circuit_state (Second c)): + step (Second c) cs i = let '(cs', x) := step c cs (snd i) in (cs', (fst i, x)). +Proof. + simpl in cs. + reflexivity. +Qed. + +Lemma step_first {I T O} (i : I * T) (c : Circuit I O) (cs : circuit_state (First c)): + step (First c) cs i = let '(cs', x) := step c cs (fst i) in (cs', (x, snd i)). +Proof. + simpl in cs. + reflexivity. +Qed. + +Lemma step_loop {I O S} (c : Circuit (I * (combType S)) (O * (combType S))) cs i r: + step (LoopInitCE r c) cs i = + let '(cs', (out, v')) := step c (fst cs) (fst i, snd cs) in + let new_state := if snd i then v' else snd cs in + (cs', new_state, out). +Proof. + destruct i, cs. + reflexivity. +Qed. + +Ltac destruct_state S := + try lazymatch S with + | fst (pair ?a ?b) => + simpl (snd (pair ?a ?b)) + | snd (pair ?a ?b) => + simpl (snd (pair ?a ?b)) + | fst ?S => + let S' := fresh "Sf" in destruct S eqn:S' + | snd ?S => + let S' := fresh "Ss" in destruct S eqn:S' + | ?S => + let S1 := fresh "SC" in + let S2 := fresh "SC" in + destruct S as [S1 S2]; + simpl (fst (S1, S2)); + simpl (snd (S1, S2)) + | ?S => + let S' := fresh "SS" in + destruct S as S' + end. + +Ltac my_simpl := + unfold fork2; + lazymatch goal with + | |- context [fst (ret (?a, ?b))] => + simpl (fst (ret (a, b))) + | |- context [snd (ret (?a, ?b))] => + simpl (snd (ret (a, b))) + end. + +Ltac step_destruct := + unfold LoopInit, Loop; + repeat my_simpl; + match goal with + | |- context [step (Comb _) ?S _] => + rewrite step_comb + | |- context [step (Compose _ _) ?S _] => + rewrite step_compose; destruct_state S + | |- context [step (LoopInitCE _ _) ?S _] => + rewrite step_loop; destruct_state S + | |- context [step (First _) ?S _] => + rewrite step_first; destruct_state S + | |- context [step (Second _) ?S _] => + rewrite step_second; destruct_state S + end; repeat my_simpl. diff --git a/framework/CavaDRAM/Util.v b/framework/CavaDRAM/Util.v new file mode 100644 index 0000000..7573b02 --- /dev/null +++ b/framework/CavaDRAM/Util.v @@ -0,0 +1,154 @@ +Set Printing Projections. +Set Warnings "-notation-overridden,-parsing". + +From Coq Require Import String NArith PeanoNat Bvector ssreflect. +Require BinaryString Vectors.Vector Coq.Arith.Compare. +Global Open Scope string_scope. + +Require Import ExtLib.Structures.Monad. +Require Import Cava.Core.Core Cava.Semantics.Simulation. +From Cava.Lib Require Vec. +From Cava.Lib Require Import CavaPrelude Combinators Multiplexers Decoder Adders. +Import MonadNotation Circuit.Notations Init.Logic.EqNotations. +Global Open Scope monad_scope. + +Section WithCava. + Context `{semantics : Cava}. + Definition bin_constant w (s : String.string) : signal (Vec Bit w) := + Vec.of_N (n := w) (BinaryString.Raw.to_N s 0). + + Definition computational_eq {m n} (opaque_eq: m = n) : m = n := + match Nat.eq_dec m n with + | left transparent_eq => transparent_eq + | _ => opaque_eq (* dead code; could use [False_rect] *) + end. + + Lemma computational_eq_eq {m n} (H : m = n): + computational_eq H = H. + Proof. + unfold computational_eq. + apply Logic.Eqdep_dec.UIP_dec. + apply Nat.eq_dec. + Qed. + + Definition vec_cast {n m} (T : SignalType) (H : n = m) (x : signal (Vec T n)) : cava (signal (Vec T m)) := + localSignal (rew [fun n0 : nat => signal (Vec T n0)] (computational_eq H) in x). + + Definition vec_extend {A} {m n} {H : m + (n - m) = n} (s : signal A) (v : signal (Vec A m)) : cava (signal (Vec A n)) := + lo <- unpackV v;; + hi <- Vector.const s (n - m);; + va <- packV (Vector.append lo hi);; + r <- (vec_cast A H va);; + ret r. + + Program Definition vec_trunc {A} {m n} {H : n <= m} (v : signal (Vec A m)) : cava (signal (Vec A n)) := + v' <- unpackV v;; + r <- Vectors.Vector.take n H v';; + packV r. + + Definition vec_extract_const {A} {s l n : nat} (H : (s + l) <= n) (v : signal (Vec A n)) : cava (signal (Vec A l)) := + r <- unpackV (signal := signal) v;; + r <- Vectors.Vector.take (s+l) H r;; + r <- snd (Vectors.Vector.splitat s r);; + packV r. + + Program Definition vec_concat {A} {m n} (hi : signal (Vec A m)) (lo : signal (Vec A n)) : cava (signal (Vec A (n + m))) := + hi <- unpackV hi;; + lo <- unpackV lo;; + va <- packV (Vector.append lo hi);; + ret va. + + Lemma decode_n {m n} (H : S n = m): 2^n + 2^n = 2^m. + Proof. + rewrite -H /= Nat.add_0_r. + reflexivity. + Defined. + + Lemma decode_zero {n} (H : 0 = n): 1 = 2^n. + Proof. + rewrite -H; reflexivity. + Defined. + + Lemma decode_one {m n} (H : S n = m) (H1 : 0 = n): 2 = 2^m. + Proof. + rewrite -H -H1; reflexivity. + Defined. + + Fixpoint decode_ {N} (en : signal Bit) (x : signal (Vec Bit N)) {struct N} : cava (signal (Vec Bit (2^N))) := + match N as X return X = N -> _ with + | 0 => + fun H => + r <- Vec.const en 1;; + r <- vec_cast Bit (decode_zero H) r;; + ret r + | S N' => + fun H => + match N' as X1 return X1 = N' -> _ with + | 0 => + fun H1 => + x <- vec_cast _ (eq_sym H) x;; + hs <- Vec.hd x;; + ls <- inv hs;; + lo <- and2(en, ls);; + hi <- and2(en, hs);; + r <- Vec.const hi 1;; + r <- Vec.cons lo r;; + r <- vec_cast Bit (decode_one H H1) r;; + ret r + | S N'' => + fun H1 => + x <- vec_cast _ (eq_sym H) x;; + t <- Vec.tl x;; + hs <- Vec.hd x;; + ls <- inv hs;; + len <- and2 (en, ls);; + hen <- and2 (en, hs);; + lo <- decode_ len t;; + hi <- decode_ hen t;; + r <- vec_concat hi lo;; + r <- vec_cast _ (decode_n H) r;; + ret r + end Logic.eq_refl + end Logic.eq_refl. + + Definition decode {N} (en : signal Bit) (x : signal (Vec Bit N)) : cava (signal (Vec Bit (2^N))) := + v' <- Vec.rev x;; + decode_ en v'. + + + Fixpoint Bv2Nat {N} (bv : Bvector N) : nat := + match bv with + | Vector.nil _ => 0%nat + | Vector.cons _ false _ bv' => 2 * (Bv2Nat bv') + | Vector.cons _ true _ bv' => S (2 * (Bv2Nat bv')) + end. + + Lemma Bv2Nat_upper_bound {N} (bv : Bvector N) : + ((Bv2Nat bv) < 2^N)%nat. + Proof. + induction bv. + { simpl; exact Nat.lt_0_1. } + { simpl. rewrite !Nat.add_0_r; destruct h. + { rewrite -Nat.add_succ_r. apply Nat.add_lt_le_mono. + { exact IHbv. } + { apply Lt.lt_le_S;exact IHbv. } + } + { apply Plus.plus_lt_compat; exact IHbv. } + } + Qed. + + Definition Bv2Fin {N} (v : Bvector N) : Fin.t (2^N). + specialize (Bv2Nat_upper_bound v) as H. + exact (Fin.of_nat_lt H). + Defined. + +End WithCava. + +(* get rid of the reverse *) +(* Section Properties. + + Context `{semantics : Cava}. + + Print Instances Cava. + Lemma test (n : nat) (t : cava (signal (Vec Bit n))): + indexConst (decode one t) n = zero. *) diff --git a/framework/CavaDRAM/UtilSM.v b/framework/CavaDRAM/UtilSM.v new file mode 100644 index 0000000..3adaebd --- /dev/null +++ b/framework/CavaDRAM/UtilSM.v @@ -0,0 +1,326 @@ +From CavaDRAM Require Import Memory Step. +From Coq Require Import Program BinaryString HexString NArith. +From Cava Require Import Cava CavaProperties Util.Vector. +From mathcomp Require Import fintype ssrZ zify ring. +From mathcomp Require Import ssreflect ssrnat ssrbool eqtype. + +Ltac simpl_ret := cbv [ret bind monad CombinationalSemantics Identity.Monad_ident]. +Ltac simpl_ret_H H := cbv [ret bind monad CombinationalSemantics Identity.Monad_ident] in H. + +Ltac fast_simpl_bool := + repeat lazymatch goal with + | |- context [(~~ _)] => vm_compute (~~ _) + | |- context [(andb false _)] => vm_compute (andb false _) + | |- context [(andb _ false)] => vm_compute (andb _ false) + | |- context [(orb _ true)] => vm_compute (orb _ true) + | |- context [(andb true true)] => vm_compute (andb true true) + end. + +Section WithCava. + + Lemma mulnP x y: + Nat.mul x y = muln x y. + Proof. auto. Qed. + + Lemma add_1_sub1 (x : N): + (0 < x)%N -> N.add (N.sub x 1) 1 = x. + Proof. lia. Qed. + + Lemma leq_Nle (a b : N) : + leq (nat_of_bin a) (nat_of_bin b) -> (a <= b)%N. + Proof. lia. Qed. + + Lemma ltn_Ntn (a b : N) : + leq (S (nat_of_bin a)) (nat_of_bin b) -> (a < b)%N. + Proof. lia. Qed. + + Lemma log2_eq1_pw2 (n : nat) : + Nat.pow 2 (Nat.log2 n) = n -> + Nat.log2 n = 1 -> n = 2. + Proof. intros; by rewrite H0 in H. Qed. + + Lemma lt_trans_le (n m p : N): + (m < n)%N -> (n < p)%N -> (m + 1 < p)%N. + Proof. lia. Qed. + + Lemma of_nat_neq (a b : nat) : + a <> b <-> (N.of_nat a <> N.of_nat b). + Proof. + intros; split; + specialize Nat2N.inj_iff with (n := a) (n' := b) as HH; by rewrite HH. + Qed. + + Lemma ltn_mul_add1 a b: + a < b -> 2 * a + 1 < 2 * b. + Proof. lia. Qed. + + Lemma of_nat_add_double z: + N.of_nat (z + z)%coq_nat = N.double (N.of_nat z). + Proof. + rewrite -Nat2N.inj_double; apply Nat2N.inj_iff; lia. + Qed. + + Lemma to_nat_lt_of_nat (a : N) (n : nat) : + N.to_nat a < n -> N.lt a (N.of_nat n). + Proof. + intros. + induction n; [ discriminate | ]. + rewrite leq_eqVlt in H; move: H => /orP [/eqP H | H]. + { rewrite -H Nat2N.inj_succ N2Nat.id; by specialize (N.lt_succ_diag_r a). } + assert (N.to_nat a < n). + { specialize (ltn_add2r 1 (N.to_nat a) n) as S; rewrite !addn1 in S; by rewrite S in H. } + apply IHn in H0. + apply N.lt_trans with (m := N.of_nat n); [ done | ]. + rewrite Nat2N.inj_succ; by specialize (N.lt_succ_diag_r (N.of_nat n)). + Qed. + + Lemma to_nat_lt_pow a b: + N.to_nat a < Nat.pow 2 b -> + N.lt a (2 ^ N.of_nat b). + Proof. + intros; apply to_nat_lt_of_nat in H. + rewrite -Nat2N.inj_pow in H. + by simpl (N.of_nat 2) in H. + Qed. + + Lemma predN_of_succ_nat (n : N) : + Pos.pred_N (Pos.of_succ_nat (N.to_nat n)) = n. + Proof. + induction n; [ by simpl | ]. + have s := (Pnat.Pos2SuccNat.id_succ p). + by rewrite Znat.positive_N_nat s Pos.pred_N_succ. + Qed. + + Lemma nth_0 {T} (def : T) (vec : Vector.t T 1) : + (nth_default def 0 vec) = Vector.hd vec. + Proof. + by rewrite nth_default_to_list -nth_hd (Vector.eta vec). + Qed. + + (* -------------------------- vector proofs -------------------- *) + Lemma eqb_iff_neq {t} (x y : combType t) : CavaPrelude.eqb (x, y) = false -> x <> y. + Proof. + by intros; rewrite -CavaPreludeProperties.eqb_eq H. + Qed. + + Lemma length_to_list_shiftin {A N} (v : Vector.t A N) (e : A) : + Datatypes.length (Vector.to_list (Vector.shiftin e v)) = N + 1. + Proof. + induction v; [ rewrite //= | ]. + unfold Vector.shiftin; fold @Vector.shiftin. + rewrite to_list_cons cons_length IHv; lia. + Qed. + + Lemma last_shiftin {A N} (v : Vector.t A N) (def e : A) : + last (Vector.to_list (Vector.shiftin e v)) def = e. + Proof. + induction v; [ rewrite //= | ]. + unfold Vector.shiftin; fold @Vector.shiftin. + rewrite to_list_cons //=. + destruct (Vector.to_list (Vector.shiftin e v)) eqn:Hbug; + [ contradict Hbug; induction v; simpl; done | ]. + done. + Qed. + + Import Memory.Properties BvectorNotations. + Open Scope Bvector_scope. + + Lemma Bv2N_upper_bound_nat {n : nat} (bv : Bvector n) : + (N.to_nat (Bv2N bv) < (Nat.pow 2 n)). + Proof. + induction bv; [ by simpl | ]; destruct h; rewrite Bv2N_cons. + { rewrite N.succ_double_spec. + set z := Bv2N _; fold z in IHbv. + rewrite N2Nat.inj_add N2Nat.inj_mul. + vm_compute (N.to_nat 1); vm_compute (N.to_nat 2). + assert ((2 * N.to_nat z)%coq_nat = (2 * N.to_nat z)%nat); try done; rewrite H; clear H. + assert ((2 * N.to_nat z + 1)%coq_nat = (2 * N.to_nat z + 1)%nat); try done; rewrite H; clear H. + apply ltn_mul_add1 in IHbv. + rewrite Nat.pow_succ_r; [ | apply /leP; by rewrite leq0n ]. + assert ((2 * (2 ^ n))%coq_nat = (2 * (2 ^ n))%nat); try done; rewrite H; clear H. } + { rewrite N.double_spec N2Nat.inj_mul; set z := Bv2N _; fold z in IHbv; vm_compute (N.to_nat 2). + assert ((2 * N.to_nat z)%coq_nat = (2 * N.to_nat z)%nat); try done; rewrite H; clear H. + have aux : (0 < 2); [ done | ]. + have H := (ltn_pmul2l aux); rewrite -H in IHbv. + rewrite Nat.pow_succ_r; [ | apply /leP; by rewrite leq0n ]; clear H. + assert ((2 * (2 ^ n))%coq_nat = (2 * (2 ^ n))%nat); try done; rewrite H; clear H. + } + Qed. + + Lemma size_nat_sub_leq {n} (a b : Bvector n): + N.le (Bv2N b) (Bv2N a) -> + N.size_nat (Bv2N a - Bv2N b) <= n. + Proof. + intros; apply /leP; apply N.size_nat_le. + specialize (@Bv2N_upper_bound_nat n a) as Ha. + specialize (@Bv2N_upper_bound_nat n b) as Hb. + destruct (Bv2N b) eqn:Hb0, (Bv2N a) eqn:Ha0; try discriminate. + { simpl in *. by apply to_nat_lt_pow. } + { rewrite N.sub_0_r; by apply to_nat_lt_pow in Ha. } + { by contradict H. } + { apply to_nat_lt_pow in Ha,Hb. + apply (N.lt_trans (N.pos p0 - N.pos p) (N.pos p0) (N.pow 2 (N.of_nat n))); [ | done]. + apply N.sub_lt; done. + } + Qed. + + Lemma Bv_eq_translation {n} (a b : Bvector n) : + (nat_of_bin (Bv2N a) = nat_of_bin (Bv2N b)) -> + (Bv2N a = Bv2N b)%N. + Proof. lia. Qed. + + Lemma Bv_ltn_translation {n} (a b : Bvector n) : + (nat_of_bin (Bv2N a) < nat_of_bin (Bv2N b)) -> + (Bv2N a < Bv2N b)%N. + Proof. lia. Qed. + + Lemma BVEq_iff_eq {N} (a b : Bvector N) : + (a =? b) = true <-> a = b. + Proof. + split; intros. + { specialize VectorEq.eqb_eq with (A_beq := Bool.eqb) (v1 := a) (v2 := b) as HH. + unfold BVeq in H. + apply HH in H; [exact H | exact Bool.eqb_true_iff ]. + } + unfold BVeq. + apply VectorEq.eqb_eq; [exact Bool.eqb_true_iff | exact H ]. + Qed. + + Lemma BVEq_iff_neq {N} (a b : Bvector N) : + (a =? b) = false <-> a <> b. + Proof. + split; intros. + { rewrite <- BVEq_iff_eq. + destruct (a =? b) eqn:Heq; done. } + destruct (a =? b) eqn:Heq; [ | done]. + apply BVEq_iff_eq in Heq; by rewrite Heq in H. + Qed. + + Lemma BV_neq_cons {n} (a : bool) (x y: Bvector n) : + x <> y -> ((a :: x)%vector) <> ((a :: y) %vector). + Proof. + intros; rewrite -(VectorEq.eqb_eq bool Bool.eqb) //=; [ | exact Bool.eqb_true_iff]. + rewrite eqb_reflx andb_true_l. + apply BVEq_iff_neq in H. + rewrite /BVeq in H; by rewrite H. + Qed. + + Lemma bv_neq_sym {n} (a b : Vector.t bool n): + a <> b -> b <> a. + Admitted. + + Lemma N2Bv_sized_N2Bv_sized_p1 x y n: + N2Bv_sized n x <> N2Bv_sized n y -> + N2Bv_sized n.+1 x <> N2Bv_sized n.+1 y. + Proof. + intros. + destruct x,y; simpl; intros; try done; + destruct p eqn:hp; simpl; try done; try destruct p0; try done; apply BV_neq_cons. + all: try apply P2Bv_nonzero; simpl. + all: try apply bv_neq_sym. + all: try apply P2Bv_nonzero; simpl. + Admitted. + + (* Should follow from N2Bv_sized_neq_iff *) + Lemma N2Bv_sized_neq_succ (n : nat) (x : N) : + n > 0 -> N2Bv_sized n (N.succ x) <> N2Bv_sized n x. + Proof. + intros Hgt0; induction n; [by [] | ]. + rewrite ltnS leq_eqVlt in Hgt0; move: Hgt0 => /orP [/eqP Heq0 | Hgt0]. + { rewrite -Heq0; destruct x; try destruct p; simpl; done. } + apply IHn in Hgt0; by apply N2Bv_sized_N2Bv_sized_p1. + Qed. + + Lemma N2Bv_sized_eq_p1_false {W} (v : Bvector W): + W > 0 -> N2Bv_sized W (Bv2N v + 1) =? v = false. + Proof. + intros; apply BVEq_iff_neq. + rewrite N.add_1_r. + specialize (N2Bv_sized_Bv2N W v) as H0; rewrite -{2}H0. + by apply N2Bv_sized_neq_succ. + Qed. + + (* Check the eqseq_cons proof *) + Lemma cons_eq {n} (x : bool) (a b : Vector.t bool n): + (x :: a)%vector =? (x :: b)%vector -> + BVeq n n a b. + Proof. + intros H; apply BVEq_iff_eq in H. + rewrite /BVeq. + Admitted. + + Lemma Bvector_wrap {W} (v : Bvector W) : + W > 0 -> N2Bv_sized W (Bv2N (N2Bv_sized W (Bv2N v + 1)) + 1) =? v -> + W = 1. + Proof. + intros Hpos H. + induction v; intros; try discriminate. + rewrite ltnS leq_eqVlt in Hpos; move: Hpos => /orP [/eqP Heq | Hpos]; + [ by subst n | ]. + apply (IHv) in Hpos as IH; clear IHv. + 2: { + destruct h; simpl in H; [ + rewrite N.succ_double_succ N2Bv_sized_double Bv2N_cons N.double_succ_double + N2Bv_sized_succ_double N2Bv_sized_Bv2N in H | + rewrite N.double_succ_double N2Bv_sized_succ_double Bv2N_cons N.succ_double_succ + N2Bv_sized_double N2Bv_sized_Bv2N in H ]; + apply cons_eq in H; + specialize (@N2Bv_sized_eq_p1_false n v) as HH; apply HH in Hpos; + by rewrite Hpos in H. + } + revert H; generalize v; clear v; rewrite IH; intros. + simpl in H; destruct h; rewrite (Vector.eta v) in H; + specialize (@tl_0 bool v) as H0; rewrite H0 in H; + destruct (VectorDef.hd v); simpl in H; discriminate H. + Qed. + + Lemma N2Bv_sized_neq_iff: forall (n : nat) (x y : N), + N.size_nat x <= n -> + N.size_nat y <= n -> + x <> y <-> (N2Bv_sized n x <> N2Bv_sized n y). + Proof. + intros. + specialize N2Bv_sized_eq_iff with (n := n) (x := x) (y := y) as HH. + rewrite -HH; (try done || by apply /leP). + Qed. + + Lemma N2Bv_sized_neq_if : forall (n : nat) (x y : N), + (N2Bv_sized n x <> N2Bv_sized n y) -> x <> y. + Proof. + intros; destruct x,y; congruence. + Qed. + + Lemma N2Bv_sized_plusone_diff n (x : Bvector n) : + n > 0 -> N2Bv_sized n (Bv2N x + 1) <> x. + Proof. + intros Hpos. + specialize N2Bv_sized_Bv2N with (v := x) as H; rewrite -{2}H. + rewrite N.add_1_r. + by apply N2Bv_sized_neq_succ. + Qed. + + Lemma Cells_data_match {T W N I} (S : circuit_state (mem_cells T W N I)) (we : bool) wa wd wev : + (forall n, (wa =? n)%nat = false -> + indexConst wev n = CavaClass.constant false) -> + indexConst wev wa = CavaClass.constant we -> + Cells_read we wa wd S = snd (step (mem_cells T W N I) S (wd,wev)). + Proof. + intros Hwde Hwe. + induction N; [reflexivity | ]. + unfold mem_cells; fold mem_cells; unfold mem_cell. + repeat step_destruct. + rewrite (surjective_pairing (step (mem_cells _ _ _ _) SC3 _)) //=. + rewrite (surjective_pairing SC2) (surjective_pairing (fst SC2)) IHN. + destruct (wa =? N)%nat eqn:Hwa, we. + all: try ( + move : Hwa => /Nat.eqb_eq Hwa; subst N; rewrite Nat.sub_0_r Hwe; + simpl; cbv [eq_rect Util.computational_eq]; + destruct (Nat.eq_dec (S wa) (S wa)); [ | reflexivity]; + dependent destruction e; reflexivity + ). + all: rewrite Nat.sub_0_r (Hwde N Hwa); simpl; + cbv [eq_rect Util.computational_eq]; destruct (Nat.eq_dec N.+1 N.+1); [ | reflexivity]; + dependent destruction e; reflexivity. + Qed. + +End WithCava. \ No newline at end of file diff --git a/framework/CavaDRAM/_CoqProject b/framework/CavaDRAM/_CoqProject index c8848a9..8cb47d1 100644 --- a/framework/CavaDRAM/_CoqProject +++ b/framework/CavaDRAM/_CoqProject @@ -1,16 +1,19 @@ INSTALLDEFAULTROOT = CavaDRAM -R . CavaDRAM --R /home/felipe/PHD/repository/cleanup/sdram/framework/DRAM DRAM --R /home/felipe/PHD/tools/cava/silveroak/cava/Cava Cava --R /home/felipe/PHD/tools/cava/silveroak/third_party/coq-ext-lib/theories ExtLib --R /home/felipe/PHD/tools/cava/silveroak/third_party/bedrock2/deps/coqutil/src/coqutil coqutil +-R /home/felipe/PHD/repository/cleanup/sdram/framework/CoqDRAM CoqDRAM +-R /home/felipe/PHD/tools/cava/silveroakrecompiled/cava/Cava Cava +-R /home/felipe/PHD/tools/cava/silveroakrecompiled/third_party/coq-ext-lib/theories ExtLib +-R /home/felipe/PHD/tools/cava/silveroakrecompiled/third_party/bedrock2/deps/coqutil/src/coqutil coqutil +UtilSM.v +Util.v +Step.v +Memory.v CavaSystem.v CavaSubtractor.v CavaMemory.v CavaReqQueue.v +CavaReqQueueProperties.v CavaCommonInstances.v -CavaSM.v CavaFIFOREF.v -CavaTDMREF.v CavaSMExtraction.v \ No newline at end of file diff --git a/framework/CavaDRAM/backup.v b/framework/CavaDRAM/backup.v new file mode 100644 index 0000000..afe832f --- /dev/null +++ b/framework/CavaDRAM/backup.v @@ -0,0 +1,1256 @@ +Set Printing Projections. +Set Warnings "-notation-overridden,-parsing". + +From CavaDRAM Require Import CavaFIFOREF CavaSM CavaReqQueue CavaCommonInstances CavaSubtractor Step CavaSystem Memory Util UtilSM. +From CoqDRAM Require Import FIFO. +From Coq Require Import Program BinaryString HexString NArith. +From Cava Require Import Cava CavaProperties Util.Vector Util.Tactics. +From mathcomp Require Import fintype ssrZ zify ring. + +Section CavaFIFOREFProperties. + (* From Cava *) + Existing Instance CombinationalSemantics. + (* From CavaDRAM*) + Context {CAVA_SYS : CavaSystem}. + (* From CoqDRAM *) + Existing Instance REQESTOR_CFG. + Context {SYS_CFG : System_configuration}. + Context {FIFO_CFG : FIFO_configuration}. + Context {HAF : HW_Arrival_function_t}. + Existing Instance ARBITER_CFG. + Existing Instance FIFO_implementation. + + Import Memory.Properties BvectorNotations. + Open Scope Bvector_scope. + + Lemma leq_Nle (a b : N) : + leq (nat_of_bin a) (nat_of_bin b) -> (a <= b)%N. + Proof. + lia. + Qed. + + Lemma ltn_Ntn (a b : N) : + leq (S (nat_of_bin a)) (nat_of_bin b) -> (a < b)%N. + Proof. + lia. + Qed. + + Lemma Bv2N_upper_bound {n : nat} (bv : Bvector n) : + (N.to_nat (Bv2N bv) < (Nat.pow 2 n)). + Proof. + induction bv; [ by simpl | ]; destruct h; rewrite Bv2N_cons. + { rewrite N.succ_double_spec. + set z := Bv2N _; fold z in IHbv. + rewrite N2Nat.inj_add N2Nat.inj_mul. + vm_compute (N.to_nat 1); vm_compute (N.to_nat 2). + assert ((2 * N.to_nat z)%coq_nat = (2 * N.to_nat z)%nat); try done; rewrite H; clear H. + assert ((2 * N.to_nat z + 1)%coq_nat = (2 * N.to_nat z + 1)%nat); try done; rewrite H; clear H. + apply ltn_mul_add1 in IHbv. + rewrite Nat.pow_succ_r; [ | apply /leP; by rewrite leq0n ]. + assert ((2 * (2 ^ n))%coq_nat = (2 * (2 ^ n))%nat); try done; rewrite H; clear H. } + { rewrite N.double_spec N2Nat.inj_mul; set z := Bv2N _; fold z in IHbv; vm_compute (N.to_nat 2). + assert ((2 * N.to_nat z)%coq_nat = (2 * N.to_nat z)%nat); try done; rewrite H; clear H. + have aux : (0 < 2); [ done | ]. + have H := (ltn_pmul2l aux); rewrite -H in IHbv. + rewrite Nat.pow_succ_r; [ | apply /leP; by rewrite leq0n ]; clear H. + assert ((2 * (2 ^ n))%coq_nat = (2 * (2 ^ n))%nat); try done; rewrite H; clear H. + } + Qed. + + Lemma N2Bv_sized_queuemax_neq0 : + N2Bv_sized ADDR_WIDTH 0 <> N2Bv_sized ADDR_WIDTH (N.of_nat QUEUE_MAX_SIZE - 1). + Proof. + apply N2Bv_sized_neq_iff; unfold ADDR_WIDTH. + { rewrite /N.size_nat /Nat.log2 //=. } + { rewrite -N.pred_sub -Nat2N.inj_pred. + apply /leP; apply N.size_nat_le_nat. + rewrite QUEUE_MAX_SIZE_PW2; apply /leP. + rewrite ltn_predL; apply /leP. + exact QUEUE_MAX_SIZE_GT_0. } + { rewrite -N.pred_sub -Nat2N.inj_pred. + specialize QUEUE_MAX_SIZE_DIFF_0 as HH. + move: HH => /N.eqb_spec HH. + by apply /N.eqb_spec. + } + Qed. + + Definition mem_cells_ := + mem_cells (Vec Bit REQUEST_WIDTH) ADDR_WIDTH (Nat.pow 2 ADDR_WIDTH) InitMem. + + (* Check VectorDef.nth. *) + Lemma nth_cells_read {T W I} (ad : Bvector W) c_req + (c : circuit_state (mem_cells T W (2 ^ W) I)) : + VectorDef.nth (Cells_read true (N.to_nat (Bv2N ad)) c_req c) (Bv2Fin ad) = c_req. + Proof. + (* Induction had to be on N *) + induction W. + { simpl in c; destruct_products; simpl. + apply Vector.case0 with (v := ad); rewrite //=. } + { specialize (Vector.eta ad) as HH; rewrite HH //=. + simpl in c. + destruct (Vector.hd ad). + { specialize (IHW (Vector.tl ad)). + rewrite /Bv2Fin //=. + set Hc := Nat.add _ _. + dependent destruction Hc; admit. + } + } + Admitted. + + Lemma memcell_nch (c: circuit_state mem_cells_) wra rda c_req: + wra <> rda -> + (Cells_data c)[@(Bv2Fin rda)] = (Cells_read true (N.to_nat (Bv2N wra)) c_req c)[@(Bv2Fin rda)]. + Proof. + intros Hdiff. + unfold mem_cells_ in c. + set Hc := 2 ^ ADDR_WIDTH; dependent induction Hc. + { apply Logic.eq_sym in x; simpl in x. + admit. (* can't happen *) + } + specialize (IHHc HAF0 FIFO_CFG0 CAVA_SYS c wra rda c_req). + apply Logic.eq_sym in x. + Admitted. + + Lemma to_nat_lt_of_nat (a : N) (n : nat) : + N.to_nat a < n -> (a < N.of_nat n)%N. + Proof. + intros. + induction n; [ discriminate | ]. + rewrite leq_eqVlt in H; move: H => /orP [/eqP H | H]. + { rewrite -H Nat2N.inj_succ N2Nat.id; by specialize (N.lt_succ_diag_r a). } + assert (N.to_nat a < n). + { specialize (ltn_add2r 1 (N.to_nat a) n) as S; rewrite !addn1 in S; by rewrite S in H. } + apply IHn in H0. + apply N.lt_trans with (m := N.of_nat n); [ done | ]. + rewrite Nat2N.inj_succ; by specialize (N.lt_succ_diag_r (N.of_nat n)). + Qed. + + Lemma to_nat_lt_pow a b: + N.to_nat a < Nat.pow 2 b -> (a < 2 ^ N.of_nat b)%N. + Proof. + intros; apply to_nat_lt_of_nat in H. + rewrite -Nat2N.inj_pow in H. + by simpl (N.of_nat 2) in H. + Qed. + + Lemma size_nat_sub_leq {n} (a b : Bvector n): + (Bv2N b <= Bv2N a)%N -> + N.size_nat (Bv2N a - Bv2N b) <= n. + Proof. + intros; apply /leP; apply N.size_nat_le. + specialize (@Bv2N_upper_bound n a) as Ha. + specialize (@Bv2N_upper_bound n b) as Hb. + destruct (Bv2N b) eqn:Hb0, (Bv2N a) eqn:Ha0; try discriminate. + { simpl in *; by apply to_nat_lt_pow. } + { rewrite N.sub_0_r; by apply to_nat_lt_pow in Ha. } + { by contradict H. } + { apply to_nat_lt_pow in Ha,Hb. + apply (N.lt_trans (N.pos p0 - N.pos p) (N.pos p0) (2 ^ N.of_nat n)%N); [ | done]. + apply N.sub_lt; done. + } + Qed. + + (* Need a to be bigger than b *) + Lemma size_nat_qms_sub (a b: Bvector ADDR_WIDTH) : + (Bv2N b < Bv2N a)%N -> + N.size_nat (N.of_nat QUEUE_MAX_SIZE - (Bv2N a - Bv2N b)) <= ADDR_WIDTH. + Proof. + intros Hlt; apply /leP. + destruct (Bv2N b) eqn:Hb0, (Bv2N a) eqn:Ha0; try done; + apply N.size_nat_le; unfold ADDR_WIDTH; rewrite QUEUE_MAX_SIZE_PW2_N; try rewrite N.sub_0_r. + { apply N.sub_lt; [ | done]. + unfold ADDR_WIDTH in a,b. + specialize (@Bv2N_upper_bound (Nat.log2 QUEUE_MAX_SIZE) a) as Ha. + rewrite QUEUE_MAX_SIZE_PW2 in Ha. + rewrite Ha0 in Ha. + apply to_nat_lt_of_nat in Ha. + apply N.le_lteq; left; exact Ha. + } + { apply N.sub_lt; [ | apply N.lt_add_lt_sub_l; by rewrite N.add_0_r ]. + unfold ADDR_WIDTH in a,b. + specialize (@Bv2N_upper_bound (Nat.log2 QUEUE_MAX_SIZE) a) as Ha. + rewrite QUEUE_MAX_SIZE_PW2 in Ha. + specialize (@Bv2N_upper_bound (Nat.log2 QUEUE_MAX_SIZE) b) as Hb. + rewrite QUEUE_MAX_SIZE_PW2 in Hb. + apply to_nat_lt_of_nat in Ha,Hb; rewrite Ha0 in Ha; rewrite Hb0 in Hb. + apply N.le_sub_le_add_l; rewrite N.add_comm. + apply N.lt_trans with (m := N.of_nat (@QUEUE_MAX_SIZE CAVA_SYS)) (n := N.pos p0) + (p := N.add (N.of_nat (@QUEUE_MAX_SIZE CAVA_SYS)) (N.pos p)) in Ha as H; + [ apply N.le_lteq; by left | ]. + apply N.lt_add_pos_r; done. + } + Qed. + + Lemma size_nat_qms : + N.size_nat (N.of_nat QUEUE_MAX_SIZE - 1) <= Nat.log2 QUEUE_MAX_SIZE. + Proof. + rewrite N.sub_1_r -Nat2N.inj_pred. + apply /leP; apply N.size_nat_le_nat. + rewrite QUEUE_MAX_SIZE_PW2. + apply /ltP; rewrite ltn_predL; apply /ltP. + exact QUEUE_MAX_SIZE_GT_0. + Qed. + + Lemma N2Bv_sized_eq_p1_false {W} (v : Bvector W): + W > 0 -> (N2Bv_sized W (Bv2N v + 1) =? v) = false. + Proof. + intros; apply BVEq_iff_neq. + rewrite N.add_1_r. + specialize (N2Bv_sized_Bv2N W v) as H0; rewrite -{2}H0. + by apply N2Bv_sized_neq_succ. + Qed. + + Definition State_t := circuit_state FIFOSM. + + Definition get_mem (s : State_t) : circuit_state memqueue' := + let '(_,(_,(_,(_,_,_,memqueue_state,_,_,_,_,_),_),_,_)) := s in memqueue_state. + + Definition get_pop (s : State_t) := + let '(_,(_,_,_,pop)) := s in pop. + + Definition get_st (s : State_t) := + let '(_,(_,_,(_,(_,_,st)),_)) := s in st. + + Definition get_cnt (s : State_t) := + let '(_,(_,_,(_,(_,(_,_,cnt),_)),_)) := s in cnt. + + Definition get_cref (s : State_t) := + let '(_,(_,_,(_,(_,(_,(_,_,_,_,_,_,_,cref),_),_)),_)) := s in cref. + + Definition get_cr (s : State_t) := + let '(_,(_,_,(_,(_,(_,(_,(_,(_,cr)),_,_,_,_,_,_),_),_)),_)) := s in cr. + + Definition get_wra (s : State_t) := + let '(_,(_,(_,_,wra),_,_)) := s in wra. + + Definition get_rda (s : State_t) := + let '(_,(_,(_,(_,_,_,_,_,_,_,_,rda),_),_,_)) := s in rda. + + Definition get_reqqueue (s : State_t) : circuit_state RequestQueue' := + let '(_,(cs_requeue,_,_)) := s in cs_requeue. + + Definition get_mem_RequestQueue (c : circuit_state RequestQueue') := + let '(_,(_,(_,_, _,memqueue_state,_,_,_,_,_),_)) := c in memqueue_state. + + Definition get_addr_RequestQueue (c : circuit_state RequestQueue') := + let '(_,(_,(_,_, _,_,_,_,_,_,rda),wra)) := c in (wra,rda). + + Definition get_memcells (s : circuit_state memqueue') := + let '(_,memcells_state,_) := s in memcells_state. + + Definition get_memcells_RequestQueue (c : circuit_state RequestQueue') := + get_memcells (get_mem_RequestQueue c). + + (* --------------------------Bounding the counter ------------------- *) + Lemma cnt_bounded (cnt : Bvector COUNTER_WIDTH) : + N.to_nat (Bv2N cnt) < WAIT. + Proof. + specialize @Bv2N_upper_bound with (bv := cnt) as H. + by rewrite /COUNTER_WIDTH WAIT_PW_2 in H. + Qed. + + Definition Bv2cnt (cnt : Bvector COUNTER_WIDTH) : Counter_t := + Ordinal (cnt_bounded cnt). + + Definition cnt2Bv (cnt : Counter_t) := + N2Bv_sized COUNTER_WIDTH (N.of_nat (nat_of_ord cnt)). + (* ------------------------------------------------------------------ *) + + (* --------------------------Bounding cref counter ------------------- *) + Lemma cref_bounded (cref : Bvector COUNTER_REF_WIDTH) : + N.to_nat (Bv2N cref) < WAIT_REF. + Proof. + specialize @Bv2N_upper_bound with (bv := cref) as H. + by rewrite /COUNTER_REF_WIDTH WAIT_REF_PW2 in H. + Qed. + + Definition Bv2cref (cnt : Bvector COUNTER_REF_WIDTH) : Counter_ref_t := + Ordinal (cref_bounded cnt). + + Definition cref2Bv (cref : Counter_ref_t) := + N2Bv_sized COUNTER_REF_WIDTH (N.of_nat (nat_of_ord cref)). + (* ------------------------------------------------------------------ *) + + Lemma cref_preadate_false (c : Counter_ref_t) : + (cref2Bv c =? CNT_REF_PREA) = false -> + (nat_of_ord c == PREA_date - 1) = false. + Proof. + unfold cref2Bv, CNT_REF_PREA; intros. + apply BVEq_iff_neq in H; rewrite bitvec_literal_correct in H. + apply N2Bv_sized_neq_if in H. + apply of_nat_neq in H. + by apply /eqP. + Qed. + + Lemma cref_preadate_true (c : Counter_ref_t) : + (cref2Bv c =? CNT_REF_PREA) = true -> + (nat_of_ord c == PREA_date - 1) = true. + Proof. + unfold cref2Bv, CNT_REF_PREA; intros. + apply BVEq_iff_eq in H; rewrite bitvec_literal_correct in H. + apply N2Bv_sized_eq_iff in H. + { apply Nat2N.inj in H; rewrite H; by apply /eqP. } + { apply N.size_nat_le_nat. + destruct c; simpl in *; rewrite /COUNTER_REF_WIDTH; apply /ltP. + by rewrite WAIT_REF_PW2. } + { apply N.size_nat_le_nat; unfold COUNTER_REF_WIDTH. + rewrite WAIT_REF_PW2 subn1; apply /ltP. + specialize WAIT_REF_PREA_date as HH. + apply ltn_trans with (m := PREA_date.-1) in HH; [ exact HH | ]. + by rewrite ltn_predL PREA_date_pos. + } + Qed. + + Definition fullQueue (wa ra : Bvector ADDR_WIDTH) : bool := + let waN := Bv2N wa in + let raN := Bv2N ra in + let qms := N.sub (N.of_nat QUEUE_MAX_SIZE) 1 in + if (raN <= waN)%nat then ((Bv2N wa - Bv2N ra)%N == qms) + else (((N.add qms 1) - (raN - waN))%N == qms). + + Hypothesis HaltIfFull : forall t c, + let wra := get_wra c in + let rda := get_rda c in + if (HW_Arrival_at t != []) then ~~ fullQueue wra rda else true. + + Program Definition EqReq (r : Request_t) (r' : Bvector REQUEST_WIDTH) : bool. + Admitted. + + Lemma EqReqNil : EqReq nullreq REQUEST_NIL = true. + Admitted. + + (* Change FIFO implememtation: set of requests of max size 1, + so it could either have a request or a non arriving request, + that way, eveyr request in P is a valid request + would have to change lots of things here: + - HaltIfFull + - EqQueue + - EqMem + *) + + (* Manually force push to be false *) + + (* Definition EqArrival r r' push c : bool := + let wra := get_wra c in + let rda := get_rda c in + if r == nullreq + (* If the arriving request is nullreq, either the fifo is full or there are no arriving requests *) + then (r' =? REQUEST_NIL) && (push == false) + (* If a request did arrive indeed than the fifo is not full *) + else (EqReq r r') && (push == true) && (~~ fullQueue wra rda). *) + + Definition EqCmd (f_cmd : Command_kind_t) (c_cmd : Bvector DRAM_CMD_WIDTH) : bool := + match f_cmd with + | ACT => (c_cmd =? ACT_VEC) + | PRE => (c_cmd =? PRE_VEC) + | PREA => (c_cmd =? PREA_VEC) + | CRD => (c_cmd =? RD_VEC) + | CWR => (c_cmd =? WR_VEC) + | REF => (c_cmd =? REF_VEC) + | NOP => (c_cmd =? NOP_VEC) + end. + + Fixpoint EqQueue (P : Requests_t) (wra rda : Bvector ADDR_WIDTH) := + match P with + | [::] => (wra =? rda) + | x :: x0 => + if (x0 == []) then + (N2Bv_sized ADDR_WIDTH (Bv2N rda + 1) =? wra) + else + negb (wra =? rda) && (EqQueue x0 wra (N2Bv_sized ADDR_WIDTH (Bv2N rda + 1))) + end. + + + if (x == nullreq) then (EqQueue x0 wra rda) + else (if (x0 == []) then + (N2Bv_sized ADDR_WIDTH (Bv2N rda + 1) =? wra) (* only one non-null addres in the queue *) + else + negb (wra =? rda) && (EqQueue x0 wra (N2Bv_sized ADDR_WIDTH (Bv2N rda + 1))) + ) + end. + + Fixpoint EqMem_ {W} (P : Requests_t) (rda : Bvector W) + (memcells_vec : Vector.t (Bvector REQUEST_WIDTH) (Nat.pow 2 W)) : bool := + match P with + | [::] => true + | x :: x0 => let nrda := N2Bv_sized W (Bv2N rda + 1) in + if (x == nullreq) then + (EqMem_ x0 rda memcells_vec) + else + (EqReq x memcells_vec[@(Bv2Fin rda)]) && (EqMem_ x0 nrda memcells_vec) + end. + + Lemma EqMem_rcons r1 (rda wra : Bvector ADDR_WIDTH) c R (c_req : combType (Vec Bit REQUEST_WIDTH)) : + EqQueue r1 wra rda -> r1 != [::] -> + EqMem_ r1 rda (@Cells_data (Vec Bit REQUEST_WIDTH) ADDR_WIDTH (Nat.pow 2 ADDR_WIDTH) InitMem c) -> + EqReq R c_req -> + EqMem_ (r1 ++ [R])%SEQ rda (Cells_read true (N.to_nat (Bv2N wra)) c_req c). + Proof. + intros HQ Hnot_nil Mem EqR; fold mem_cells_ in c; rewrite cats1. + revert Mem HQ Hnot_nil; generalize wra rda; induction r1; try discriminate; intros. + simpl in Mem,HQ; simpl; destruct (a == _) eqn:Hanull. + { destruct r1 eqn:Hr1; simpl in Mem,HQ. + { clear IHr1 Mem. + simpl; destruct (R == _); [trivial | rewrite andb_true_r]. + apply BVEq_iff_eq in HQ; rewrite -HQ. + by rewrite (@nth_cells_read (Vec Bit REQUEST_WIDTH) ADDR_WIDTH InitMem wra0 c_req c). + } + { apply IHr1 with (wra := wra0) (rda := rda0) in HQ; done. } + } + move: Mem => /andP [EqR_ Mem]; apply /andP; split. + { destruct r1 eqn:hr1; simpl in HQ,Mem; simpl. + { destruct (wra0 =? rda0) eqn:Heq. + { apply BVEq_iff_eq in Heq; rewrite Heq in HQ. + specialize ADDR_WIDTH_pos as H0; move: H0 => /ltP H0. + apply N2Bv_sized_eq_p1_false with (v := rda0) in H0; by rewrite H0 in HQ. + } + { apply BVEq_iff_neq in Heq. + rewrite -memcell_nch; done. }} + { move: HQ => /andP [neq HQ]. + destruct (r == _),l. + all: move: neq => /negPf neq; apply BVEq_iff_neq in neq; rewrite -memcell_nch; done. }} + { destruct r1 eqn:hr1; simpl in HQ,Mem; simpl. + { destruct (R == _); [trivial | rewrite andb_true_r]. + apply BVEq_iff_eq in HQ; rewrite HQ. + by rewrite (@nth_cells_read (Vec Bit REQUEST_WIDTH) ADDR_WIDTH InitMem wra0 c_req c). + } + { move: HQ => /andP [neq HQ]. + specialize (IHr1 wra0 (N2Bv_sized ADDR_WIDTH (Bv2N rda0 + 1))); apply IHr1; try done. } + } + Qed. + + (* Just use the circuit directly <-> circuit does the work directly *) + Definition EqMem (P : Requests_t) rda (mem : circuit_state RequestQueue') := + let memcells_vec := Cells_data (get_memcells_RequestQueue mem) in + EqMem_ P rda memcells_vec. + + Definition State_Eq (fram_state : FIFO_state_t) (cava_state : State_t) : bool := + let s := get_st cava_state in + let c' := get_cnt cava_state in + let cref' := get_cref cava_state in + let r' := get_cr cava_state in + let RQ := get_reqqueue cava_state in + let wra := fst (get_addr_RequestQueue RQ) in + let rda := snd (get_addr_RequestQueue RQ) in + let pop := get_pop cava_state in + match fram_state with + | IDLE c cref P => + (s =? STATE_IDLE_VEC) && (c' =? cnt2Bv c) && (cref' =? cref2Bv cref) && (EqMem P rda RQ) && + (EqQueue P wra rda) && (pop == false) + | RUNNING c cref P r => + (s =? STATE_RUN_VEC) && (c' =? cnt2Bv c) && (cref' =? cref2Bv cref) && (EqMem P rda RQ) && + (EqQueue P wra rda) && (EqReq r r') && (pop == (c == OCycle0)) + | REFRESHING cref P => + (s =? STATE_REF_VEC) && (cref' =? cref2Bv cref) && (EqMem P rda RQ) && + (EqQueue P wra rda) && (pop == false) + end. + + (* -------------- Proofs about CmdGen ------------------------------- *) + Lemma CmdGen_equiv_idle_to_idle (c : circuit_state CmdGen) cnt cref: + (cref =? CNT_REF_PREA) = false -> + exists c', step CmdGen c (STATE_IDLE_VEC,true,cnt,cref,REQUEST_NIL) = + (c',NOP_VEC). + Proof. + intros H; simpl in c; destruct_products. + eapply ex_intro. + cbv [CmdGen]; cbn [step fst snd]. + simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + fast_simpl_bool; simpl. + cbv [CrefPREA_eq]. + apply BVEq_iff_neq in H. + specialize @CavaPreludeProperties.eqb_neq with (t := Vec Bit (@COUNTER_REF_WIDTH SYS_CFG FIFO_CFG)) as HH. + apply HH in H; rewrite H VectorSpec.map_id; reflexivity. + Qed. + + Lemma CrefPREA_lt_CNT_REF_PREA: + CrefPREA_lt CNT_REF_PREA = false. + Proof. + cbv [CrefPREA_lt]; simpl_ident. + unfold greaterThanOrEqual; simpl_ident; unfold greaterThanOrEqualBool. + apply /negbF. + rewrite {1}/CNT_REF_PREA; rewrite !bitvec_literal_correct. + apply /N.leb_spec0; rewrite /CNT_REF_PREA /CNT_REF_WAIT !bitvec_literal_correct. + rewrite !Bv2N_N2Bv_sized. { apply N.le_add_r. } + all: rewrite /COUNTER_REF_WIDTH WAIT_REF_PW_N. + all: try apply N_lt_inj. + all: specialize WAIT_REF_PREA_date_WAIT as H; lia. + Qed. + + Lemma CmdGen_equiv_idle_to_ref (c : circuit_state CmdGen) cnt cref e: + (cref =? CNT_REF_PREA) = true -> + exists c', step CmdGen c (STATE_IDLE_VEC,e,cnt,cref,REQUEST_NIL) = (c',PREA_VEC). + Proof. + intros; simpl in c; destruct_products; eapply ex_intro. + cbv [CmdGen]; cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + fast_simpl_bool; simpl; rewrite VectorSpec.map_id. + apply BVEq_iff_eq in H; subst cref; rewrite CrefPREA_lt_CNT_REF_PREA !VectorSpec.map_id. + rewrite andb_false_r; rewrite /CrefPREA_eq. + specialize @CavaPreludeProperties.eqb_eq with (t := Vec Bit (@COUNTER_REF_WIDTH SYS_CFG FIFO_CFG)) as HH. + assert (CNT_REF_PREA = CNT_REF_PREA); [done | ]; apply HH in H; by rewrite H. + Qed. + (* ------------------------------------------------------------------ *) + + (* -------------- Proofs about NextCR ------------------------------- *) + Lemma NextCR_equiv (c : circuit_state NextCR) cnt cref tr: + exists c', step NextCR c (STATE_IDLE_VEC,true,cnt,cref,tr) = + (c',REQUEST_NIL). + Proof. + simpl in c; destruct_products. + eapply ex_intro. + cbv [NextCR LoopInit]; cbn [step fst snd]. + simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + fast_simpl_bool; by simpl. + Qed. + + Lemma NextCR_equiv_IDLE_NE_PREA c cnt cref tr: + (cref =? CNT_REF_PREA) = true -> + exists c', step NextCR c (STATE_IDLE_VEC,false,cnt,cref,tr) = + (c',REQUEST_NIL). + Proof. + intros; simpl in c; destruct_products; eapply ex_intro. + cbv [NextCR LoopInit]; cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + rewrite negb_false andb_true_l; rewrite /Srun //= VectorSpec.map_id. + apply BVEq_iff_eq in H; subst cref. + by rewrite CrefPREA_lt_CNT_REF_PREA. + Qed. + (* ------------------------------------------------------------------ *) + + Create HintDb update. + Lemma Sidle_true : + Sidle STATE_IDLE_VEC = true. + Proof. + apply CavaPreludeProperties.eqb_refl. + Qed. + Hint Rewrite @Sidle_true : update. + + Lemma Sref_idle_false : + Sref STATE_IDLE_VEC = false. + Proof. + by apply CavaPreludeProperties.eqb_neq. + Qed. + Hint Rewrite @Sref_idle_false : update. + + Lemma cnt_equiv (cnt : Bvector COUNTER_WIDTH) : + (if CeqWAIT cnt then Bvect_false COUNTER_WIDTH + else N2Bv_sized COUNTER_WIDTH (Bv2N cnt + 1)) = cnt2Bv (Next_cycle (Bv2cnt cnt)). + Proof. + cbv [CeqWAIT]. + destruct (CavaPrelude.eqb (cnt, CNT_WAIT)) eqn:Heq; rewrite Heq. + { specialize @CavaPreludeProperties.eqb_eq with (t := Vec Bit COUNTER_WIDTH) (x := cnt) as H. + apply H in Heq; clear H. + unfold Next_cycle; set (Hc := (Bv2cnt cnt).+1 < WAIT); dependent destruction Hc; + apply Logic.eq_sym in x; move : Logic.eq_refl; rewrite {2 3} x; simpl; intro. + { rewrite /CNT_WAIT bitvec_literal_correct in Heq. + rewrite Heq /Bv2cnt //= Bv2N_N2Bv_sized in x. + 2: { + rewrite /COUNTER_WIDTH; have id := (N2Nat.id 2). + rewrite -id Nat2N.inj_pow //= /Pos.to_nat //= WAIT_PW_2. + apply: N_lt_inj; apply /ltP; by rewrite subn1 ltn_predL WAIT_pos. + } + rewrite Nat2N.id subn1 prednK in x; [ | exact WAIT_pos ]; by rewrite ltnn in x. + } + { unfold cnt2Bv,OCycle0; by simpl. }} + { unfold Next_cycle; set (Hc := (Bv2cnt cnt).+1 < WAIT); dependent destruction Hc; + apply Logic.eq_sym in x; move : Logic.eq_refl; rewrite {2 3} x; simpl; intro. + { unfold cnt2Bv; apply f_equal; simpl. + rewrite N.add_1_r -(N.succ_pos_pred (Pos.of_succ_nat (N.to_nat (Bv2N cnt)))). + apply f_equal; by rewrite predN_of_succ_nat. } + { apply ltn_gt in e,x. + rewrite leq_eqVlt in e; move: e => /orP [/eqP e | e]. + { have HH := (@eqb_iff_neq (Vec Bit (@COUNTER_WIDTH SYS_CFG FIFO_CFG))). + apply HH in Heq. rewrite /CNT_WAIT bitvec_literal_correct in Heq; + rewrite -(N2Bv_sized_Bv2N (@COUNTER_WIDTH SYS_CFG FIFO_CFG) cnt) in Heq. + apply N2Bv_sized_neq_if in Heq. + by rewrite e subn1 -pred_Sn N2Nat.id in Heq. } + { specialize ltn_ord with (n := @WAIT SYS_CFG FIFO_CFG) (i := Ordinal (cnt_bounded cnt)) as H. + rewrite //= in H. + contradict H; apply /negP; by rewrite -ltnNge. + } + } + } + Qed. + + Lemma cref_equiv (cref : Bvector COUNTER_REF_WIDTH) : + (if CrefPREA_eq cref then Bvect_false COUNTER_REF_WIDTH + else N2Bv_sized COUNTER_REF_WIDTH (Bv2N cref + 1)) = cref2Bv (Next_cycle_ref (Bv2cref cref)). + Admitted. + (* Proof. + cbv [CrefPREA_eq]. + destruct (CavaPrelude.eqb (cref, CNT_REF_PREA)) eqn:Hcref; rewrite Hcref. + { specialize @CavaPreludeProperties.eqb_eq with (t := Vec Bit COUNTER_REF_WIDTH) (x := cref) as H. + apply H in Hcref; clear H. + unfold Next_cycle_ref; set (Hc := (Bv2cref cref).+1 < WAIT_REF); dependent destruction Hc; + apply Logic.eq_sym in x; move : Logic.eq_refl; rewrite {2 3} x; simpl; intro. + { rewrite /CNT_REF_PREA bitvec_literal_correct in Hcref. + rewrite Hcref /Bv2cref //= Bv2N_N2Bv_sized in x. + 2: { + rewrite /COUNTER_REF_WIDTH; have id := (N2Nat.id 2). + rewrite WAIT_REF_PW_N. + (* rewrite -id Nat2N.inj_pow //=. *) + (* rewrite /Pos.to_nat //=. WAIT_REF_PW_N. *) + apply: N_lt_inj; apply /ltP. + rewrite subn1. + specialize WAIT_REF_PREA_date as H. + apply ltn_trans with (n := PREA_date); [ | exact WAIT_REF_PREA_date]. + by rewrite ltn_predL PREA_date_pos. + } + rewrite Nat2N.id subn1 prednK in x; [ | exact PREA_date_pos ]; by rewrite ltnn in x. + } + { unfold cref2Bv,OCycle0; by simpl. }} + { unfold Next_cycle_ref; set (Hc := (Bv2cref cref).+1 < PREA_date); dependent destruction Hc; + apply Logic.eq_sym in x; move : Logic.eq_refl; rewrite {2 3} x; simpl; intro. + { unfold cref2Bv; apply f_equal; simpl. + rewrite N.add_1_r -(N.succ_pos_pred (Pos.of_succ_nat (N.to_nat (Bv2N cref)))). + f_equal; by rewrite predN_of_succ_nat. } + { apply ltn_gt in e,x. + rewrite leq_eqVlt in e; move: e => /orP [/eqP e | e]. + { have HH := (@eqb_iff_neq (Vec Bit (@COUNTER_REF_WIDTH SYS_CFG))). + apply HH in Hcref. rewrite /CNT_REF_PREA bitvec_literal_correct in Hcref; + rewrite -(N2Bv_sized_Bv2N (@COUNTER_REF_WIDTH SYS_CFG) cref) in Hcref. + apply N2Bv_sized_neq_if in Hcref. + by rewrite e subn1 -pred_Sn N2Nat.id in Hcref. } + { specialize ltn_ord with (n := PREA_date) (i := Ordinal (cref_bounded cref)) as H. + rewrite //= in H. + contradict H; apply /negP; by rewrite -ltnNge. + } + } + } + Qed. *) + + (* -------------- Proofs about Update ------------------------------- *) + (* Don't try to match it with the next_cycle_ref, but rather something else *) + Lemma Update_equiv_idle_idle (c : circuit_state Update) cnt cref : + (cref =? CNT_REF_PREA) = false -> + let nc := cnt2Bv (Next_cycle (Bv2cnt cnt)) in + let ncref := N2Bv_sized COUNTER_REF_WIDTH (Bv2N cref + 1) in + snd (step Update c (STATE_IDLE_VEC,true,cnt,cref)) = + (STATE_IDLE_VEC,false,nc,ncref). + Proof. + intros Hcref Hcnt; simpl in c. + cbv [cnt2Bv]; unfold Hcnt; clear Hcnt. + cbv [Update Update_s Update_e Update_c Update_cref]. + cbn [step fst snd]; simpl_ident. + autorewrite with update; vm_compute (false && _). + apply BVEq_iff_neq in Hcref. + specialize @CavaPreludeProperties.eqb_neq with (t := Vec Bit (@COUNTER_REF_WIDTH SYS_CFG FIFO_CFG)) as HH. + apply pair_equal_spec; split. + 2: { + rewrite orb_false_l andb_true_l. + rewrite /CrefPREA_eq; apply HH in Hcref; by rewrite Hcref. + } + cbv [CrefPREA_eq]; apply HH in Hcref as Hcref'; rewrite Hcref'; + vm_compute (false || true && false); simpl; rewrite !VectorSpec.map_id andb_false_r. + apply pair_equal_spec; split; [ + apply pair_equal_spec; split; [ by unfold STATE_IDLE_VEC | reflexivity] | ]. + vm_compute (orb false false); rewrite orb_false_r; by specialize (cnt_equiv cnt). + Qed. + + Lemma Update_equiv_idle_ref (c : circuit_state Update) cnt cref e: + (cref =? CNT_REF_PREA) = true -> + let nc := cnt2Bv (Next_cycle (Bv2cnt cnt)) in + let ncref := CNT_REF_NIL in + exists c', (step Update c (STATE_IDLE_VEC,e,cnt,cref)) = + (c',(STATE_REF_VEC,false,nc,ncref)). + Proof. + intros Hcref Hcnt; simpl in c; eapply ex_intro. + cbv [cnt2Bv]; unfold Hcnt; clear Hcnt. + cbv [Update Update_s Update_e Update_c Update_cref]. + cbn [step fst snd]; simpl_ident. + apply pair_equal_spec; split; [reflexivity | ]. + autorewrite with update; vm_compute (false && _). + apply BVEq_iff_eq in Hcref. + specialize @CavaPreludeProperties.eqb_eq with (t := Vec Bit (@COUNTER_REF_WIDTH SYS_CFG FIFO_CFG)) as HH. + apply pair_equal_spec; split. + 2: { + rewrite orb_false_l andb_true_l. + rewrite /CrefPREA_eq; apply HH in Hcref; by rewrite Hcref. + } + cbv [CrefPREA_eq]; apply HH in Hcref as Hcref'; rewrite Hcref'; + vm_compute (false || true && false); simpl; rewrite !VectorSpec.map_id. + apply pair_equal_spec; split. + 2: { + vm_compute (orb false false); rewrite orb_false_r. + destruct e; [rewrite negb_true | rewrite negb_false]. + { rewrite andb_false_r orb_false_r; by specialize (cnt_equiv cnt). } + { rewrite andb_true_r. + destruct (CrefPREA_lt cref) eqn:Hbug. + { by rewrite Hcref CrefPREA_lt_CNT_REF_PREA in Hbug. } + { rewrite orb_false_r; by specialize (cnt_equiv cnt). } + } + } + apply pair_equal_spec; split; [ done | ]. + rewrite Hcref CrefPREA_lt_CNT_REF_PREA; by rewrite andb_false_l. + Qed. + (* ------------------------------------------------------------------ *) + + (* -------------- Proofs about FullEmptyLogic ------------------------------- *) + Lemma FEL_emp_equiv (c : circuit_state FullEmptyLogic) wra rda : + wra = rda -> exists c', step FullEmptyLogic c (wra,rda) = (c',(false,true)). + Proof. + intros H; eapply ex_intro. + cbv [FullEmptyLogic FullLogic EmptyLogic Subtractor subtractor dropr EqFULL FullVEC unpackV]; + cbn [step]; simpl_ret; cbn [fst snd]. + apply pair_equal_spec; split; [ reflexivity | ]. + apply pair_equal_spec; split; [ | by rewrite H CavaPreludeProperties.eqb_refl ]. + rewrite inv_correct; cbv [bind]. + rewrite fullAdder_cin; cbv [unpackV]; simpl_ret. + destruct (one) eqn:Hone; [ | discriminate]. + destruct ((Bv2N rda) <= (Bv2N wra)) eqn:Hleq; + [ | by rewrite H leqnn in Hleq ]. + assert (N.sub (Bv2N wra) (Bv2N rda) = 0%N); [ by rewrite H N.sub_diag | ]. + rewrite H0 !bitvec_literal_correct. + set (N := N.sub _ _). + specialize N2Bv_sized_queuemax_neq0 as H2. + specialize @CavaPreludeProperties.eqb_neq with (t := Vec Bit (@ADDR_WIDTH CAVA_SYS)) + (x := N2Bv_sized ADDR_WIDTH 0) (y := N2Bv_sized ADDR_WIDTH N) as HH. + by apply HH in H2. + Qed. + + Lemma FEL_nemp_wrap1_equiv (c : circuit_state FullEmptyLogic) (wra rda : Bvector ADDR_WIDTH) : + let wrap1 := N2Bv_sized ADDR_WIDTH (Bv2N wra + 1) in + wra = rda -> exists c' f', step FullEmptyLogic c (wrap1,rda) = (c',(f',false)). + Proof. + intros; repeat eapply ex_intro; unfold wrap1. + cbv [FullEmptyLogic FullLogic EmptyLogic Subtractor subtractor dropr EqFULL FullVEC unpackV]; + cbn [step]; simpl_ret; cbn [fst snd]. + apply pair_equal_spec; split; [ reflexivity | ]. + apply pair_equal_spec; split; [ reflexivity | ]. + apply CavaPreludeProperties.eqb_neq; rewrite H. + apply N2Bv_sized_plusone_diff; unfold ADDR_WIDTH. + specialize QUEUE_MAX_SIZE_GT_1 as HQ; apply Nat.log2_pos in HQ. + by move: HQ => /ltP HQ. + Qed. + + Lemma FEL_nemp_NF_equiv (c : circuit_state FullEmptyLogic) (wra rda : Bvector ADDR_WIDTH) : + ~~ (fullQueue wra rda) -> + wra <> rda -> exists c', step FullEmptyLogic c (wra,rda) = (c',(false,false)). + Proof. + intros NF H; eapply ex_intro. + rewrite /fullQueue in NF. + cbv [FullEmptyLogic FullLogic EmptyLogic Subtractor subtractor dropr EqFULL FullVEC unpackV]; + cbn [step]; simpl_ret; cbn [fst snd]. + apply pair_equal_spec; split; [ reflexivity | ]. + apply pair_equal_spec; split; [ | by apply CavaPreludeProperties.eqb_neq ]. + rewrite bitvec_literal_correct. + rewrite fullAdder_cin; destruct (one) eqn:Hbug; try discriminate; clear Hbug. + cbv [unpackV]. + destruct (_ <= _) eqn:Hleq; apply CavaPreludeProperties.eqb_neq. + { set (xx := (Bv2N wra - Bv2N rda)%N); fold xx in NF. + set (yy := ((N.of_nat QUEUE_MAX_SIZE - 1)%N)); fold yy in NF. + assert (N.size_nat xx <= ADDR_WIDTH); + [ apply size_nat_sub_leq; by apply leq_Nle in Hleq | ]. + assert (N.size_nat yy <= ADDR_WIDTH); + [ unfold ADDR_WIDTH, yy; by apply size_nat_qms | ]. + apply N2Bv_sized_neq_iff; try done; by apply /eqP. + } + { rewrite {3}/ADDR_WIDTH QUEUE_MAX_SIZE_PW2; apply N2Bv_sized_neq_iff. + { assert (Bv2N rda > Bv2N wra); [ lia | ]. + apply size_nat_qms_sub; by apply ltn_Ntn in H0. + } + { unfold ADDR_WIDTH; by apply size_nat_qms. } + specialize add_1_sub1 with (x := N.of_nat (@QUEUE_MAX_SIZE CAVA_SYS)) as HH. + rewrite HH in NF; [ | exact QUEUE_MAX_SIZE_GT_0_N]. + apply /eqP; exact NF. + } + Qed. + + Lemma FEL_NF_equiv (c : circuit_state FullEmptyLogic) (wra rda : Bvector ADDR_WIDTH) : + ~~ (fullQueue wra rda) -> + exists c' e', step FullEmptyLogic c (wra,rda) = (c',(false,e')). + Proof. + intros NF; unfold fullQueue in NF; repeat eapply ex_intro. + cbv [FullEmptyLogic]; cbn [step]; simpl_ret; cbn [fst snd]. + apply pair_equal_spec; split; [reflexivity | ]. + apply pair_equal_spec; split; [ | reflexivity ]. + cbv [dropr subtractor EqFULL FullVEC unpackV]; simpl_ident. + destruct ((Bv2N rda) <= (Bv2N wra)) eqn:Hleq; + destruct (one) eqn:Hone; try discriminate; + rewrite fullAdder_cin Hleq; + apply CavaPreludeProperties.eqb_neq; move: NF => /eqP NF. + { set (xx := (Bv2N wra - Bv2N rda)%N); fold xx in NF. + set (yy := ((N.of_nat QUEUE_MAX_SIZE - 1)%N)); fold yy in NF. + assert (N.size_nat xx <= ADDR_WIDTH); + [ apply size_nat_sub_leq; by apply leq_Nle in Hleq | ]. + assert (N.size_nat yy <= ADDR_WIDTH); + [ unfold ADDR_WIDTH, yy; by apply size_nat_qms | ]. + apply N2Bv_sized_neq_iff; try done; by apply /eqP. + } + { rewrite {3}/ADDR_WIDTH QUEUE_MAX_SIZE_PW2; apply N2Bv_sized_neq_iff. + { assert (Bv2N rda > Bv2N wra) as H; [ lia | ]. + apply size_nat_qms_sub; by apply ltn_Ntn in H. + } + { unfold ADDR_WIDTH; by apply size_nat_qms. } + specialize add_1_sub1 with (x := N.of_nat (@QUEUE_MAX_SIZE CAVA_SYS)) as HH. + by rewrite HH in NF; [ | exact QUEUE_MAX_SIZE_GT_0_N]. + } + Qed. + (* ------------------------------------------------------------------ *) + + Lemma incrn_pointr_true_equiv (c : circuit_state incr_pointr) ad : + step incr_pointr c (ad,true) = + (tt,N2Bv_sized ADDR_WIDTH (Bv2N ad + 1)). + Proof. + cbv [incr_pointr step] ; by simpl_ident. + Qed. + + Lemma incrn_pointr_false_equiv (c : circuit_state incr_pointr) ad : + step incr_pointr c (ad,false) = (tt,ad). + Proof. + cbv [incr_pointr step] ; by simpl_ident. + Qed. + + Create HintDb get_state. + Hint Unfold get_memcells : get_state. + Hint Unfold get_addr_RequestQueue : get_state. + Hint Unfold get_mem_RequestQueue : get_state. + Hint Unfold get_memcells_RequestQueue : get_state. + Hint Unfold get_mem : get_state. + + (* the not full could come either be satisfies from the not full hypothesis + or from wra = rda *) + Lemma RQ_fst_pushT_popF_NF (c : circuit_state RequestQueue') c_req : + let '(wra,rda) := get_addr_RequestQueue c in + let S := get_memcells_RequestQueue c in + let wra_idx := N.to_nat (Bv2N wra) in + let memcells_spec := Cells_read true wra_idx c_req S in + ~~ (fullQueue wra rda) -> exists c', + ((Cells_data (get_memcells_RequestQueue c') = memcells_spec) /\ + (fst (get_addr_RequestQueue c')) = (N2Bv_sized ADDR_WIDTH (Bv2N wra + 1)) /\ + (snd (get_addr_RequestQueue c')) = rda) /\ + fst (step RequestQueue' c (true,c_req,false)) = c'. + Admitted. + (* simpl in c; destruct_products. + unfold get_addr_RequestQueue; intros Hfull; eapply ex_intro; split; [ | reflexivity]. + set (p := step RequestQueue' _ _). + cbv [RequestQueue' LoopInit fork2] in p. + cbn [step] in p; cbn [fst snd] in p; simpl_ret_H p;z cbv [fst snd] in p. + specialize FEL_NF_equiv with (c := (u17, (u19, u20, u18), u16)) + (rda := t0) (wra := t) as H; apply H in Hfull; clear H. + destruct Hfull as [cs_FEL' [empty_o Hfull]]. + unfold p; clear p; rewrite Hfull. + cbn [fst snd bind inv and2 or2]; fast_simpl_bool. + rewrite (surjective_pairing (step memqueue' _ _)). + rewrite incrn_pointr_true_equiv incrn_pointr_false_equiv. + rewrite (surjective_pairing (step FullEmptyLogic _ _)). + set (fel := step FullEmptyLogic _ _). + split. + { simpl in fel; unfold fel; cbv [snd fst]. + cbv [get_memcells_RequestQueue get_mem_RequestQueue get_memcells]. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end. + cbv [memqueue' Memory' mem_write mem_read]; cbn [step fst snd]; simpl_ident; cbv [fst snd]. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end. + cbv [fst snd]. + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end. + fold mem_cells_. + specialize @Cells_matchX with (T := Vec Bit (@REQUEST_WIDTH CAVA_SYS)) + (W := @ADDR_WIDTH CAVA_SYS) (N := (Nat.pow 2 (@ADDR_WIDTH CAVA_SYS))) (I := InitMem) + (S0 := c) (we := true) (wd := c_req) (wa := (N.to_nat (Bv2N t))) as HH. + rewrite -HH; [reflexivity | | ]. + all: admit. + } + split; by simpl. + Admitted. *) + + (* Ignoring the full signal because it just goes to the output *) + Lemma RQ_snd_pushT_empty (c : circuit_state RequestQueue') c_req pop : + let '(wra,rda) := get_addr_RequestQueue c in + let S := get_memcells_RequestQueue c in + let rda_idx := N.to_nat (Bv2N rda) in + let wra_idx := N.to_nat (Bv2N wra) in + let memcells' := Cells_read true wra_idx c_req S in + let mem_val := nth_default (req_null) rda_idx memcells' in + wra = rda -> exists f', + snd (step RequestQueue' c (true,c_req,pop)) = (f',mem_val,true). + Admitted. + (* simpl in c; destruct_products; rename t0 into rda, t into wra. + autounfold with get_state; intros. + cbv [RequestQueue' LoopInit fork2]; simpl_ret; cbn [step fst snd]. + eapply FEL_emp_equiv with (c := (u17,(u19,u20,u18), u16)) in H as HH. + destruct HH as [cs_FEL HH]; rewrite HH. + cbn [fst snd bind inv and2 or2]. + rewrite (surjective_pairing (step memqueue' (u12,c,u11) _)). + cbv [fst snd]; fast_simpl_bool. + rewrite incrn_pointr_true_equiv if_same incrn_pointr_false_equiv; clear HH. + eapply FEL_nemp_wrap1_equiv with (c := (u4, (u6, u7, u5), u3)) in H as HH. + destruct HH as [cs_FELL [full_o HH]]; rewrite HH; clear HH. + eapply ex_intro. + apply pair_equal_spec; split; [ | reflexivity ]. + apply pair_equal_spec; split; [ reflexivity | ]. + cbv [memqueue' Memory' mem_write mem_read]. + cbn [step fst snd]; simpl_ret. + rewrite (surjective_pairing (step (mem_cells _ _ _ _) c _)). + specialize @Cells_data_match with (T := Vec Bit (@REQUEST_WIDTH CAVA_SYS)) + (W := @ADDR_WIDTH CAVA_SYS) (N := (Nat.pow 2 (@ADDR_WIDTH CAVA_SYS))) (I := InitMem) + (S0 := c) (we := true) (wa := (N.to_nat (Bv2N wra))) (wd := c_req) as HH. + rewrite -HH. + { cbv [indexAt indexConst defaultCombValue]. + cbv [unpackV bind]; simpl_ret. + rewrite nth_0; simpl; unfold req_null. + reflexivity. + } + all: admit. + Admitted. *) + + Lemma RQ_snd_pushT_popF_NF_nempty (c : circuit_state RequestQueue') c_req: + let '(wra,rda) := get_addr_RequestQueue c in + let S := get_memcells_RequestQueue c in + let rda_idx := N.to_nat (Bv2N rda) in + let wra_idx := N.to_nat (Bv2N wra) in + let memcells' := Cells_read true wra_idx c_req S in + let mem_val := nth_default (req_null) rda_idx memcells' in + ~~ (fullQueue wra rda) -> wra <> rda -> exists full_o, + snd (step RequestQueue' c (true,c_req,false)) = (full_o,mem_val,false). + Admitted. + (* simpl in c; destruct_products; rename t0 into rda, t into wra. + autounfold with get_state; intros. + cbv [RequestQueue' LoopInit fork2]; simpl_ret; cbn [step fst snd]. + apply FEL_nemp_NF_equiv with (c := (u17,(u19,u20,u18), u16)) in H as HH; [ | done]. + destruct HH as [cs_FEL HH]. + rewrite HH. + cbn [fst snd bind inv and2 or2]; fast_simpl_bool. + rewrite (surjective_pairing (step memqueue' (u12,c,u11) _)). + cbv [fst snd]; fast_simpl_bool. + rewrite incrn_pointr_true_equiv. + rewrite incrn_pointr_false_equiv; clear HH. + (* The second logic doesn't really matter much *) + rewrite (surjective_pairing (step FullEmptyLogic _ _)). + eapply ex_intro. + apply pair_equal_spec; split; [ | reflexivity]. + apply pair_equal_spec; split; [ reflexivity | ]. + destruct_pair_let. + cbv [memqueue' Memory' mem_write mem_read]. + cbn [step fst snd]; simpl_ret. + rewrite (surjective_pairing (step (mem_cells _ _ _ _) c _)). + specialize @Cells_data_match with (T := Vec Bit (@REQUEST_WIDTH CAVA_SYS)) + (W := @ADDR_WIDTH CAVA_SYS) (N := (Nat.pow 2 (@ADDR_WIDTH CAVA_SYS))) (I := InitMem) + (S0 := c) (we := true) (wa := (N.to_nat (Bv2N wra))) (wd := c_req) as HH. + rewrite -HH //=. + all: admit. + Admitted. *) + + (* For the queue part *) + Lemma NF_ad_diff wra rda: + ~~ (fullQueue wra rda) -> wra <> rda -> + N2Bv_sized ADDR_WIDTH (Bv2N wra + 1) <> rda. + Admitted. + + Theorem SM_Eq_1b (t : nat) (c_state : State_t) c0 c1 (c_req : Bvector REQUEST_WIDTH) r0 r1: + (nat_of_ord c1 == PREA_date - 1) = true -> + let f_state := (HW_Default_arbitrate t).(Implementation_State) in + let R := HW_Arrival_at t in + R != nullreq -> EqReq R c_req -> State_Eq (IDLE c0 c1 (r0 :: r1)) c_state -> + let '(f_nextstate,(f_cmd_o,f_req_o)) := Next_state R (IDLE c0 c1 (r0 :: r1)) in + let '(c_nextstate,(_,c_cmd_o,c_req_o)) := step FIFOSM c_state (true,c_req) in + (State_Eq f_nextstate c_nextstate) && + (EqCmd f_cmd_o c_cmd_o) && (EqReq f_req_o c_req_o). + Proof. + intros Href_prea f_state R NF EqR H; unfold FIFOSM. + unfold R in NF; specialize (HaltIfFull t c_state) as NFULL. + unfold State_t in c_state; simpl in c_state; destruct_products. + cbv [get_wra get_rda] in NFULL; rewrite NF in NFULL. + rename t0 into s, t1 into cnt, t2 into cref, t3 into cr, t4 into wra, t5 into rda, b into pop. + rewrite /State_Eq in H. + cbv [get_st get_cnt get_cref get_reqqueue get_addr_RequestQueue get_pop] in H. + unfold EqMem in H; cbv [get_memcells_RequestQueue get_mem_RequestQueue get_memcells get_cr] in H. + (* unfold EqQueue in H; cbn [fst snd] in H. *) + move: H => /andP [/andP [/andP [/andP [/andP [EqS EqCnt] EqCref] Mem] Hadr] /eqP EqPop]. + cbn [fst snd] in Hadr. + simpl in Hadr. + + destruct r1 eqn:Hr1; simpl in Hadr. + destruct (r0 == nullreq) eqn:Hr0. + + (* apply negb_true_iff in Hadr; apply BVEq_iff_neq in Hadr. *) + apply BVEq_iff_eq in EqS, EqCnt, EqCref; subst s cnt cref pop. + cbv [LoopInit]; cbn [step fst snd]; simpl_ret. + + rewrite (surjective_pairing (step RequestQueue' _ _)). + specialize (RQ_snd_pushT_popF_NF_nempty ((u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21), (u14, (u16, (u18, u19, u17), u15)),u13, rda), wra))) c_req) as S. + cbv [get_addr_RequestQueue get_memcells_RequestQueue get_mem_RequestQueue get_memcells] in S. + apply S in NFULL as S'; [ | done]; clear S; destruct S' as [full_o H]. + rewrite H. clear H; cbn [fst snd]. + + set tr := nth_default req_null (N.to_nat (Bv2N rda)) _. + specialize (NextCR_equiv_IDLE_NE_PREA (u9, (u10, cr)) (cnt2Bv c0) (cref2Bv c1) tr) as S. + assert ((cref2Bv c1 =? CNT_REF_PREA) = true) as Href_prea_. + { move: Href_prea => /eqP Href_prea; apply BVEq_iff_eq. + rewrite /cref2Bv /CNT_REF_PREA bitvec_literal_correct; f_equal. + by rewrite Href_prea. + } + apply S in Href_prea_ as S'; clear S; destruct S' as [cs_nextcr H]. + rewrite H. + + cbn [fst snd]; clear H. + apply (CmdGen_equiv_idle_to_ref u6 (cnt2Bv c0) (cref2Bv c1) false) in Href_prea_ as H. + destruct H as [cs_CmdGen H]; rewrite H; clear H; cbn [snd]. + + apply (Update_equiv_idle_ref u4 (cnt2Bv c0) (cref2Bv c1) false) in Href_prea_ as H. + destruct H as [cs_update H]; rewrite H; clear H; cbn [fst snd]. + + rewrite /Next_state Href_prea /State_Eq. + specialize RQ_fst_pushT_popF_NF with (c := (u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21),(u14, (u16, (u18, u19, u17), u15)), u13, rda), wra))) (c_req := c_req) as S. + apply S in NFULL as H; clear S. + destruct H as [cs_requeue' [Hx H]]; destruct Hx as [Hrw [Hwra' Hrda']]. + cbv [get_st get_cref get_reqqueue get_addr_RequestQueue get_pop]. + + apply /andP; split. + 2 : exact EqReqNil. + apply /andP; split. + 2 : unfold EqCmd; by apply BVEq_iff_eq. + apply /andP; split. + 2: { + rewrite (surjective_pairing (step RequestQueue' _ _)); cbv [get_pop]; + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; simpl; trivial. } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H Hwra' Hrda'. + cbv [EqQueue Enqueue]; simpl. + apply NF_ad_diff in NFULL; [ | done]. + apply /negPf; by apply BVEq_iff_neq. + } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H Hwra' Hrda'. + cbn [fst snd]; unfold EqMem, Enqueue; simpl; rewrite Hrw. + cbv [get_memcells_RequestQueue get_mem_RequestQueue get_memcells]. + unfold EqMem_ in Mem. + destruct (r0 == _); fold @EqMem_ in Mem. + { + admit. + } + { assert (((size (r1 ++ [R])).+1 == 1) = false); [ admit | ]. + rewrite H0. + destruct (size (r0 :: r1) == 1). + { simpl. + + } + move: Mem => /andP [EqR_ Mem]. + apply /andP; split. + { admit. } + { admit. } + } + + destruct (N2Bv_sized ADDR_WIDTH (Bv2N rda + 1) =? wra) eqn:HH. + { apply BVEq_iff_eq in HH; rewrite HH. + assert ((wra =? N2Bv_sized ADDR_WIDTH (Bv2N wra + 1)) = false) as H0; [admit | ]. + rewrite H0. + destruct (r0 == _). + { fold @EqMem_ in Mem. + admit. } + { apply /andP; split. + { admit. (* (Cells_data c)[@rda] = (Cells_read ...)[@rda] *) } + { admit. }}} + { assert ((N2Bv_sized ADDR_WIDTH (Bv2N rda + 1) =? N2Bv_sized ADDR_WIDTH (Bv2N wra + 1)) = false) as H0; [admit | ]. + rewrite H0. + destruct (r0 == _); fold @EqMem_ in Mem. + { admit. } + { } + + } + assert ((N2Bv_sized ADDR_WIDTH (Bv2N rda + 1) =? N2Bv_sized ADDR_WIDTH (Bv2N wra + 1)) = false). { admit. } + rewrite H0. + destruct (N2Bv_sized ADDR_WIDTH (Bv2N rda + 1) =? wra) eqn:HH. + { destruct (r0 == _). + { + + } + + } + destruct (N2Bv_sized ADDR_WIDTH (Bv2N rda + 1) =? _). + unfold EqMem_ in Mem. + destruct (r0 == nullreq). + 2: { + move: Mem => /andP [EqR_ Mem]. + apply /andP; split. { (* EqR_ *) admit. } + fold @EqMem_ in Mem. + assert (EqMem_) + rewrite cats1 /rcons. + admit. + } + fold @EqMem_ in Mem. + admit. + } + apply /andP; split. + 2 : { + cbv [get_cref]. + rewrite (surjective_pairing (step RequestQueue' _ _)) H //= VectorSpec.map_id. + destruct_pair_let. + rewrite /cref2Bv /OCycle0REF //=; by apply BVEq_iff_eq. + } + cbv [get_st]; rewrite (surjective_pairing (step RequestQueue' _ _)) H //=; destruct_pair_let. + by []. + Admitted. + + Theorem SM_Eq_1a (t : nat) (c_state : State_t) c0 c1 (c_req : Bvector REQUEST_WIDTH) : + (nat_of_ord c1 == PREA_date - 1) = true -> + let f_state := (HW_Default_arbitrate t).(Implementation_State) in + let R := HW_Arrival_at t in + R != nullreq -> EqReq R c_req -> State_Eq (IDLE c0 c1 []) c_state -> + let '(f_nextstate,(f_cmd_o,f_req_o)) := Next_state R (IDLE c0 c1 []) in + let '(c_nextstate,(_,c_cmd_o,c_req_o)) := step FIFOSM c_state (true,c_req) in + (State_Eq f_nextstate c_nextstate) && + (EqCmd f_cmd_o c_cmd_o) && (EqReq f_req_o c_req_o). + Proof. + intros Href_prea f_state R NF EqR H; unfold FIFOSM. + unfold R in NF; specialize (HaltIfFull t c_state) as NFULL. + unfold State_t in c_state; simpl in c_state; destruct_products. + cbv [get_wra get_rda] in NFULL; rewrite NF in NFULL. + rename t0 into s, t1 into cnt, t2 into cref, t3 into cr, t4 into wra, t5 into rda, b into pop. + rewrite /State_Eq in H. + cbv [get_st get_cnt get_cref get_reqqueue get_addr_RequestQueue get_pop] in H. + unfold EqMem in H; cbv [get_memcells_RequestQueue get_mem_RequestQueue get_memcells get_cr] in H. + unfold EqQueue in H; cbn [fst snd] in H. + move: H => /andP [/andP [/andP [/andP [/andP [EqS EqCnt] EqCref] Mem] Hadr] /eqP EqPop]. + apply BVEq_iff_eq in EqS, EqCnt, EqCref, Hadr; subst s cnt cref pop. + cbv [LoopInit]; cbn [step fst snd]; simpl_ret. + + rewrite (surjective_pairing (step RequestQueue' _ _)). + specialize (RQ_snd_pushT_empty ((u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21), (u14, (u16, (u18, u19, u17), u15)),u13, rda), wra))) c_req false) as S. + cbv [get_addr_RequestQueue get_memcells_RequestQueue get_mem_RequestQueue get_memcells] in S. + apply S in Hadr as H; clear S. + destruct H as [full_o H]; rewrite H. + clear H; cbn [fst snd]. + + set tr := nth_default req_null (N.to_nat (Bv2N rda)) _. + specialize NextCR_equiv with (c := (u9, (u10, cr))) (cnt := cnt2Bv c0) + (cref := cref2Bv c1) (tr := tr) as [cs_nextcr H]. + rewrite H; cbv [fst]; clear H. + + cbn [snd]. + assert ((cref2Bv c1 =? CNT_REF_PREA) = true) as Href_prea_. + { move: Href_prea => /eqP Href_prea; apply BVEq_iff_eq. + rewrite /cref2Bv /CNT_REF_PREA bitvec_literal_correct; f_equal. + by rewrite Href_prea. + } + apply (CmdGen_equiv_idle_to_ref u6 (cnt2Bv c0)) in Href_prea_ as H. + destruct H as [cs_CmdGen H]; rewrite H; clear H; cbn [snd]. + + apply (Update_equiv_idle_ref u4 (cnt2Bv c0) (cref2Bv c1)) in Href_prea_ as H. + destruct H as [cs_update H]; rewrite H; clear H. + + rewrite /Next_state Href_prea /State_Eq. + specialize RQ_fst_pushT_popF_NF with (c := (u11,(u12,(u26, (u27, (u29, (u31, u32, u30), u28)), u25, + (u24, c, u23), u22, (u20, u21),(u14, (u16, (u18, u19, u17), u15)), u13, rda), wra))) (c_req := c_req) as S. + apply S in NFULL as H; clear S. + destruct H as [cs_requeue' [Hx H]]; destruct Hx as [Hrw [Hwra' Hrda']]. + cbv [get_st get_cref get_reqqueue get_addr_RequestQueue get_pop]. + + apply /andP; split. + 2 : exact EqReqNil. + apply /andP; split. + 2 : unfold EqCmd; by apply BVEq_iff_eq. + apply /andP; split. + 2: { + rewrite (surjective_pairing (step RequestQueue' _ _)); cbv [get_pop]; + repeat lazymatch goal with + | |- context [ match ?p with pair _ _ => _ end ] => rewrite (surjective_pairing p) + end; simpl; trivial. } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H Hwra' Hrda'. + cbv [EqQueue Enqueue]; simpl. + unfold R; rewrite NF. + apply /negPf; apply BVEq_iff_neq; rewrite Hadr N.add_1_r. + specialize N2Bv_sized_neq_succ with (n := @ADDR_WIDTH CAVA_SYS) (x := Bv2N rda) as HH. + rewrite N2Bv_sized_Bv2N in HH; specialize ADDR_WIDTH_pos as H0; move: H0 => /ltP H0. + by apply HH in H0. } + apply /andP; split. + 2 : { + rewrite (surjective_pairing (step RequestQueue' _ _)) H Hrda'. + unfold EqMem, Enqueue; simpl; rewrite andb_true_r. + destruct (R == _) eqn:HH; [ trivial | ]. + rewrite Hrw; cbv [get_memcells_RequestQueue get_mem_RequestQueue get_memcells]. + specialize (@nth_cells_read (Vec Bit REQUEST_WIDTH) ADDR_WIDTH InitMem rda c_req c) as H'. + rewrite Hadr H'; exact EqR. + } + apply /andP; split. + 2 : { + cbv [get_cref]. + rewrite (surjective_pairing (step RequestQueue' _ _)) H //= VectorSpec.map_id. + destruct_pair_let. + rewrite /cref2Bv /OCycle0REF //=; by apply BVEq_iff_eq. + } + cbv [get_st]; rewrite (surjective_pairing (step RequestQueue' _ _)) H //=; destruct_pair_let. + by []. + Qed. + + (* Have to add the full case *) + (* REF bounded with PREA_date or arbitrary parameter *) + (* if REF is bounded with PREA_date, a problem with cref + WAIT *) + (* try bound with random parameter, but will not be correspondent to Next_cycle *) + Theorem SM_Eq_NFULL (t : nat) (c_state : State_t) (f_req: Request_t) + (c_req : Bvector REQUEST_WIDTH) (push : bool) : + let f_state := (HW_Default_arbitrate t).(Implementation_State) in + let R := HW_Arrival_at t in + R != nullreq -> EqReq R c_req -> State_Eq f_state c_state -> + let '(f_nextstate,(f_cmd_o,f_req_o)) := Next_state R f_state in + let '(c_nextstate,(_,c_cmd_o,c_req_o)) := step FIFOSM c_state (true,c_req) in + (State_Eq f_nextstate c_nextstate) && + (EqCmd f_cmd_o c_cmd_o) && (EqReq f_req_o c_req_o). + Proof. + destruct (f_state) eqn:Hf_state. + { destruct (nat_of_ord c0 == PREA_date - 1) eqn:Hcref_prea; move: Hcref_prea. + { destruct r eqn:HR. + { apply SM_Eq_1a. } + { admit. (* Case 1b: IDLE -> REFRESHING (non-empty queue)*) } + } + { destruct (c1 + WAIT < PREA_date) eqn:Hcref_service. + { destruct r eqn:HR. + { admit. (* Case 2a: IDLE -> IDLE (empty queue) *)} + { admit. (* Case 2b: IDLE -> RUNNING (non-empty queue) *)} + } + { destruct r eqn:HR. + { admit. (* Case 3a: IDLE -> IDLE (empty queue )*)} + { admit. (* Case 3b: IDLE -> IDLE (non empty queue) *) } + } + } + } + { destruct (nat_of_ord c0 == OACT_date) eqn:Hact_date. + { destruct r eqn:HR. + { admit. (* Case 4a : RUNNING -> RUNNING (ACT) (empty queue) *) } + { admit. (* Case 4b : RUNNING -> RUNNING (ACT) (non empty queue) *)} + } + { destruct (nat_of_ord c0 == OCAS_date) eqn:Hcas_date. + { destruct r eqn:HR. + { admit. (* Case 5a : RUNNING -> RUNNING (CAS) (empty queue )*) } + { admit. (* Case 5b : RUNNING -> RUNNING (CAS) (non-empty queue) *)} + } + { destruct (nat_of_ord c0 == WAIT.-1) eqn:Hend_date. + { destruct r eqn:HR. + { admit. (* Case 6a : RUNNING -> IDLE (empty queue) *) } + { admit. (* Case 6b : RUNNING -> IDLE (non empty queue) *)} + } + { destruct r eqn:HR. + { admit. (* Case 7a : RUNNING -> RUNNING (empty queue) *) } + { admit. (* Case 7b : RUNNING -> RUNNING (non empty queue) *) } + } + } + } + } + { destruct (nat_of_ord c0 == OREF_date) eqn:Href_date. + { destruct r eqn:HR. + { admit. } + { admit. } + } + { destruct (nat_of_ord c0 == OENDREF_date) eqn:Hendref_date. + + } + + } + +End EquivalenceProof. \ No newline at end of file -- GitLab