diff --git a/framework/DRAM/FIFO_proofs.v b/framework/DRAM/FIFO_proofs.v index 4cfa6d5bedf3d00922a2cd9f69496456c6925165..58a7a73653fc545bb02fe5b0cf11df1af70cd9a9 100644 --- a/framework/DRAM/FIFO_proofs.v +++ b/framework/DRAM/FIFO_proofs.v @@ -4,6 +4,7 @@ Set Printing Projections. From mathcomp Require Export fintype div. Require Import Program. From DRAM Require Export FIFO. +From mathcomp Require Import ssrZ zify. Section FIFOPROOFS. @@ -15,6 +16,10 @@ Section FIFOPROOFS. Existing Instance ARBITER_CFG. Existing Instance FIFO_implementation. + + (* ------------------------------------------------------------------ *) + (* --------------------- USEFUL DEFINITIONS ------------------------- *) + (* ------------------------------------------------------------------ *) Definition FIFO_counter (AS : State_t) := match AS with @@ -58,6 +63,10 @@ Section FIFOPROOFS. | RUNNING _ _ r => Some r end. + (* ------------------------------------------------------------------ *) + (* --------------------- BASIC LEMMAS ------------------------------- *) + (* ------------------------------------------------------------------ *) + Ltac isCommand := unfold isPRE, isACT, isCAS, PRE_of_req, ACT_of_req, CAS_of_req, Kind_of_req; match goal with @@ -2473,6 +2482,50 @@ Section FIFOPROOFS. apply leq_subr. } exact Hreq_b. Qed. + + Theorem Cmds_initial t b: + b \in (Default_arbitrate t).(Arbiter_Commands) -> isCAS b -> + exists a, (a \in (Default_arbitrate t).(Arbiter_Commands)) && (isACT a) && (Same_Row a b) && (Before a b). + Proof. + intros Hb iCb. + apply FIFO_CAS_date in Hb as H. destruct H as [Hcb [Hrun_b Hreq_b]]. + 2: done. + destruct (Default_arbitrate b.(CDate)).(Implementation_State) eqn:Hsb. + 1: by simpl in Hrun_b. + rewrite -Hsb in Hreq_b. + apply Request_ACT_bounded in Hreq_b. + 2: by rewrite -Hsb in Hrun_b. + rewrite /Slot_start Hsb in Hreq_b. + exists (ACT_of_req b.(Request) (b.(CDate) - c + Next_cycle OACT_date)). + rewrite /isACT //= eq_refl andbT /Before /After //= /Same_Row eq_refl //= andbT. + + apply /andP; split. + 2: { + rewrite /FIFO_counter in Hcb; rewrite Hcb FIFO_next_cycle_cas_eq_casS FIFO_nextcycle_act_eq_actS. + rewrite -Hsb in Hrun_b. + rewrite -subnA. + 3: { + apply Date_gt_counter in Hrun_b as H; rewrite Hsb /FIFO_counter Hcb FIFO_next_cycle_cas_eq_casS in H. + apply ltn_trans with (m := CAS_date) in H. exact H. done. } + 2: rewrite /CAS_date /ACT_date -addnS; by apply nat_ltn_add. + rewrite ltn_subrL. + apply FIFO_date_gt_0 in Hb; rewrite subn_gt0 Hb andbT -addn1 -[CAS_date.+1]addn1 leq_add2r. + rewrite /CAS_date /ACT_date; apply nat_ltn_add; by rewrite lt0n T_RCD_pos. + } + + apply FIFO_in_the_past with (t := b.(CDate)). + { by apply Cmd_in_trace. } + apply FIFO_in_the_past with (t := b.(CDate) - c + Next_cycle OACT_date). + { rewrite -subnA. + 3: { rewrite -Hsb in Hrun_b; apply Date_gt_counter in Hrun_b. + rewrite /FIFO_counter Hsb in Hrun_b; by rewrite leq_eqVlt Hrun_b orbT. } + 2: { rewrite /FIFO_counter in Hcb; rewrite Hcb; + rewrite FIFO_next_cycle_cas_eq_casS FIFO_nextcycle_act_eq_actS; + rewrite /CAS_date -addnS; by apply nat_ltn_add. } + apply leq_subr. } + exact Hreq_b. + Qed. + (* ------------------------------------------------------------------ *) (* --------------------- INSTANCES ---------------------------------- *) @@ -2518,7 +2571,7 @@ Section FIFOPROOFS. Qed. (* nat -> Trace *) - Definition FIFO_arbitrate t := + Program Definition FIFO_arbitrate t := mkTrace (Default_arbitrate t).(Arbiter_Commands) (Default_arbitrate t).(Arbiter_Time) @@ -2535,12 +2588,17 @@ Section FIFOPROOFS. (Cmds_T_WtoR_DBG_ok t) (Cmds_T_CCD_SBG_ok t) (Cmds_T_CCD_DBG_ok t) + _ + _ (Cmds_T_FAW_ok t) (Cmds_T_RRD_SBG_ok t) (Cmds_T_RRD_DBG_ok t) (Cmds_ACT_ok t) - (Cmds_row_ok t). - + (Cmds_row_ok t) + (Cmds_initial t) + _. + Admit Obligations. + Global Instance FIFO_arbiter : Arbiter_t := mkArbiter AF FIFO_arbitrate Requests_handled Default_arbitrate_time_match. diff --git a/framework/DRAM/System.v b/framework/DRAM/System.v index fec7f72f21d86f52a4ab0305822c5c03165d3773..0f74c25af6783eec0261a14da252505a62314efe 100644 --- a/framework/DRAM/System.v +++ b/framework/DRAM/System.v @@ -26,6 +26,16 @@ Class System_configuration := T_CCD_s : nat; (* RD/WR to RD/WR delay intra- + inter-bank : different bank groups *) T_CCD_l : nat; (* RD/WR to RD/WR delay intra- + inter-bank : same bank groups *) + (* Refresh related properties *) + (* Assuming 1X refresh mode *) + + T_REFI : nat; + (* All banks must be pre-charged and idle for a minimum time tRP before the REF command can be applied *) + (* Address bits should be don't care during a refresh command *) + T_RFC : nat; (* Depends on memory density *) + (* Delay to be respected between REF and the next valid command (except DES) *) + (* Maximum 8/16/32 REF can be postponed -> 1X/2X/4X refresh mode *) + (* POs *) BANKGROUPS_pos : BANKGROUPS != 0; BANKS_pos : BANKS != 0; @@ -43,7 +53,12 @@ Class System_configuration := T_WTR_s_pos : T_WTR_s != 0; T_WTR_l_pos : T_WTR_l != 0; T_CCD_s_pos : T_CCD_s != 0; - T_CCD_l_pos : T_CCD_l != 0 + T_CCD_l_pos : T_CCD_l != 0; + T_RFC_pos : T_RFC > 0; + + T_RRD_bgs : T_RRD_s < T_RRD_l; + T_WTR_bgs : T_WTR_s < T_WTR_l; + T_CCD_bgs : T_CCD_s < T_CCD_l; }. End System. \ No newline at end of file diff --git a/framework/DRAM/TDMds.v b/framework/DRAM/TDMds.v new file mode 100644 index 0000000000000000000000000000000000000000..64914f43e0b20f5803432d60b7f6bd554e23de82 --- /dev/null +++ b/framework/DRAM/TDMds.v @@ -0,0 +1,340 @@ +Set Warnings "-notation-overridden,-parsing". +Set Printing Projections. + +From DRAM Require Export ImplementationInterface. +From mathcomp Require Import fintype div ssrZ zify. +From mathcomp Require Import ssreflect seq. + +From Coq Require Import Program FMapList OrderedTypeEx. + +(* FMapList.Make expects an instance of the OrderedType module, which we define as Nat_as_OT *) +Module Import NatMap := FMapList.Make(Nat_as_OT). + +Section TDMds. + + Context {SYS_CFG : System_configuration}. + + #[local] Axiom DDR3: BANKGROUPS = 1. + + Definition ACT_date := T_RP.+1. + Definition CAS_date := ACT_date + T_RCD.+1. + + Class TDMds_configuration := + { + SL : nat; (* still exists *) + SN : nat; (* number of critical tasks / TDM slots *) + + SN_one : 1 < SN; + + SL_pos : 0 < SL; + SL_ACT : ACT_date < SL; + SL_CASS : CAS_date.+1 < SL; + }. + + Context {TDMds_CFG : TDMds_configuration}. + + Lemma SN_pos : 0 < SN. + specialize SN_one; lia. + Qed. + + Lemma SL_CAS: CAS_date < SL. + specialize SL_CASS as H; lia. + Qed. + + Lemma Last_cycle: SL.-1 < SL. + specialize SL_pos; lia. + Qed. + + (* Have to introduce the concept of criticality as well *) + Record Requestor_t_def := mkRequestorSlack + { + nb : nat; (* the id of the requestor : no longer bounded by slot number *) + crit : bool; (* criticality *) + + (* critical requests are bounded by the number of slots *) + crit_req : crit == true -> nb < SN; + }. + + Definition Same_Requestor (a b : Requestor_t_def) := + a.(nb) == b.(nb). + + Definition Requestor_t_def_eqdef (a b : Requestor_t_def) := + (a.(nb) == b.(nb)) && (a.(crit) == b.(crit)). + + Lemma Requestor_t_def_eqn : Equality.axiom Requestor_t_def_eqdef. + Admitted. + + Canonical Requestor_t_def_eqMixin := EqMixin Requestor_t_def_eqn. + Canonical Requestor_t_def_eqType := Eval hnf in EqType Requestor_t_def Requestor_t_def_eqMixin. + + Instance REQUESTOR_CFG : Requestor_configuration := + { + Requestor_t := Requestor_t_def_eqType + }. + + Context {AF : Arrival_function_t}. + + Definition Slot_t := ordinal_eqType SN. + Definition Counter_t := ordinal SL. + + (* Weak maps : maps with no ordering on the key type nor the data type, WSfun and WS *) + (* Sfun and S: the key type is ordered *) + Check NatMap.t. + + (* Slack is an ordered map from nat (requestor id) to nat (slack amount) *) + Definition Slack_t := NatMap.t nat. + + (* Track whether a request is processed (RUNNING) or not (IDLE), the owner of + the current slot, the cycle offset within the slot, as well as the set of + pending requests. *) + Inductive TDM_state_t := + | IDLE : Slot_t -> Slack_t -> Counter_t -> Requests_t -> TDM_state_t + | RUNNING : Slot_t -> Slack_t -> Counter_t -> Requests_t -> Request_t-> TDM_state_t. + + Global Instance ARBITER_CFG : Arbiter_configuration := + { + State_t := TDM_state_t; + }. + + Definition OZCycle := Ordinal SL_pos. + Definition OACT_date := Ordinal SL_ACT. + Definition OCAS_date := Ordinal SL_CAS. + Definition OLastCycle := Ordinal Last_cycle. + Definition OZSlot := Ordinal SN_pos. + + (*************************************************************************************************) + (** ARBITER IMPLEMENTATION ***********************************************************************) + (*************************************************************************************************) + + Definition p_transform (x cs : nat) : nat := + match (cs > 0) as X return nat with + | true => if (x < cs) then (cs - 1) - x else (SN - 1 + cs) - x + | _ => (SN - 1) - x + end. + + Definition egt (cs a b : nat) := + gtn (p_transform a cs) (p_transform b cs). + + Definition lp (cs : Slot_t) := if (nat_of_ord cs == 0) then (SN.-1) else cs.-1. + + Definition dist (max a b : nat) : nat := + if (b < a) then (a - b) else (if (b == a) then 0 else (max - (b - a))). + + (* Definition elt (cs a b : nat) : bool := + if (a == cs) then true + else if (b == cs) then false + else if (((a > cs) && (b < cs)) || (a < cs) && (b > cs)) then (ltn a b) else ~~ (ltn a b). + + Definition elt_ (cs a b : nat) : bool := + if (b == cs) then true + else if (a == cs) then false + else if (((a > cs) && (b < cs)) || (a < cs) && (b > cs)) then (ltn a b) else ~~ (ltn a b). + + Definition less_priority cs := (cs + (SN - 1)) %% SN. *) + + (* Increment counter for cycle offset (with wrap-arround). *) + Definition Next_cycle (c : Counter_t) := + let nextc := c.+1 < SL in + (if nextc as X return (nextc = X -> Counter_t) then + fun (P : nextc = true) => Ordinal (P : nextc) + else + fun _ => OZCycle) Logic.eq_refl. + + (* Increment the slot counter (with wrap-arround) *) + Definition Next_slot (s : Slot_t) (c : Counter_t) : Slot_t := + if (c.+1 < SL) then s + else + let nexts := s.+1 < SN in + (if nexts as X return (nexts = X -> Slot_t) then + fun (P : nexts = true) => Ordinal (P : nexts) + else + fun _ => OZSlot) Logic.eq_refl. + + Definition Enqueue (R P : Requests_t) := P ++ R. + Definition Dequeue r (P : Requests_t) := rem r P. + + Program Definition nullreq := mkReq + (mkRequestorSlack 0 true _) 0 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0. + Next Obligation. + exact SN_pos. + Qed. + + (* Returns a triple: the selected requestor's id, the current slot, and the request *) + Program Definition edf (cs : Slot_t) := foldr (fun r_it r_saved => + let s := r_it.(Requestor).(nb) in + let min := r_saved.(Requestor).(nb) in + let cs_nat := nat_of_ord cs in + if egt cs_nat s min then r_it else r_saved) + (mkReq (mkRequestorSlack (nat_of_ord cs) true _) 1 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0). + + Program Definition edf_slack (cs : Slot_t) (smap : Slack_t) := foldr (fun req r_saved => + let min := r_saved.(Requestor).(nb) in + let req_id := req.(Requestor).(nb) in + let slack := find req.(Requestor).(nb) smap in + let cs_nat := nat_of_ord cs in + let cond := egt cs_nat req_id min in + (* Testing with SN = 4 and SL = 8 *) + match slack with + | None => if cond then req else r_saved + | Some sl => let t := ((cs_nat + 1) * 8) - (req.(Date) %% 32) in + if (sl > t) then r_saved + (* if there is enough slack, then the + associated request is not priority, don't update variables *) + else if cond then req else r_saved + end) (mkReq (mkRequestorSlack (nat_of_ord cs) true _) 1 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0). + + Program Definition edf_slack_crit (cs : Slot_t) (smap : Slack_t) := foldr (fun r_it r_saved => + let cs_nat := nat_of_ord cs in + let r_it_crit := r_it.(Requestor).(crit) in + let r_it_id := r_it.(Requestor).(nb) in + let r_saved_crit := r_saved.(Requestor).(crit) in + let r_saved_id := r_saved.(Requestor).(nb) in + if ~~ (r_it_crit) then + (* safe to choose the non-critical request when the saved + request is not the upcoming one, which has the most priority *) + (if (r_saved_id != cs_nat) then r_it else r_saved) + else ( + (* choose the request if: + a) r_it[i] > r_saved[i] , i.e., r_it has more priority than r_saved + b) r_it[i] is the due for the upcoming slot (most priority), this condition + is useful to overwrite previously selected non-critical requests *) + let cond := (egt cs_nat r_it_id r_saved_id) || (r_it_id == cs_nat) || (r_saved.(Date) == 0) in + let slack := find r_it.(Requestor).(nb) smap in + match slack with + | None => if cond then r_it else r_saved + | Some sl => + let t := (r_it.(Date) %% (SL * SN)) in + if (sl > t) then r_saved else + (* if there is enough slack, then the + associated request is not priority, don't update variables *) + (if cond then r_it else r_saved) + end(* how to make sure that the initial request will never be picked ? *) + )) (mkReq (mkRequestorSlack (lp cs) true _) 0 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0). + Next Obligation. + unfold lp; clear H. + destruct (nat_of_ord cs == 0); [ rewrite ltn_predL; exact SN_pos | ]. + destruct cs; simpl; lia. + Qed. + + Definition empty_nat_map := NatMap.empty nat. + + Definition Next_state (R : Requests_t) (AS : TDM_state_t) + : (TDM_state_t * (Command_kind_t * Request_t)) := + match AS return (TDM_state_t * (Command_kind_t * Request_t)) with + | IDLE s slmap c P => + let P' := Enqueue R P in + let s' := Next_slot s c in + let c' := Next_cycle c in + if (c == OZCycle) then ( + match P with + | [::] => (IDLE s' slmap c' P', (NOP,nullreq)) + | _ => let req := edf_slack_crit s slmap P in + (RUNNING s' slmap c' (Enqueue R (Dequeue req P)) req, (PRE, req)) + end) + else (IDLE s' slmap c' P', (NOP,nullreq)) + | RUNNING s slmap c P r => + let P' := Enqueue R P in + let s' := Next_slot s c in + let c' := Next_cycle c in + if c == OACT_date then + (RUNNING s' slmap c' P' r, (ACT, r)) + else if c == OCAS_date then + (RUNNING s' slmap c' P' r, (Kind_of_req r, r)) + else if c == OLastCycle then + let req_id := r.(Requestor).(nb) in + let slack' := (dist SN (nat_of_ord s) req_id) * SL in + (* replaces existing slack -- won't accumulate *) + let slmap' := NatMap.add req_id slack' slmap in + (IDLE s' slmap' c' P', (NOP, nullreq)) + else + (RUNNING s' slmap c' P' r, (NOP, nullreq)) + end. + + Definition Init_state R := + IDLE OZSlot empty_nat_map OZCycle (Enqueue R [::]). + + Instance TDMds_implementation : Implementation_t := + mkImplementation Init_state Next_state. + + Program Definition TDMds_arbitrate t := + mkTrace + (Default_arbitrate t).(Arbiter_Commands) + (Default_arbitrate t).(Arbiter_Time) + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _. + Admit Obligations. + + Program Instance TDMds_arbiter : Arbiter_t := + mkArbiter AF TDMds_arbitrate _ _. + Admit Obligations. + +End TDMds. + +Section TDMds_sim. + + Program Instance SYS_CFG : System_configuration := + { + BANKGROUPS := 1; + BANKS := 8; + + T_BURST := 1; + T_WL := 1; + T_RRD_s := 1; + T_RRD_l := 3; + T_FAW := 20; + T_RC := 3; + T_RP := 1; + T_RCD := 1; + T_RAS := 4; + T_RTP := 4; + T_WR := 1; + T_RTW := 10; + T_WTR_s := 1; + T_WTR_l := 10; + T_CCD_s := 1; + T_CCD_l := 12; + + T_REFI := 10; + T_RFC := 10; + }. + + Program Instance TDMds_CFG : TDMds_configuration := + { + SN := 2; + SL := 8; + }. + + Existing Instance REQUESTOR_CFG. + Existing Instance TDMds_implementation. + Existing Instance TDMds_arbiter. + + Program Definition ReqA0 := mkReq + (mkRequestorSlack 0 true _) 2 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 5. + + Program Definition ReqB0 := mkReq (* 3 instead of 14 *) + (mkRequestorSlack 1 true _) 14 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 10. + + Program Definition ReqC0 := mkReq + (mkRequestorSlack 2 false _) 26 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0. + + Program Definition ReqB1 := mkReq + (mkRequestorSlack 1 true _) 28 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0. + + Program Definition ReqA1 := mkReq + (mkRequestorSlack 0 true _) 40 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0. + + Program Definition ReqC1 := mkReq + (mkRequestorSlack 2 false _) 46 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0. + + Program Definition ReqB2 := mkReq + (mkRequestorSlack 1 true _) 50 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0. + + Program Definition ReqA2 := mkReq + (mkRequestorSlack 0 true _) 72 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0. + + Definition test_req_seq := [:: ReqA0;ReqB0;ReqC0;ReqB1;ReqA1;ReqC1;ReqB2;ReqA2]. + + Program Instance AF : Arrival_function_t := Default_arrival_function_t test_req_seq. + + Compute (Arbitrate 80).(Commands). + +End TDMds_sim. \ No newline at end of file diff --git a/framework/DRAM/TDMes.v b/framework/DRAM/TDMes.v new file mode 100644 index 0000000000000000000000000000000000000000..f78c960da7a90f201d69b8344e350bffdf925de0 --- /dev/null +++ b/framework/DRAM/TDMes.v @@ -0,0 +1,337 @@ +Set Warnings "-notation-overridden,-parsing". +Set Printing Projections. + +From DRAM Require Export ImplementationInterface. +From mathcomp Require Import fintype div ssrZ zify. +From mathcomp Require Import ssreflect seq. + +From Coq Require Import Program FMapList OrderedTypeEx. + +(* FMapList.Make expects an instance of the OrderedType module, which we define as Nat_as_OT *) +Module Import NatMap := FMapList.Make(Nat_as_OT). + +Section TDMes. + + Context {SYS_CFG : System_configuration}. + + #[local] Axiom DDR3: BANKGROUPS = 1. + + Definition ACT_date := T_RP.+1. + Definition CAS_date := ACT_date + T_RCD.+1. + + Class TDMds_configuration := + { + SL : nat; (* still exists *) + SN : nat; (* number of critical tasks / TDM slots *) + + SN_one : 1 < SN; + + SL_pos : 0 < SL; + SL_ACT : ACT_date < SL; + SL_CASS : CAS_date.+1 < SL; + }. + + Context {TDMds_CFG : TDMds_configuration}. + + Lemma SN_pos : 0 < SN. + specialize SN_one; lia. + Qed. + + Lemma SL_CAS: CAS_date < SL. + specialize SL_CASS as H; lia. + Qed. + + Lemma Last_cycle: SL.-1 < SL. + specialize SL_pos; lia. + Qed. + + (* Have to introduce the concept of criticality as well *) + Record Requestor_t_def := mkRequestorSlack + { + nb : nat; (* the id of the requestor : no longer bounded by slot number *) + crit : bool; (* criticality *) + + (* critical requests are bounded by the number of slots *) + crit_req : crit == true -> nb < SN; + }. + + Definition Same_Requestor (a b : Requestor_t_def) := + a.(nb) == b.(nb). + + Definition Requestor_t_def_eqdef (a b : Requestor_t_def) := + (a.(nb) == b.(nb)) && (a.(crit) == b.(crit)). + + Lemma Requestor_t_def_eqn : Equality.axiom Requestor_t_def_eqdef. + Admitted. + + Canonical Requestor_t_def_eqMixin := EqMixin Requestor_t_def_eqn. + Canonical Requestor_t_def_eqType := Eval hnf in EqType Requestor_t_def Requestor_t_def_eqMixin. + + Instance REQUESTOR_CFG : Requestor_configuration := + { + Requestor_t := Requestor_t_def_eqType + }. + + Context {AF : Arrival_function_t}. + + Definition Slot_t := ordinal_eqType SN. + Definition Counter_t := ordinal SL. + + (* Weak maps : maps with no ordering on the key type nor the data type, WSfun and WS *) + (* Sfun and S: the key type is ordered *) + (* Check NatMap.t. *) + + (* Slack is an ordered map from nat (requestor id) to nat (slack amount) *) + Definition Slack_t := NatMap.t nat. + + (* Track whether a request is processed (RUNNING) or not (IDLE), the owner of + the current slot, the cycle offset within the slot, as well as the set of + pending requests. *) + Inductive TDM_state_t := + | IDLE : Slot_t -> Slack_t -> Counter_t -> Requests_t -> TDM_state_t + | RUNNING : Slot_t -> Slack_t -> Counter_t -> Counter_t -> Requests_t -> Request_t-> TDM_state_t. + + Global Instance ARBITER_CFG : Arbiter_configuration := + { + State_t := TDM_state_t; + }. + + Definition OZCycle := Ordinal SL_pos. + + Lemma SL_one : 1 < SL. + specialize SL_ACT; specialize T_RP_pos; unfold ACT_date; lia. + Qed. + Definition OSlot1 := Ordinal SL_one. + + Definition OACT_date := Ordinal SL_ACT. + Definition OCAS_date := Ordinal SL_CAS. + Definition OLastCycle := Ordinal Last_cycle. + Definition OZSlot := Ordinal SN_pos. + + (*************************************************************************************************) + (** ARBITER IMPLEMENTATION ***********************************************************************) + (*************************************************************************************************) + + Definition p_transform (x cs : nat) : nat := + match (cs > 0) as X with + | true => if (x < cs) then (cs - 1) - x else (SN - 1 + cs) - x + | _ => (SN - 1) - x + end. + + Definition egt (cs a b : nat) := + gtn (p_transform a cs) (p_transform b cs). + + Definition lp (cs : Slot_t) := if (nat_of_ord cs == 0) then (SN.-1) else cs.-1. + + Definition dist (max a b : nat) : nat := + if (b < a) then (a - b) else (if (b == a) then 0 else (max - (b - a))). + + (* Increment counter for cycle offset (with wrap-arround). *) + Definition Next_cycle (c : Counter_t) := + let nextc := c.+1 < SL in + (if nextc as X return (nextc = X -> Counter_t) then + fun (P : nextc = true) => Ordinal (P : nextc) + else + fun _ => OZCycle) Logic.eq_refl. + + (* Increment the slot counter (with wrap-arround) *) + Definition Next_slot (s : Slot_t) (c : Counter_t) : Slot_t := + if (c.+1 < SL) then s + else + let nexts := s.+1 < SN in + (if nexts as X return (nexts = X -> Slot_t) then + fun (P : nexts = true) => Ordinal (P : nexts) + else + fun _ => OZSlot) Logic.eq_refl. + + Definition Enqueue (R P : Requests_t) := P ++ R. + Definition Dequeue r (P : Requests_t) := rem r P. + + Program Definition nullreq := mkReq + (mkRequestorSlack 0 true _) 0 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0. + Next Obligation. + exact SN_pos. + Qed. + + Program Definition edf_slack_crit (cs : Slot_t) (smap : Slack_t) := foldr (fun r_it r_saved => + let cs_nat := nat_of_ord cs in + let r_it_crit := r_it.(Requestor).(crit) in + let r_it_id := r_it.(Requestor).(nb) in + let r_saved_crit := r_saved.(Requestor).(crit) in + let r_saved_id := r_saved.(Requestor).(nb) in + if ~~ (r_it_crit) then + (* safe to choose the non-critical request when the saved + request is not the upcoming one, which has the most priority *) + (if (r_saved_id != cs_nat) then r_it else r_saved) + else ( + (* choose the request if: + a) r_it[i] > r_saved[i] , i.e., r_it has more priority than r_saved + b) r_it[i] is the due for the upcoming slot (most priority), this condition + is useful to overwrite previously selected non-critical requests + c) overwrite the default request, which has special date 0 *) + let cond := (egt cs_nat r_it_id r_saved_id) || (r_it_id == cs_nat) || (r_saved.(Date) == 0) in + let slack := find r_it.(Requestor).(nb) smap in + match slack with + | None => if cond then r_it else r_saved + | Some sl => + let t := (r_it.(Date) %% (SL * SN)) in + if (sl > t) then r_saved else + (* if there is enough slack, then the + associated request is not priority, don't update variables *) + (if cond then r_it else r_saved) + end(* how to make sure that the initial request will never be picked ? *) + )) (mkReq (mkRequestorSlack (lp cs) true _) 0 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0). + Next Obligation. + unfold lp; clear H. + destruct (nat_of_ord cs == 0); [ rewrite ltn_predL; exact SN_pos | ]. + destruct cs; simpl; lia. + Qed. + + Definition empty_nat_map := NatMap.empty nat. + + Definition early_start cs cnt smap req := + let ncs := nat_of_ord (Next_slot cs OLastCycle) in + if (ncs == req.(Requestor).(nb)) then true + else (let slack := find ncs smap in + match slack with + | None => false + | Some sl => SL.-1 - cnt < sl + end + ). + + Definition Next_state (R : Requests_t) (AS : TDM_state_t) + : (TDM_state_t * (Command_kind_t * Request_t)) := + match AS return (TDM_state_t * (Command_kind_t * Request_t)) with + | IDLE s slmap c P => + let P' := Enqueue R P in + let s' := Next_slot s c in + let c' := Next_cycle c in + match P with + | [::] => (IDLE s' slmap c' P', (NOP,nullreq)) + | _ => + (* normal start at beginning of slot *) + if (c == OZCycle) then ( + let req := edf_slack_crit s slmap P in + (RUNNING s' slmap c' OSlot1 (Enqueue R (Dequeue req P)) req, (PRE, req))) + (* early-start optimisation *) + else ( + (* if arbitrating in the middle of slot, then priority rules chance, hence + the different argument sent to the scheduling function *) + let req := edf_slack_crit (Next_slot s OLastCycle) slmap P in + if (early_start s c slmap req) then + (RUNNING s' slmap c' OSlot1 (Enqueue R (Dequeue req P)) req, (PRE, req)) + else (IDLE s' slmap c' P', (NOP,req))) + end + | RUNNING s slmap c cnt_cmd P r => + let P' := Enqueue R P in + let s' := Next_slot s c in + let c' := Next_cycle c in + let cnt_cmd' := Next_cycle cnt_cmd in + if (cnt_cmd == OACT_date) then + (RUNNING s' slmap c' cnt_cmd' P' r, (ACT, r)) + else if (cnt_cmd == OCAS_date) then + (RUNNING s' slmap c' cnt_cmd' P' r, (Kind_of_req r, r)) + else if (cnt_cmd == OLastCycle) then + let req_id := r.(Requestor).(nb) in + (* slack can be gained in two ways: + either by request finishing in the middle of the slot or at the end *) + let slack' := if r.(Requestor).(crit) then + (SL.-1 - c) + ((dist SN (nat_of_ord s) req_id) * SL) else 0 in + (* replaces existing slack with new slack -- won't accumulate *) + let slmap' := NatMap.add req_id slack' slmap in + (IDLE s' slmap' c' P', (NOP, nullreq)) + else + (RUNNING s' slmap c' cnt_cmd' P' r, (NOP, nullreq)) + end. + + Definition Init_state R := + IDLE OZSlot empty_nat_map OZCycle (Enqueue R [::]). + + Instance TDMes_implementation : Implementation_t := + mkImplementation Init_state Next_state. + + Program Definition TDMes_arbitrate t := + mkTrace + (Default_arbitrate t).(Arbiter_Commands) + (Default_arbitrate t).(Arbiter_Time) + _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _. + Admit Obligations. + + Program Instance TDMes_arbiter : Arbiter_t := + mkArbiter AF TDMes_arbitrate _ _. + Admit Obligations. + +End TDMes. + +Section TDMes_sim. + + Program Instance SYS_CFG : System_configuration := + { + BANKGROUPS := 1; + BANKS := 8; + + T_BURST := 1; + T_WL := 1; + T_RRD_s := 1; + T_RRD_l := 3; + T_FAW := 20; + T_RC := 3; + T_RP := 1; + T_RCD := 1; + T_RAS := 4; + T_RTP := 4; + T_WR := 1; + T_RTW := 10; + T_WTR_s := 1; + T_WTR_l := 10; + T_CCD_s := 1; + T_CCD_l := 12; + + T_REFI := 10; + T_RFC := 10; + }. + + Program Instance TDMds_CFG : TDMds_configuration := + { + SN := 2; + SL := 8; + }. + + Existing Instance REQUESTOR_CFG. + Existing Instance TDMes_implementation. + Existing Instance TDMes_arbiter. + + Program Definition ReqA0 := mkReq + (mkRequestorSlack 0 true _) 2 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 5. + + Program Definition ReqB0 := mkReq (* 3 instead of 14 *) + (mkRequestorSlack 1 true _) 14 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 10. + + Program Definition ReqC0 := mkReq + (mkRequestorSlack 2 false _) 26 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0. + + Program Definition ReqB1 := mkReq + (mkRequestorSlack 1 true _) 28 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0. + + Program Definition ReqA1 := mkReq + (mkRequestorSlack 0 true _) 40 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0. + + Program Definition ReqC1 := mkReq + (mkRequestorSlack 2 false _) 40 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0. + + Program Definition ReqB2 := mkReq + (mkRequestorSlack 1 true _) 44 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0. + + Program Definition ReqA2 := mkReq + (mkRequestorSlack 0 true _) 62 RD (Nat_to_bankgroup 0) (Nat_to_bank 0) 0. + + Definition test_req_seq := [:: ReqA0;ReqB0;ReqC0;ReqB1;ReqA1;ReqC1;ReqB2;ReqA2]. + + Program Instance AF : Arrival_function_t := Default_arrival_function_t test_req_seq. + + Compute (Arbitrate 80).(Commands). + + (* Next: introduce the concepts of page open / closed *) + (* Do proofs about TDMes ? *) + +End TDMes_sim. \ No newline at end of file diff --git a/framework/DRAM/Trace.v b/framework/DRAM/Trace.v index 25d8708ff01bf47adb49499d13d4d5f86ee12bb2..31c3af57a502b6c14716f89713907487a83d24fb 100644 --- a/framework/DRAM/Trace.v +++ b/framework/DRAM/Trace.v @@ -1,5 +1,6 @@ Set Warnings "-notation-overridden,-parsing". Set Printing Projections. + From mathcomp Require Export ssreflect ssrnat ssrbool seq eqtype. From DRAM Require Export Commands. @@ -157,7 +158,7 @@ Section Trace. CWR_to_CRD a b -> Before a b -> ~~ Same_Bankgroup a b -> Apart_at_least a b (T_WTR_s + T_WL + T_BURST); - (* Ensure that the time between a CAS and a CAS commands respects T_CCD *) + (* Ensure that the time between a CAS and a CAS commaCWR_to_PREnds respects T_CCD *) Cmds_T_CCD_SBG_ok : forall a b, a \in Commands -> b \in Commands -> CRD_to_CRD a b \/ CWR_to_CWR a b -> Before a b -> Same_Bankgroup a b -> Apart_at_least a b T_CCD_l; @@ -165,6 +166,14 @@ Section Trace. Cmds_T_CCD_DBG_ok : BANKGROUPS > 1 -> forall a b, a \in Commands -> b \in Commands -> CRD_to_CRD a b \/ CWR_to_CWR a b -> Before a b -> ~~ Same_Bankgroup a b -> Apart_at_least a b T_CCD_s; + + (* Refresh related constraints *) + Cmds_T_RFC_ok : forall a b, a \in Commands -> b \in Commands -> + isREF a -> ~~ isNOP b -> Before a b -> Apart_at_least a b T_RFC; + + (* Upper bound *) + Cmds_T_REFI_ok : forall a b, a \in Commands -> b \in Commands -> + isREF a -> isREF b -> Before a b -> b.(CDate) <= a.(CDate) + 9 * T_REFI; (* ---------------------------------------------------------------------------------- *) @@ -195,6 +204,20 @@ Section Trace. (* Every CAS command is preceded by a matching ACT without another ACT or PRE in between *) Cmds_row_ok : forall b c, b \in Commands -> c \in Commands -> isCAS b -> isPRE c -> Same_Bank b c -> Before c b -> - exists a, (a \in Commands) && (isACT a) && (Same_Row a b) && (After a c) && (Before a b) + exists a, (a \in Commands) && (isACT a) && (Same_Row a b) && (After a c) && (Before a b); + + (* implies the init state of the memory *) + Cmds_initial : forall b, b \in Commands -> isCAS b -> + exists a, (a \in Commands) && (isACT a) && (Same_Row a b) && (Before a b); + + (* Banks must be idle for at least T_RFC cycles before a REF is issued *) + Cmds_REF_ok : forall ref, ref \in Commands -> + (exists prea, (prea \in Commands) && + (isPREA prea) && (Before prea ref) && (prea.(CDate) + T_RP <= ref.(CDate))) + \/ + (forall bank, bank \in All_banks -> exists pre, (pre \in Commands) && + (isPRE pre) && (Before pre ref) && (bank == pre.(Request).(Bank)) + && (pre.(CDate) + T_RP <= ref.(CDate))) }. + End Trace. \ No newline at end of file