diff --git a/TLAplus/FirstModels/TDMv1/TDM.tla b/TLAplus/FirstModels/TDMv1/TDM.tla new file mode 100644 index 0000000000000000000000000000000000000000..cc0d399ce12e95f6b766328c2bdc93b7c34135b4 --- /dev/null +++ b/TLAplus/FirstModels/TDMv1/TDM.tla @@ -0,0 +1,256 @@ +-------------------------------- MODULE TDM -------------------------------- +(***************************************************************************) +(* This is a simple TDM arbitration between memory requests *) +(* inside a DRAM controller *) +(***************************************************************************) +EXTENDS Integers, Reals, Sequences, SequencesExt + +CONSTANT + BANKS, + t_RCD, \* ACT to RD/WR + t_RP, \* PRE to ACT + t_RC, \* ACT to ACT + t_RAS, \* ACT to PRE + t_WL, \* WL to data bus + t_RL, \* RD to data bus + t_RTP, \* RD to PRE + t_WR, \* Enf of a WR to PRE + t_RRD, \* ACT to ACT + t_FAW, \* Four ACT window + t_RTW, + t_WR_to_RD, + t_WTR, + t_BURST, + t_CCD + +VARIABLES + time, + slotOwner, + bankState, \* last command sent to the bank + lastACT, + lastRD, + lastWR, + lastPRE, + lastBUS, + bus, + slotCounter + +BusDir == {"RD","WR"} +BusSta == BANKS \cup {"IDLE"} +tBANKS == SetToSeq(BANKS) + +TDMTypeOK == + /\ time \in Int + /\ slotOwner \in BANKS + /\ bankState \in [BANKS -> {"NOP","PRE","ACT","RD","WR"}] + /\ lastPRE \in [BANKS -> Int] + /\ lastACT \in [BANKS -> Int] + /\ lastRD \in [BANKS -> Int] + /\ lastWR \in [BANKS -> Int] + /\ lastBUS \in Int + /\ bus.ocup \in BusSta + /\ bus.dir \in BusDir + /\ slotCounter \in 1..Len(tBANKS) + +TDMInit == + /\ time = 0 + /\ slotOwner = CHOOSE b \in BANKS : TRUE + /\ bankState = [b \in BANKS |-> "NOP"] + /\ lastPRE = [b \in BANKS |-> 100] + /\ lastACT = [b \in BANKS |-> 100] + /\ lastRD = [b \in BANKS |-> 100] + /\ lastWR = [b \in BANKS |-> 100] + /\ lastBUS = 100 + /\ bus = [ocup |-> "IDLE", dir |-> CHOOSE dir \in {"RD","WR"} : TRUE] + /\ slotCounter = 1 + +----------------------------------------------------------------------------- +(***************************************************************************) +(* BUS ACTIONS *) +(***************************************************************************) +\* To use the bus, the demanding bank must respect the timing constraints and the bus has to be idle +UseBus(b) == /\ IF bankState[b] = "RD" THEN lastRD[b] >= t_RL + 1 + ELSE IF bankState[b] = "WR" THEN lastWR[b] >= t_WL + 1 + ELSE FALSE + \* Not optimal, since this restraints that bus can only be used once per slot + /\ lastBUS >= t_BURST + t_WR - 1 + t_RP + /\ bus.ocup = "IDLE" + /\ bus' = [ocup |-> b, dir |-> IF bankState[b] = "RD" THEN "RD" ELSE "WR"] + /\ lastBUS' = 0 + /\ UNCHANGED <<time,slotOwner,bankState,lastACT,lastPRE,lastRD,lastWR,slotCounter>> + +ReleaseBus(b) == /\ lastBUS >= t_BURST + /\ bus.ocup /= "IDLE" + /\ bus' = [bus EXCEPT !.ocup = "IDLE"] + /\ UNCHANGED <<time,slotOwner,bankState,lastACT,lastPRE,lastRD,lastWR,lastBUS,slotCounter>> +----------------------------------------------------------------------------- +(***************************************************************************) +(* THE SCHEDULER ACTIONS *) +(***************************************************************************) +ACTintraReady(b) == + /\ lastACT[b] >= t_RC + /\ lastPRE[b] >= t_RP + +ACTinterReady(b) == + /\ \A m \in BANKS \ {b} : /\ lastACT[m] >= t_RRD + /\ lastACT[m] >= t_FAW + +SchACT(b) == /\ bankState[b] = "PRE" \/ bankState[b] = "NOP" + \* We consider for now that an ACT can only be scheduled at the beginning of a TDM slot + /\ time = 0 + /\ slotOwner = b + /\ ACTintraReady(b) + /\ ACTinterReady(b) + /\ bankState' = [bankState EXCEPT ![b] = "ACT"] + /\ lastACT' = [lastACT EXCEPT ![b] = 0] + /\ UNCHANGED <<time,slotOwner,lastPRE,lastRD,lastWR,bus,lastBUS,slotCounter>> + +RDintraReady(b) == + /\ lastACT[b] >= t_RCD + /\ lastRD[b] >= t_CCD + /\ lastWR[b] >= t_WR_to_RD + +RDinterReady(b) == + /\ \A m \in BANKS \ {b} : /\ lastRD[m] >= t_CCD + /\ lastWR[m] >= t_WR_to_RD + /\ IF bus.dir = "WR" THEN lastBUS >= t_WTR + t_BURST ELSE TRUE + +SchRD(b) == /\ bankState[b] = "ACT" + /\ slotOwner = b + /\ RDintraReady(b) + /\ RDinterReady(b) + /\ bankState' = [bankState EXCEPT ![b] = "RD"] + /\ lastRD' = [lastRD EXCEPT ![b] = 0] + /\ UNCHANGED <<time,slotOwner,lastACT,lastPRE,lastWR,bus,lastBUS,slotCounter>> + +WRintraReady(b) == + /\ lastACT[b] >= t_RCD + /\ lastRD[b] >= t_RTW + /\ lastWR[b] >= t_CCD + +WRinterReady(b) == + /\ \A m \in BANKS \ {b} : /\ lastRD[m] >= t_RTW + /\ lastWR[m] >= t_CCD + +SchWR(b) == /\ bankState[b] = "ACT" /\ bankState[b] /= "PRE" + /\ slotOwner = b + /\ WRintraReady(b) + /\ WRinterReady(b) + /\ bankState' = [bankState EXCEPT ![b] = "WR"] + /\ lastWR' = [lastWR EXCEPT ![b] = 0] + /\ UNCHANGED <<time,slotOwner,lastACT,lastPRE,lastRD,bus,lastBUS,slotCounter>> + +PREintraReady(b) == + /\ lastACT[b] >= t_RAS + /\ lastRD [b] >= t_RTP + \* Not the best, this is considering there will be only one use of the BUS per slot + /\ IF bus.dir = "WR" THEN lastBUS >= t_WR - 1 + t_BURST ELSE TRUE + +SchPRE(b) == /\ bankState[b] = "RD" \/ bankState[b] = "WR" + /\ slotOwner = b + /\ PREintraReady(b) + /\ bankState' = [bankState EXCEPT ![b] = "PRE"] + /\ lastPRE' = [lastPRE EXCEPT ![b] = 0] + /\ UNCHANGED <<time,slotOwner,lastACT,lastRD,lastWR,bus,lastBUS,slotCounter>> + +UpdateSlotOwner == + /\ slotCounter' = IF slotCounter = Len(tBANKS) - 1 + THEN 1 + ELSE slotCounter + 1 + /\ slotOwner' = tBANKS[slotCounter+1] + +SlotLength == t_RCD + t_WL + t_BURST + t_WR + t_RP + +SchChange == /\ slotCounter =< 2 + /\ time >= SlotLength + /\ UpdateSlotOwner + /\ time' = 0 + /\ UNCHANGED <<bankState,lastACT,lastRD,lastWR,lastPRE,bus,lastBUS>> +----------------------------------------------------------------------------- +(***************************************************************************) +(* TIME ACTIONS *) +(***************************************************************************) +UpdateDelays == + /\ lastACT' = [b \in BANKS |-> lastACT[b] + 1] + /\ lastRD' = [b \in BANKS |-> lastRD[b] + 1] + /\ lastWR' = [b \in BANKS |-> lastWR[b] + 1] + /\ lastPRE' = [b \in BANKS |-> lastPRE[b] + 1] + /\ lastBUS' = lastBUS + 1 + +Step == + \* A step can only happen if scheduling / bus actions are not enabled + /\ \A b \in BANKS : /\ \neg (ENABLED SchACT(b)) + /\ \neg (ENABLED SchRD(b)) + /\ \neg (ENABLED SchWR(b)) + /\ \neg (ENABLED SchPRE(b)) + /\ \neg (ENABLED UseBus(b)) + /\ \neg (ENABLED ReleaseBus(b)) + /\ \neg (ENABLED SchChange) + /\ slotCounter =< 2 + /\ time' = time + 1 + /\ UpdateDelays + /\ UNCHANGED<<slotOwner,bankState,bus,slotCounter>> +----------------------------------------------------------------------------- +TDMNext == + \/ Step + \/ \E b \in BANKS : \/ SchACT(b) + \/ SchPRE(b) + \/ SchRD(b) + \/ SchWR(b) + \/ UseBus(b) + \/ ReleaseBus(b) + \/ SchChange +----------------------------------------------------------------------------- +vars == <<time,slotOwner,bankState,lastACT,lastPRE,lastRD,lastWR,lastBUS,bus,slotCounter>> +(***************************************************************************) +(* Stong fairness of TDMNext states that if there is a non stuttering *) +(* action possible TDMNext it must happen *) +(***************************************************************************) +TDMSpec == /\ TDMInit + /\ [][TDMNext]_vars + /\ SF_vars(TDMNext) +----------------------------------------------------------------------------- +\* Temporal properties +(***************************************************************************) +(* TDMTemp1 states that if a RD or a WR has been scheduled to a certain *) +(* bank, then the bus will eventually by occupied by the requestor *) +(* TDMTemp2 states that if a requestor owns the slot that eventually a RD *) +(* will be issued *) +(***************************************************************************) +\* How can I check that things happen in the same slot (time < 0) ? +TDMTemp1 == + /\ \A b \in BANKS : bankState[b] \in {"RD","WR"} ~> bus.ocup = b + +TDMTemp2 == + /\ \A b \in BANKS : slotOwner = b ~> bankState[b] = "RD" + +\* Ensures that changing slots will happen +TDMChange == + []<><<SchChange>>_vars + +TDMLimit == + <>(slotCounter = 3) +----------------------------------------------------------------------------- +\*Invariants +(***************************************************************************) +(* TDMValidity1 states that if a RD or a WR has been scheduled for a *) +(* certain bank, than the requestor owner of that bank owns the TDM slot *) +(* TDMValidity2 states that if a certain bank b doesn't own the slot, than *) +(* the last command sent to it must have been a NOP or a PRE *) +(***************************************************************************) +TDMValidity1 == + /\ \A b \in BANKS : bankState[b] \in {"RD","WR"} => slotOwner = b + +TDMValidity2 == + /\ \A b \in BANKS : slotOwner /= b => bankState[b] \in {"NOP", "PRE"} + +IntraBankConstraints == + /\ \A b \in BANKS : CASE ENABLED SchRD(b) -> lastACT[b] >= t_RCD /\ lastRD[b] >= t_RTW /\ lastWR[b] >= t_WR_to_RD + [] ENABLED SchWR(b) -> lastACT[b] >= t_RCD /\ lastRD[b] >= t_RTW /\ lastWR[b] >= t_CCD + [] ENABLED SchACT(b) -> lastACT[b] >= t_RC /\ lastPRE[b] >= t_RP + [] ENABLED SchPRE(b) -> lastACT[b] >= t_RAS /\ lastRD [b] >= t_RTP /\ IF bus.dir = "WR" THEN lastBUS >= t_WR - 1 + t_BURST ELSE TRUE + [] OTHER -> TRUE +============================================================================= +\* Modification History +\* Last modified Wed Feb 10 11:42:39 CET 2021 by felipe +\* Created Mon Jan 18 10:05:32 CET 2021 by felipe diff --git a/TLAplus/FirstModels/TDMv2/TDMv2.tla b/TLAplus/FirstModels/TDMv2/TDMv2.tla new file mode 100644 index 0000000000000000000000000000000000000000..506641985732848cc2462e2125565fb986157d7e --- /dev/null +++ b/TLAplus/FirstModels/TDMv2/TDMv2.tla @@ -0,0 +1,78 @@ +------------------------------- MODULE TDMv2 ------------------------------- +(***************************************************************************) +(* This is the functional module explaining the working mechanisms of TDM, *) +(* time related expressions are decribed in RealTimeNew *) +(***************************************************************************) +EXTENDS Integers, Reals, Sequences, SequencesExt, FiniteSets + +CONSTANTS BANKS, REQUESTORS + +\* On a private bank policy, each requestor is served in a different DRAM bank +ASSUME Cardinality(BANKS) = Cardinality(REQUESTORS) + +\* This is the set of banks converted to a sequence (tuple) +tBANKS == SetToSeq(BANKS) + +VARIABLES + slotOwner, + slotCounter, + lastCmd, + bus_dir, + bus_status + +BusDir == {"RD","WR"} +BusStatus == {"IDLE","BUSY"} + +TypeOK == + /\ slotOwner \in BANKS + /\ slotCounter \in 1..Len(tBANKS) + /\ lastCmd \in [BANKS -> {"NOP","PRE","ACT","RD","WR"}] + /\ bus_dir \in BusDir + /\ bus_status \in BusStatus +----------------------------------------------------------------------------- +(***************************************************************************) +(* Initial Predicate *) +(***************************************************************************) +Init == + /\ slotOwner = CHOOSE b \in BANKS : TRUE + /\ slotCounter = 0 + /\ lastCmd = [b \in BANKS |-> "NOP"] + /\ bus_dir = CHOOSE v \in BusDir : TRUE + /\ bus_status = CHOOSE v \in BusStatus : TRUE + +(***************************************************************************) +(* Scheduler Actions *) +(***************************************************************************) +IssueACT(b) == /\ lastCmd[b] \in {"NOP","PRE"} + /\ slotOwner = b + /\ lastCmd' = [lastCmd EXCEPT ![b] = "ACT"] + /\ UNCHANGED <<slotOwner,slotCounter,bus_dir,bus_status>> + +IssueRD(b) == + +IssueWR(b) == + +IssuePRE(b) == + +UseBus(b) == + +ReleaseBus(b) == + +SchChange == + +Next == + \/ \E b \in BANKS : \/ IssueACT(b) + \/ IssueRD(b) + \/ IssueWR(b) + \/ IssuePRE(b) + \/ UseBus(b) + \/ ReleaseBus(b) + \/ SchChange +----------------------------------------------------------------------------- +vars == <<slotOwner,SlotCounter,lastCmd,bus_dir,bus_status>> +L == WF_vars(Next) +Spec == Init /\ [][Next]_vars /\ L +============================================================================= +\* Modification History +\* Last modified Fri Feb 12 15:42:19 CET 2021 by felipe +\* Created Fri Feb 12 11:43:19 CET 2021 by felipe diff --git a/TLAplus/FirstModels/TDMv3/TDMv3.tla b/TLAplus/FirstModels/TDMv3/TDMv3.tla new file mode 100644 index 0000000000000000000000000000000000000000..e1fab612bf1c9ae19138d2fcfd5abc10cf9c00b9 --- /dev/null +++ b/TLAplus/FirstModels/TDMv3/TDMv3.tla @@ -0,0 +1,288 @@ +------------------------------- MODULE TDMv3 ------------------------------- +EXTENDS Naturals, FiniteSets, Sequences, SequencesExt + +(***************************************************************************) +(* Utility functions *) +(***************************************************************************) +Max(S) == CHOOSE x \in S : \A y \in S : x >= y +Min(S) == CHOOSE x \in S : \A y \in S : x =< y +ModuloSum(a,b,max) == IF a + b =< max THEN a + b ELSE max - ((a+b)%max) + +CONSTANTS + CrRq, \* The set of critical requestors + NCrRq, \* The set of non-critical requestors + AllBanks, \* The set of DRAM private banks + Mapping, \* Bank Adress Maping + TDM_Slot, \* The length of the TDM slot + Queue_Capacity \* The capacity of the request queue + +\*This produces a function that maps requestors to banks +Requestors == CrRq \cup NCrRq +tMapping == SetToSeq(Mapping) +BankMapping == [req \in Requestors |-> tMapping[req]] + +ASSUME + /\ Cardinality(Requestors) = Cardinality(Mapping) + +NumberOfSlots == Cardinality(CrRq) + +(***************************************************************************) +(* In TLA+ language, arrays are functions, and can be also seen as a hash *) +(* map. A record is a analogue to a data structure, where which field is *) +(* also a function. So, it can also be seen as a two variable function, *) +(* or a matrix. And finally, in this module, we have a tuple (or *) +(* sequence) of records, which is analogue to 3d function *) +(***************************************************************************) + +VARIABLES + time, + control, + req_under_treatment, + queue, + request_count, + slot_count, + slot_owner, + row_buffer, + slack, + bank_state, + timer + +vars == <<time,control,req_under_treatment,queue,request_count, + slot_count,slot_owner,row_buffer,slack,bank_state,timer>> + +CMDS == {"NOP","ACT","RD","BUS","WR","PRE","REF"} +Control == {"IDLE","ARRIVAL","TREATMENT","COMPLETED"} + +\*Limit the model checking +max_time == 50 +max_slots == 10 +max_requests == 100 + +\* For now there are no type constraints on : queue, req_under_treatment + +TypeOK == + /\ time \in 0..500 + /\ control \in Control + /\ request_count \in [Requestors -> 0..max_requests] + /\ slot_count \in 1..10 + /\ slot_owner \in 1..NumberOfSlots + /\ row_buffer \in [AllBanks -> {"OPEN","CLOSED"}] + /\ slack \in [CrRq -> Nat] + /\ bank_state \in [AllBanks -> CMDS] + +(***************************************************************************) +(* O problema de usar o modelo com contatdores e clocks (ideal e seguro) é *) +(* a complexidade de checagem do modelo. Pode-se argumentar então que o *) +(* modelo aqui representado não corresponde exatamente ao controlador. O *) +(* controlador implementado em hardware seria correto por design (timing *) +(* constraints usadas como contadores) ou baseado em um modelo tal que *) +(* esse? O controlador desta especificação não representa o mesmo da outra *) +(***************************************************************************) +----------------------------------------------------------------------------- +(***************************************************************************) +(* Init state predicate *) +(***************************************************************************) +Init == + /\ time = 0 + /\ control = "IDLE" + /\ req_under_treatment = [type |-> "NONE", + deadline |-> 0, + target |-> "NONE", + number |-> 0, + owner |-> 0, + issue_date |-> 0, + delayed_issue_date |-> 0, + hit_miss |-> "NONE"] + /\ queue = <<>> + /\ request_count = [r \in Requestors |-> 0] + /\ slot_count = 1 + /\ slot_owner = 1 + /\ row_buffer = [b \in AllBanks |-> "CLOSED"] + /\ slack = [req \in CrRq |-> 0] + /\ bank_state = [b \in AllBanks |-> "NOP"] + /\ timer = 0 +----------------------------------------------------------------------------- +(***************************************************************************) +(* Actions that representing the issuing of DRAM commands, they are the *) +(* only ones that enable time to elapse *) +(***************************************************************************) +IssueACT(bank) == + /\ control = "TREATMENT" + /\ bank_state[bank] = "ACT" + /\ time' = time + 1 + /\ bank_state' = IF req_under_treatment.type = "RD" + THEN [bank_state EXCEPT ![bank] = "RD"] + ELSE [bank_state EXCEPT ![bank] = "WR"] + /\ UNCHANGED<<control,req_under_treatment,queue,request_count, + slot_count,slot_owner,row_buffer,slack,timer>> + +IssueRD(bank) == +LET t_RCD == 6 +IN /\ control = "TREATMENT" + /\ bank_state[bank] = "RD" + /\ time' = time + t_RCD + /\ bank_state' = [bank_state EXCEPT ![bank] = "BUS"] + /\ UNCHANGED<<control,req_under_treatment,queue,request_count, + slot_count,slot_owner,row_buffer,slack,timer>> + +IssueWR(bank) == +LET t_RCD == 6 +IN /\ control = "TREATMENT" + /\ bank_state[bank] = "WR" + /\ time' = time + t_RCD + /\ bank_state' = [bank_state EXCEPT ![bank] = "BUS"] + /\ UNCHANGED<<control,req_under_treatment,queue,request_count, + slot_count,slot_owner,row_buffer,slack,timer>> + +\* For RD requests, the PRE command can be issued instanteneously, as for WR requests +\* there is a WR to PRE timing constraint +IssuePRE(bank) == +LET t_WR == 6 + t_RTP == 4 + t_RL == 6 + t_BURST == 4 +IN /\ control = "TREATMENT" + /\ control' = "COMPLETED" + /\ bank_state[bank] = "PRE" + /\ time' = IF req_under_treatment.type = "WR" + THEN time + t_WR + ELSE IF t_RTP >= t_RL + t_BURST + THEN time + t_RTP - (t_RL + t_BURST) + ELSE time + /\ bank_state' = [bank_state EXCEPT ![bank] = "NOP"] + /\ req_under_treatment' = [req_under_treatment EXCEPT !.owner = 0] + /\ UNCHANGED<<queue,request_count, + slot_count,slot_owner,row_buffer,slack,timer>> + +UsingBus(bank) == +LET t_RL == 6 + t_WL == 5 + t_BURST == 4 +IN /\ control = "TREATMENT" + /\ bank_state[bank] = "BUS" + /\ time' = IF req_under_treatment.type = "RD" + THEN time + t_RL + t_BURST + ELSE time + t_WL + t_BURST + /\ bank_state' = [bank_state EXCEPT ![bank] = "PRE"] + /\ UNCHANGED<<control,req_under_treatment,queue,request_count, + slot_count,slot_owner,row_buffer,slack,timer>> +----------------------------------------------------------------------------- +\* Have to create a completed action, which will say +(***************************************************************************) +(* This action has to do the following things 1. Decide which is the next *) +(* request (on the request queue) is to be treated 2. Decide which *) +(* is the order of commands that has to be issued for that request 3. *) +(* Decide to leave the row buffer open or closed based on the amount of *) +(* slack gained. *) +(***************************************************************************) +\* Slacks are already considered in the delayed issue date, so, among all requests +\* in the queue, we choose from EDF. +treat_request == +LET deadlines == {queue[n].deadline : n \in 1..Len(queue)} + min_deadline == Min(deadlines) + selected_req == SelectSeq(queue, LAMBDA elem: elem.deadline = min_deadline)[1] + StartTreatment == /\ queue' = Remove(queue,selected_req) + /\ req_under_treatment' = selected_req + /\ bank_state' = [bank_state EXCEPT ![selected_req.target] = "ACT"] + ResumeTreatment == UNCHANGED<<queue,req_under_treatment,bank_state>> +IN /\ (control = "ARRIVAL") \/ (control = "COMPLETE" \/ queue /= <<>>) + /\ control' = "TREATMENT" + /\ IF req_under_treatment.owner = 0 + THEN StartTreatment + ELSE ResumeTreatment + /\ UNCHANGED<<time,request_count,slot_count,slot_owner,row_buffer,slack,timer>> +----------------------------------------------------------------------------- +(***************************************************************************) +(* Actions that model the arrival of new tasks into the system. They are *) +(* stored in the request queue. *) +(***************************************************************************) +\* so_did -> slot owner of the delayed issue date +\* dist -> distance to the next slot owned by the requestor +request_arrival(req,ty,hm,arrival_rate) == +LET so_did == IF slack[req] >= (slot_count*TDM_Slot - time) + THEN ModuloSum((slack[req]%TDM_Slot)+1,slot_owner,NumberOfSlots) + ELSE slot_owner + dist == IF (time = TDM_Slot*(slot_count - 1)) /\ (req = slot_owner) + THEN 0 + ELSE IF req = so_did + THEN NumberOfSlots + ELSE IF req - so_did >= 0 THEN req - so_did ELSE so_did - req + calc_deadline == IF req \in CrRq + THEN TDM_Slot*(slot_count + dist) + ELSE TDM_Slot*(slot_count + 1) + request_instance == [number |-> request_count[req] + 1, + owner |-> req, + target |-> BankMapping[req], + issue_date |-> time, + delayed_issue_date |-> time + slack[req], + deadline |-> calc_deadline, + type |-> ty, + hit_miss |-> hm] +\* Requist arrival +\* 1. Only one request per requestor in the queue +\* 2. No consecutive arrivals +\* 3. There are at least arrival_rate cycles between two requests of the same requestor +IN /\ req \notin {queue[n].owner : n \in 1..Len(queue)} + /\ control /= "ARRIVAL" + /\ time - request_count[req]*arrival_rate >= 0 + /\ control' = "ARRIVAL" + /\ request_count' = [request_count EXCEPT ![req] = request_count[req] + 1] + /\ queue' = Append(queue,request_instance) + /\ UNCHANGED<<time,req_under_treatment,slot_count,slot_owner,row_buffer,slack,bank_state,timer>> +----------------------------------------------------------------------------- +\* From RealTimeNew Module +IntervalLB(t,Acts,B,v,min,lb) == +LET TNext == t' = IF <<B>>_v \/ \neg(ENABLED <<Acts \/ B>>_v)' + THEN 0 + ELSE t + (time' - time) + LowerBound == B => IF lb THEN t >= min ELSE t > min +IN /\ TNext + /\ LowerBound +----------------------------------------------------------------------------- +(***************************************************************************) +(* Next Predicate *) +(***************************************************************************) +Next == + \/ request_arrival(1,"RD","HIT",10) + \/ request_arrival(2,"WR","HIT",20) + \/ treat_request + \/ \E b \in AllBanks : \/ IssueACT(b) + \/ IssueRD(b) + \/ IssueWR(b) + \/ IssuePRE(b) + \/ UsingBus(b) + /\ LET t_RCD == 6 IN \A b \in AllBanks: IntervalLB(timer,TRUE,IssueRD(b),vars,t_RCD,TRUE) +----------------------------------------------------------------------------- +(***************************************************************************) +(* Fairness and Temporal Formula *) +(***************************************************************************) +L == /\ WF_vars(request_arrival(1,"RD","HIT",10)) + /\ WF_vars(request_arrival(2,"WR","HIT",12)) + /\ WF_vars(treat_request) + /\ \A b \in AllBanks : /\ SF_vars(IssueACT(b)) + /\ SF_vars(IssueRD(b)) + /\ SF_vars(IssueWR(b)) + /\ SF_vars(UsingBus(b)) + /\ SF_vars(IssuePRE(b)) + +Spec == Init /\ [][Next]_vars /\ L +----------------------------------------------------------------------------- +(***************************************************************************) +(* Invariants *) +(***************************************************************************) +\* The queue never becomes full +FullQueue == Len(queue) =< Queue_Capacity +\* The queue never has two requests of the same requestor +OneRequestInTheQueue == +LET Owners == {queue[n].owner : n \in 1..Len(queue)} +IN \A requestor \in Requestors : Cardinality({owner \in Owners : owner = requestor}) =< 1 + +(***************************************************************************) +(* Temporal Properties *) +(***************************************************************************) +\* Requests are eventually served +MaxTime == <>(time = max_time) +============================================================================= +\* Modification History +\* Last modified Fri Feb 26 18:53:51 CET 2021 by felipe +\* Created Fri Feb 19 10:11:16 CET 2021 by felipe diff --git a/TLAplus/FirstModels/TDMv4/TDMv4.tla b/TLAplus/FirstModels/TDMv4/TDMv4.tla new file mode 100644 index 0000000000000000000000000000000000000000..f78fba0cd0213c8203b859d42d3a3e4217c928c0 --- /dev/null +++ b/TLAplus/FirstModels/TDMv4/TDMv4.tla @@ -0,0 +1,147 @@ +------------------------------- MODULE TDMv4 ------------------------------- +EXTENDS Naturals, FiniteSets, Sequences, SequencesExt + +(***************************************************************************) +(* Utility functions *) +(***************************************************************************) +Max(S) == CHOOSE x \in S : \A y \in S : x >= y +Min(S) == CHOOSE x \in S : \A y \in S : x =< y +ModuloSum(a,b,max) == IF a + b =< max THEN a + b ELSE max - ((a+b)%max) +----------------------------------------------------------------------------- + +CONSTANTS + CrRq, \* The set of critical requestors + NCrRq, \* The set of non-critical requestors + AllBanks, \* The set of DRAM private banks + Mapping, \* Bank Adress Maping + TDM_Slot, \* The length of the TDM slot + Queue_Capacity \* The capacity of the request queue + +\*This produces a function that maps requestors to banks +Requestors == CrRq \cup NCrRq +tMapping == SetToSeq(Mapping) +BankMapping == [req \in Requestors |-> tMapping[req]] + +ASSUME + /\ Cardinality(Requestors) = Cardinality(Mapping) + +NumberOfSlots == Cardinality(CrRq) + +\* Total : 15 variables. Is this too much ? +VARIABLES + time, + lastACT, + lastRD, + lastWR, + lastPRE, + lastBUS, + control, + req_under_treatment, + req_queue, + req_count, + slot_count, + slot_owner, + bank_state, + row_buffer, + slack, + bus + +vars == <<time, lastACT, lastRD, lastWR, lastPRE, lastBUS, + control, req_under_treatment, req_queue, req_count, slot_count, slot_owner, + bank_state, row_buffer, slack, bus>> + +\* Auxiliary sets +Control == {"IDLE","ARRIVAL","TREATMENT","COMPLETED"} +CMDS == {"NOP","ACT","RD","BUS","WR","PRE","REF"} + +\* Simulation bounds +max_time == 100 +max_requests == 10 +max_slots == 50 + +\* Timing constraints +t_RCD == 6 +t_RP == 6 +t_RC == 21 +t_RAS == 15 +t_WL == 5 +t_RL == 6 +t_RTP == 4 +t_WR == 6 +t_RRD == 4 +t_FAW == 5 +t_RTW == 7 +t_WRtoRD == 13 +t_WTR == 4 +t_BURST == 4 +t_CCD == 4 + +\* Some variables (for now) don`t have type invariance. +TypeOK == + /\ time \in 0..max_time + /\ lastACT \in [AllBanks -> Nat] + /\ lastRD \in [AllBanks -> Nat] + /\ lastWR \in [AllBanks -> Nat] + /\ lastPRE \in [AllBanks -> Nat] + /\ lastBUS \in Nat + /\ control \in Control + /\ req_count \in [Requestors -> 0..max_requests] + /\ slot_count \in 1..max_slots + /\ slot_owner \in 1..NumberOfSlots + /\ bank_state \in [AllBanks -> CMDS] + /\ row_buffer \in [AllBanks -> {"OPEN","CLOSED"}] + /\ slack \in [CrRq -> Nat] +----------------------------------------------------------------------------- +(***************************************************************************) +(* The Initial Predicate *) +(***************************************************************************) +Init == + /\ time = 0 + /\ lastACT = [b \in AllBanks |-> 100] + /\ lastRD = [b \in AllBanks |-> 100] + /\ lastWR = [b \in AllBanks |-> 100] + /\ lastPRE = [b \in AllBanks |-> 100] + /\ lastBUS = 100 + /\ control = "IDLE" + /\ req_under_treatment = [type |-> "NONE", + deadline |-> 0, + target |-> "NONE", + number |-> 0, + owner |-> 0, + issue_date |-> 0, + delayed_issue_date |-> 0, + hit_miss |-> "NONE"] + /\ req_queue = <<>> + /\ req_count = [r \in Requestors |-> 0] + /\ slot_count = 1 + /\ slot_owner = 1 + /\ bank_state = [b \in AllBanks |-> "NOP"] + /\ row_buffer = [b \in AllBanks |-> "CLOSED"] + /\ slack = [req \in CrRq |-> 0] + /\ bus = [ocup |-> "IDLE", dir |-> CHOOSE dir \in {"RD","WR"} : TRUE] + +----------------------------------------------------------------------------- +(***************************************************************************) +(* DRAM commmands *) +(***************************************************************************) +\* Commands are only available when they are intra or inter ready. This ensures +\* time correctness by design. +IssueACT(b) == +LET + ACTintraReady == /\ lastACT[b] >= t_RC /\ lastPRE[b] >= t_RP + ACTinterReady == \A m \in AllBanks \ {b} : /\ lastACT[m] >= t_RRD /\ lastACT[m] >= t_FAW +IN + /\ control = "TREATMENT" + /\ bank_state[b] = "ACT" + /\ ACTintraReady + /\ ACTinterReady + /\ bank_state' = IF req_under_treatment.type = "RD" + THEN [bank_state EXCEPT ![b] = "RD"] + ELSE [bank_state EXCEPT ![b] = "WR"] + /\ UNCHANGED SetToSeq({{vars[n] : n \in 1..Len(vars)} \ bank_state}) + + +============================================================================= +\* Modification History +\* Last modified Fri Feb 26 20:28:30 CET 2021 by felipe +\* Created Fri Feb 26 18:57:44 CET 2021 by felipe diff --git a/TLAplus/FirstModels/TDMv5/TDMv5.tla b/TLAplus/FirstModels/TDMv5/TDMv5.tla new file mode 100644 index 0000000000000000000000000000000000000000..f74d19b3074f61286ad3207edb24250efe2690b4 --- /dev/null +++ b/TLAplus/FirstModels/TDMv5/TDMv5.tla @@ -0,0 +1,295 @@ +------------------------------- MODULE TDMv5 ------------------------------- +EXTENDS Integers, FiniteSets, Sequences, SequencesExt + +\* Utility predicates +Max2Numbers(a,b) == IF a >= b THEN a ELSE b +Max(S) == CHOOSE x \in S : \A y \in S : x >= y +Min(S) == CHOOSE x \in S : \A y \in S : x =< y +ModuloSum(a,b,max) == IF a + b =< max THEN a + b ELSE max - ((a+b)%max) + +CONSTANTS + \* Intra-bank constraints + t_RCD, + t_RP, + t_RC, + t_RAS, + t_RL, + t_WL, + t_RTP, + t_WR, + \* Inter-bank constraints + t_RRD, + \* Inter- and intra-bank constraints + t_RTW, + t_WRtoRD, + t_CCD, + t_WTR, + t_BURST, + \* Other constants + Banks, + CrRq, + NCrRq, + Mapping, + Queue_Capacity + +\* This creates a function that maps each requestor to a bank +Requestors == CrRq \cup NCrRq +tMapping == SetToSeq(Mapping) +BankMapping == [req \in Requestors |-> tMapping[req]] +\* Length of the TDM slot. Worst case is a write miss +TDM_Slot == t_RCD + t_WL + t_BURST + t_WR + t_RP + 1 +\* Peridiocity of the TDM +TDM_Period == Cardinality(CrRq) + +ASSUME + /\ Cardinality(Requestors) = Cardinality(Mapping) + +VARIABLES + cmds_lbtimer, \* Lower bound timers, used for expressing timing constraints. There is one per bank per command type. + arvl_lbtimer, \* Upper bound timers, used for modelling arrival of requests. There is one per requestor. Could be any type of timer. SF required. + chsl_lbtimer, \* Lower bound timer, used for modelling the change in slot_owner. Coulbe be any type of timer. SF required. + now, \* Current time + bank_state, \* Used to control the issue of commands to each bank + queue, \* A sequence of records containing the requests that have arrived in the system + req_under_treatment, \* A record representing the request currently under treatment + request_count, \* Counts how many requests per requestor have arrived + slot_count, \* Counts how many TDM slots have elapsed at total + slot_owner, \* The requestor who currently owns the TDM slot + row_buffer, \* A function that maps banks to a row buffer situation, i.e open or closed + slack, \* A function that maps each critical request to a value of slack + control \* A variable that controls the general advance of the system + +vars == <<cmds_lbtimer,arvl_lbtimer,chsl_lbtimer,now, + bank_state,queue,req_under_treatment,request_count,slot_count,slot_owner,row_buffer,slack,control>> + +\* Auxiliary sets +CMDS == {"IDLE","USEBUS","RLSBUS","ACT","RD","WR","PRE"} +CONTROL == {"INIT","ARRIVAL","TREATMENT","COMPLETED"} +----------------------------------------------------------------------------- +\* What is the rule for changing the slot owner ? Have to make an action for that ? +\* How to express the type predicate for cmds_lbtimer ? +\* Bounding time for now +maxtime == 100 +----------------------------------------------------------------------------- +TimeTypeOK == + \* /\ cmds_lbtimer \in [Banks \X {CMDS \{"IDLE"}} -> Int] + /\ arvl_lbtimer \in [Requestors -> Int] + /\ chsl_lbtimer \in Int + /\ now \in 0..maxtime + +\* No type invariance for now : req_under_treatment, queue +TypeOK == + /\ bank_state \in [Banks -> CMDS] + /\ request_count \in [Requestors -> Nat] + /\ slot_count \in Nat + /\ slot_owner \in 1..Cardinality(CrRq) + /\ row_buffer \in [Banks -> {"OPEN","CLOSED"}] + /\ slack \in [CrRq -> Nat] + /\ control \in CONTROL + +Init == + /\ cmds_lbtimer = [b \in Banks, c \in CMDS\{"IDLE"} |-> 0] + /\ arvl_lbtimer = [req \in Requestors |-> 0] + /\ chsl_lbtimer = 0 + /\ now = 0 + /\ bank_state = [b \in Banks |-> "IDLE"] + /\ req_under_treatment = [type |-> "NONE", + deadline |-> 0, + target |-> "NONE", + number |-> 0, + owner |-> 0, + issue_date |-> 0, + delayed_issue_date |-> 0, + hit_miss |-> "NONE"] + /\ queue = <<>> + /\ request_count = [r \in Requestors |-> 0] + /\ slot_count = 1 + /\ slot_owner = 1 + /\ row_buffer = [b \in Banks |-> "CLOSED"] + /\ slack = [req \in CrRq |-> 0] + /\ control = "INIT" +----------------------------------------------------------------------------- +Set2dimTimer(a,b,timer,value) == timer' = [timer EXCEPT ![a,b] = value] +Set1dimTimer(a,timer,value) == timer' = [timer EXCEPT ![a] = value] +TimedOut_2dim(a,b,timer) == timer[a,b] = 0 +TimedOut_1dim(a,timer) == timer[a] = 0 +----------------------------------------------------------------------------- +IssueACT(this_bank) == + /\ bank_state[this_bank] = "ACT" + /\ control = "TREATMENT" + /\ bank_state' = [bank_state EXCEPT ![this_bank] = "RD"] + /\ UNCHANGED<<arvl_lbtimer,chsl_lbtimer,now,queue,req_under_treatment,request_count,slot_count,slot_owner,row_buffer,slack,control>> + +IssueRD(this_bank) == + /\ bank_state[this_bank] = "RD" + /\ control = "TREATMENT" + \* Checks if command is both intra and inter-ready + /\ \A bank \in Banks : TimedOut_2dim(bank,"RD",cmds_lbtimer) + \* Sets intra bank timers + /\ Set2dimTimer(this_bank,"USEBUS",cmds_lbtimer,t_RL) + /\ Set2dimTimer(this_bank,"PRE",cmds_lbtimer,t_RTP) + \* Sets inter and inter bank timers + /\ \A bank \in Banks : /\ Set2dimTimer(bank,"WR",cmds_lbtimer,t_RTW) + /\ Set2dimTimer(bank,"RD",cmds_lbtimer,t_CCD) + /\ bank_state' = [bank_state EXCEPT ![this_bank] = "USEBUS"] + /\ UNCHANGED<<arvl_lbtimer,chsl_lbtimer,now,queue,req_under_treatment,request_count, + slot_count,slot_owner,row_buffer,slack,control>> + +IssueWR(this_bank) == + /\ bank_state[this_bank] = "WR" + /\ control = "TREATMENT" + \* Checks if command is both intra and inter-ready + /\ \A bank \in Banks : TimedOut_2dim(bank,"RD",cmds_lbtimer) + \* Sets intra bank timers + /\ Set2dimTimer(this_bank,"USEBUS",cmds_lbtimer,t_WL) + /\ Set2dimTimer(this_bank,"PRE",cmds_lbtimer,t_RTP) + \* Sets inter bank timers + /\ \A other_bank \in Banks \ {this_bank} : Set2dimTimer(other_bank,"RD",cmds_lbtimer,t_WRtoRD) + /\ bank_state' = [bank_state EXCEPT ![this_bank] = "USEBUS"] + /\ UNCHANGED<<arvl_lbtimer,chsl_lbtimer,now,queue,req_under_treatment,request_count, + slot_count,slot_owner,row_buffer,slack,control>> + +UseBus(this_bank) == + /\ bank_state[this_bank] = "USEBUS" + /\ control = "TREATMENT" + /\ \A bank \in Banks : TimedOut_2dim(bank,"USEBUS",cmds_lbtimer) + /\ \A bank \in Banks : Set2dimTimer(bank,"RLSBUS",cmds_lbtimer,t_BURST) + /\ bank_state' = [bank_state EXCEPT ![this_bank] = "RLSBUS"] + /\ UNCHANGED<<arvl_lbtimer,chsl_lbtimer,now,queue,req_under_treatment,request_count, + slot_count,slot_owner,row_buffer,slack,control>> + +ReleaseBus(this_bank) == + /\ bank_state[this_bank] = "RLSBUS" + /\ control = "TREATMENT" + /\ \A bank \in Banks : TimedOut_2dim(bank,"RLSBUS",cmds_lbtimer) + /\ IF req_under_treatment.type = "WR" + THEN Set2dimTimer(this_bank,"PRE",cmds_lbtimer,t_WR) + ELSE TRUE + /\ \A bank \in Banks : IF req_under_treatment.type = "WR" + THEN Set2dimTimer(bank,"RD",cmds_lbtimer,t_WTR) + ELSE TRUE + /\ bank_state' = [bank_state EXCEPT ![this_bank] = "PRE"] + /\ UNCHANGED<<arvl_lbtimer,chsl_lbtimer,now,queue,req_under_treatment,request_count, + slot_count,slot_owner,row_buffer,slack,control>> + +IssuePRE(this_bank) == + /\ bank_state[this_bank] = "PRE" + /\ control = "TREATMENT" + /\ \A bank \in Banks : TimedOut_2dim(bank,"PRE",cmds_lbtimer) + \* Intra-bank : PRE to ACT + /\ Set2dimTimer(this_bank,"ACT",cmds_lbtimer,t_RP) + \* Complection : bank becomes idle again + /\ bank_state' = [bank_state EXCEPT ![this_bank] = "IDLE"] + /\ UNCHANGED<<arvl_lbtimer,chsl_lbtimer,now,queue,req_under_treatment,request_count, + slot_count,slot_owner,row_buffer,slack,control>> +----------------------------------------------------------------------------- +treat_request == +LET deadlines == {queue[n].deadline : n \in 1..Len(queue)} + min_deadline == Min(deadlines) + selected_req == SelectSeq(queue, LAMBDA elem: elem.deadline = min_deadline)[1] + StartTreatment == /\ queue' = Remove(queue,selected_req) + /\ req_under_treatment' = selected_req + /\ bank_state' = [bank_state EXCEPT ![selected_req.target] = "ACT"] + ResumeTreatment == UNCHANGED<<queue,req_under_treatment,bank_state>> +IN /\ (control = "ARRIVAL") \/ (control = "COMPLETE" /\ queue /= <<>>) + /\ control' = "TREATMENT" + /\ IF req_under_treatment.owner = 0 + THEN StartTreatment + ELSE ResumeTreatment + /\ UNCHANGED<<arvl_lbtimer,cmds_lbtimer,chsl_lbtimer,now,request_count,slot_count,slot_owner, + row_buffer,slack>> +----------------------------------------------------------------------------- +\* so_did : slot owner considering the delayed issue date +\* dist : distance to the next slot owned by the requestor +request_arrival(req,ty,hm,arrival_rate) == +LET so_did == IF slack[req] >= (slot_count*TDM_Slot - now) + THEN ModuloSum((slack[req]%TDM_Slot)+1,slot_owner,TDM_Period) + ELSE slot_owner + dist == IF (now = TDM_Slot*(slot_count - 1)) /\ (req = slot_owner) + THEN 0 + ELSE IF req = so_did + THEN TDM_Period + ELSE IF req - so_did >= 0 + THEN req - so_did + ELSE so_did - req + calc_deadline == IF req \in CrRq + THEN TDM_Slot*(slot_count + dist) + ELSE TDM_Slot*(slot_count + 1) + request_instance == [number |-> request_count[req] + 1, + owner |-> req, + target |-> BankMapping[req], + issue_date |-> now, + delayed_issue_date |-> now + slack[req], + deadline |-> calc_deadline, + type |-> ty, + hit_miss |-> hm, + period |-> arrival_rate] +IN \* Only one request per requestor in the queue + /\ req \notin {queue[n].owner : n \in 1..Len(queue)} + \* No consecutive arrivals + /\ control \in CONTROL \{"ARRIVAL"} + \* Sets up the timer for the next TDM slot + /\ IF control = "INIT" THEN chsl_lbtimer' = TDM_Slot ELSE UNCHANGED<<chsl_lbtimer>> + \* The next arrival should happen at max arrival_rate cycles after this + /\ TimedOut_1dim(req,arvl_lbtimer) + /\ Set1dimTimer(req,arvl_lbtimer,arrival_rate) + /\ control' = "ARRIVAL" + /\ request_count' = [request_count EXCEPT ![req] = request_count[req] + 1] + /\ queue' = Append(queue,request_instance) + /\ UNCHANGED<<cmds_lbtimer,now,bank_state,req_under_treatment, + slot_count,slot_owner,row_buffer,slack>> +----------------------------------------------------------------------------- +SlotChange == + /\ control /= "INIT" + \* Checks if the timer has timed_out + /\ chsl_lbtimer = 0 + \* Sets it aggain + /\ chsl_lbtimer' = TDM_Slot + /\ slot_count' = slot_count + 1 + /\ slot_owner' = ModuloSum(slot_owner,1,TDM_Period) + /\ UNCHANGED<<cmds_lbtimer,arvl_lbtimer,now,bank_state,queue,req_under_treatment,request_count,row_buffer,slack,control>> +----------------------------------------------------------------------------- +TNext(bank) == \/ IssueACT(bank) + \/ IssueRD(bank) + \/ IssueWR(bank) + \/ UseBus(bank) + \/ ReleaseBus(bank) + \/ IssuePRE(bank) + +Tick == LET d == 1 IN + /\ ~\E bank \in Banks : TNext(bank) + /\ \neg ENABLED (treat_request \/ request_arrival(1,"RD","HIT",10) \/ request_arrival(2,"WR","MISS",15) \/ SlotChange) + /\ now' = now + d + /\ arvl_lbtimer' = [req \in Requestors |-> Max2Numbers(0,arvl_lbtimer[req]-d)] + /\ cmds_lbtimer' = [b \in Banks, c \in CMDS \{"IDLE"} |-> Max2Numbers(0,cmds_lbtimer[b,c]-d)] + /\ chsl_lbtimer' = Max2Numbers(0,chsl_lbtimer-d) + /\ UNCHANGED<<bank_state,queue,req_under_treatment,request_count,slot_count,slot_owner,row_buffer,slack,control>> +----------------------------------------------------------------------------- +Next == \/ Tick + \/ \E bank \in Banks : TNext(bank) + \/ treat_request + \/ SlotChange + \/ request_arrival(1,"RD","HIT",10) + \/ request_arrival(2,"WR","MISS",15) +----------------------------------------------------------------------------- +SafetySpec == Init /\ [][Next]_vars +FullQueue == Len(queue) =< Queue_Capacity +THEOREM SafetySpec => FullQueue +----------------------------------------------------------------------------- +Fairness == /\ \A b \in Banks : + /\ SF_vars(IssueACT(b)) + /\ SF_vars(IssueRD(b)) + /\ SF_vars(IssueWR(b)) + /\ SF_vars(IssuePRE(b)) + /\ SF_vars(UseBus(b)) + /\ SF_vars(ReleaseBus(b)) + /\ WF_vars(SlotChange) + /\ WF_vars(treat_request) + /\ WF_vars(request_arrival(1,"RD","HIT",10)) + /\ WF_vars(request_arrival(2,"WR","MISS",15)) + +Spec == SafetySpec /\ Fairness +============================================================================= +\* Modification History +\* Last modified Fri Mar 05 10:32:19 CET 2021 by felipe +\* Created Wed Mar 03 20:37:54 CET 2021 by felipe diff --git a/TLAplus/FirstModels/TDMv6/TDMv6.tla b/TLAplus/FirstModels/TDMv6/TDMv6.tla new file mode 100644 index 0000000000000000000000000000000000000000..7b398bead8b38c31aaab2c710d3ad7d21a905c19 --- /dev/null +++ b/TLAplus/FirstModels/TDMv6/TDMv6.tla @@ -0,0 +1,225 @@ +------------------------------- MODULE TDMv6 ------------------------------- +EXTENDS Integers, FiniteSets, Sequences, SequencesExt + +----------------------------------------------------------------------------- +Max2Numbers(a,b) == IF a >= b THEN a ELSE b +Max(S) == CHOOSE x \in S : \A y \in S : x >= y +Min(S) == CHOOSE x \in S : \A y \in S : x =< y +ModuloSum(a,b,max) == IF a + b =< max THEN a + b ELSE max - ((a+b)%max) +----------------------------------------------------------------------------- +Infinity == 1000 +Real == 0..100 \cup Infinity +----------------------------------------------------------------------------- + +CONSTANTS + \* Intra-bank constraints + t_RCD, + t_RP, + t_RC, + t_RAS, + t_RL, + t_WL, + t_RTP, + t_WR, + \* Inter-bank constraints + t_RRD, + \* Inter- and intra-bank constraints + t_RTW, + t_WRtoRD, + t_CCD, + t_WTR, + t_BURST, + \* Other constants + Banks, + CrRq, + NCrRq, + Mapping, + Queue_Capacity + +\* This creates a function that maps each requestor to a bank +Requestors == CrRq \cup NCrRq +tMapping == SetToSeq(Mapping) +BankMapping == [req \in Requestors |-> tMapping[req]] +\* Length of the TDM slot. Worst case is a write miss +TDM_Slot == t_RCD + t_WL + t_BURST + t_WR + t_RP + 1 +\* Peridiocity of the TDM +TDM_Period == Cardinality(CrRq) + +ASSUME + /\ Cardinality(Requestors) = Cardinality(Mapping) + +VARIABLES + now, + ACT_lbtimer, + RD_lbtimer, + WR_lbtimer, + PRE_lbtimer, + USEBUS_lbtimer, + RLSBUS_lbtimer, + ARV_lbtimer, + SLOT_lbtimer, + bank_state, + queue, + req_under_treatment, + request_count, + slot_count, + slot_owner, + row_buffer, + slack, + control + +vars == <<now,ACT_lbtimer,RD_lbtimer,WR_lbtimer,PRE_lbtimer,USEBUS_lbtimer,RLSBUS_lbtimer,ARV_lbtimer,SLOT_lbtimer, + bank_state,queue,req_under_treatment,request_count,slot_count,slot_owner,row_buffer,slack,control>> +----------------------------------------------------------------------------- +CMDS == {"ACT","RD","WR","PRE","IDLE","USEBUS","RLSBUS"} +CONTROL == {"INIT","ARRIVAL","TREATMENT","COMPLETED"} +----------------------------------------------------------------------------- +TimeTypeOK == + /\ now \in Real + /\ ACT_lbtimer \in [Banks -> Real] + /\ RD_lbtimer \in [Banks -> Real] + /\ WR_lbtimer \in [Banks -> Real] + /\ PRE_lbtimer \in [Banks -> Real] + /\ USEBUS_lbtimer \in [Banks -> Real] + /\ RLSBUS_lbtimer \in [Banks -> Real] + /\ ARV_lbtimer \in [Requestors -> Real] + /\ SLOT_lbtimer \in Real + +\* No type invariance for now : req_under_treatment, queue +TypeOK == + /\ bank_state \in [Banks -> CMDS] + /\ request_count \in [Requestors -> Nat] + /\ slot_count \in Nat + /\ slot_owner \in 1..Cardinality(CrRq) + /\ row_buffer \in [Banks -> {"OPEN","CLOSED"}] + /\ slack \in [CrRq -> Nat] + /\ control \in CONTROL + +Init == + /\ now = 0 + /\ ACT_lbtimer = [b \in Banks |-> 0] + /\ RD_lbtimer = [b \in Banks |-> 0] + /\ WR_lbtimer = [b \in Banks |-> 0] + /\ PRE_lbtimer = [b \in Banks |-> 0] + /\ USEBUS_lbtimer = [b \in Banks |-> 0] + /\ RLSBUS_lbtimer = [b \in Banks |-> 0] + /\ ARV_lbtimer = [req \in Requestors |-> 0] + /\ SLOT_lbtimer = 0 + /\ bank_state = [b \in Banks |-> "IDLE"] + /\ queue = <<>> + /\ req_under_treatment = [type |-> "NONE",deadline |-> 0,target |-> "NONE",number |-> 0,owner |-> 0, + issue_date |-> 0,delayed_issue_date |-> 0,hit_miss |-> "NONE"] + /\ request_count = [r \in Requestors |-> 0] + /\ slot_count = 1 + /\ slot_owner = 1 + /\ row_buffer = [b \in Banks |-> "CLOSED"] + /\ slack = [req \in CrRq |-> 0] + /\ control = "INIT" +----------------------------------------------------------------------------- +TimedOut(timer,index) == timer[index] = 0 +SetLBTimer(timer,index,value) == timer' = [timer EXCEPT ![index] = value] +----------------------------------------------------------------------------- +IssueACT(bank) == + /\ control = "TREATMENT" + /\ bank_state[bank] = "ACT" + /\ ACT_lbtimer["N1"] = 0 + /\ ACT_lbtimer["N2"] = 0 + /\ control' = "INIT" + /\ UNCHANGED<<now,ACT_lbtimer,RD_lbtimer,WR_lbtimer,PRE_lbtimer,USEBUS_lbtimer,RLSBUS_lbtimer,ARV_lbtimer,SLOT_lbtimer, + bank_state,queue,req_under_treatment,request_count,slot_count,slot_owner,row_buffer,slack>> +----------------------------------------------------------------------------- +treat_request == +LET deadlines == {queue[n].deadline : n \in 1..Len(queue)} + min_deadline == Min(deadlines) + selected_req == SelectSeq(queue, LAMBDA elem: elem.deadline = min_deadline)[1] +IN /\ (control = "ARRIVAL") \/ (control = "COMPLETE" /\ queue /= <<>>) + /\ control' = "TREATMENT" + /\ queue' = IF req_under_treatment.owner = 0 THEN Remove(queue,selected_req) ELSE queue + /\ req_under_treatment' = IF req_under_treatment.owner = 0 THEN selected_req ELSE req_under_treatment + /\ bank_state' = IF req_under_treatment.owner = 0 THEN [bank_state EXCEPT ![selected_req.target] = "ACT"] ELSE bank_state + /\ UNCHANGED<<now,ACT_lbtimer,RD_lbtimer,WR_lbtimer,PRE_lbtimer,USEBUS_lbtimer,RLSBUS_lbtimer,ARV_lbtimer,SLOT_lbtimer, + request_count,slot_count,slot_owner,row_buffer,slack>> +----------------------------------------------------------------------------- +request_arrival(req,ty,hm,arrival_rate) == +LET so_did == IF slack[req] >= (slot_count*TDM_Slot - now) + THEN ModuloSum((slack[req]%TDM_Slot)+1,slot_owner,TDM_Period) + ELSE slot_owner + dist == IF (now = TDM_Slot*(slot_count - 1)) /\ (req = slot_owner) + THEN 0 + ELSE IF req = so_did + THEN TDM_Period + ELSE IF req - so_did >= 0 + THEN req - so_did + ELSE so_did - req + calc_deadline == IF req \in CrRq + THEN TDM_Slot*(slot_count + dist) + ELSE TDM_Slot*(slot_count + 1) + request_instance == [number |-> request_count[req] + 1, + owner |-> req, + target |-> BankMapping[req], + issue_date |-> now, + delayed_issue_date |-> now + slack[req], + deadline |-> calc_deadline, + type |-> ty, + hit_miss |-> hm, + period |-> arrival_rate] +IN /\ req \notin {queue[n].owner : n \in 1..Len(queue)} + /\ control \in CONTROL \{"ARRIVAL"} + /\ TimedOut(ARV_lbtimer,req) + \* Primed + /\ SLOT_lbtimer' = IF control = "INIT" THEN TDM_Slot ELSE SLOT_lbtimer + /\ SetLBTimer(ARV_lbtimer,req,arrival_rate) + /\ control' = "ARRIVAL" + /\ request_count' = [request_count EXCEPT ![req] = request_count[req] + 1] + /\ queue' = Append(queue,request_instance) + /\ UNCHANGED<<now,ACT_lbtimer,RD_lbtimer,WR_lbtimer,PRE_lbtimer,USEBUS_lbtimer,RLSBUS_lbtimer, + bank_state,req_under_treatment,slot_count,slot_owner,row_buffer,slack>> +----------------------------------------------------------------------------- +SlotChange == + /\ control /= "INIT" + /\ SLOT_lbtimer = 0 + /\ SLOT_lbtimer' = TDM_Slot + /\ slot_count' = slot_count + 1 + /\ slot_owner' = ModuloSum(slot_owner,1,TDM_Period) + /\ UNCHANGED<<now,ACT_lbtimer,RD_lbtimer,WR_lbtimer,PRE_lbtimer,USEBUS_lbtimer,RLSBUS_lbtimer,ARV_lbtimer, + bank_state,queue,req_under_treatment,request_count,row_buffer,slack,control>> +----------------------------------------------------------------------------- +\*TNext(bank) == IssueACT(bank) +----------------------------------------------------------------------------- +Tick == \E d \in 0..100: + \* The Tick action is only allowed to happen when other decision actions are not possible + /\ ~\E bank \in Banks : IssueACT(bank) + /\ \neg ENABLED (treat_request \/ request_arrival(1,"RD","HIT",10) \/ request_arrival(2,"WR","MISS",15) \/ SlotChange) + /\ now' = now + d + /\ ACT_lbtimer' = [b \in Banks |-> Max2Numbers(0,ACT_lbtimer[b]-d)] + /\ RD_lbtimer' = [b \in Banks |-> Max2Numbers(0,RD_lbtimer[b]-d)] + /\ WR_lbtimer' = [b \in Banks |-> Max2Numbers(0,WR_lbtimer[b]-d)] + /\ PRE_lbtimer' = [b \in Banks |-> Max2Numbers(0,PRE_lbtimer[b]-d)] + /\ USEBUS_lbtimer' = [b \in Banks |-> Max2Numbers(0,USEBUS_lbtimer[b]-d)] + /\ RLSBUS_lbtimer' = [b \in Banks |-> Max2Numbers(0,RLSBUS_lbtimer[b]-d)] + /\ ARV_lbtimer' = [b \in Banks |-> Max2Numbers(0,ARV_lbtimer[b]-d)] + /\ SLOT_lbtimer' = Max2Numbers(0,SLOT_lbtimer-d) + /\ UNCHANGED<<bank_state,queue,req_under_treatment,request_count,slot_count,slot_owner,row_buffer,slack,control>> +----------------------------------------------------------------------------- +Next == \/ request_arrival(1,"RD","HIT",10) + \/ request_arrival(2,"WR","MISS",15) + \/ Tick + \/ treat_request + \/ SlotChange + \/ \E bank \in Banks : IssueACT(bank) +----------------------------------------------------------------------------- +SafetySpec == Init /\ [][Next]_vars +FullQueue == Len(queue) =< Queue_Capacity +THEOREM SafetySpec => FullQueue +----------------------------------------------------------------------------- +Liveness == /\ SF_vars(SlotChange) + /\ SF_vars(treat_request) + /\ SF_vars(request_arrival(1,"RD","HIT",10)) + /\ SF_vars(request_arrival(2,"WR","MISS",15)) + /\ \A b \in Banks : SF_vars(IssueACT(b)) + +Spec == SafetySpec /\ Liveness +============================================================================= +\* Modification History +\* Last modified Fri Mar 05 15:30:05 CET 2021 by felipe +\* Created Wed Mar 03 20:37:54 CET 2021 by felipe \ No newline at end of file diff --git a/TLAplus/StandardModules/RealTimeNew.tla b/TLAplus/StandardModules/RealTimeNew.tla new file mode 100644 index 0000000000000000000000000000000000000000..8a052638f610ada057c5fda253e77dc059529c0a --- /dev/null +++ b/TLAplus/StandardModules/RealTimeNew.tla @@ -0,0 +1,119 @@ +---------------------------- MODULE RealTimeNew ---------------------------- +EXTENDS Reals + +VARIABLE now + +---------------------------------------------------------------------------- +(***************************************************************************) +(* 1. Time Passing *) +(***************************************************************************) +NowNext(v) == + /\ now' \in {r \in Real : r > now} + /\ UNCHANGED v +---------------------------------------------------------------------------- +(***************************************************************************) +(* 2. Constraints on duration of actions *) +(***************************************************************************) +DurationBound(STRflag,t,A,v,min,lb,max,ub) == +LET TNext == t' = IF <<A>>_v \/ \neg(ENABLED <<A>>_v)' + THEN 0 + ELSE t + (now' - now) + UpperBound == IF STRflag = TRUE + THEN IF ub THEN t' =< max ELSE t' < max + ELSE A => IF ub THEN t =< max ELSE t < max + LowerBound == A => IF lb THEN t >= min ELSE t > min +IN /\ TNext + /\ UpperBound + /\ LowerBound + +DurationUB(STRflag,t,A,v,max,ub) == +LET TNext == t' = IF <<A>>_v \/ \neg(ENABLED <<A>>_v)' + THEN 0 + ELSE t + (now' - now) + UpperBound == IF STRflag = TRUE + THEN IF ub THEN t' =< max ELSE t' < max + ELSE A => IF ub THEN t =< max ELSE t < max +IN /\ TNext + /\ UpperBound + +DurationLB(t,A,v,min,lb) == +LET TNext == t' = IF <<A>>_v \/ \neg(ENABLED <<A>>_v)' + THEN 0 + ELSE t + (now' - now) + LowerBound == A => IF lb THEN t >= min ELSE t > min +IN /\ TNext + /\ LowerBound + +DurationValue(STRflag,t,A,vars,val) == +LET TNext == t' = IF <<A>>_vars \/ \neg(ENABLED <<A>>_vars)' + THEN 0 + ELSE t + (now' - now) + ValueBound == IF STRflag = TRUE THEN t' = val ELSE A => t = val +IN /\ TNext + /\ ValueBound +---------------------------------------------------------------------------- +(***************************************************************************) +(* 3. Constraints on time interval between actions *) +(***************************************************************************) +IntervalBound(STRflag,t,Acts,B,v,min,lb,max,ub) == +LET TNext == t' = IF <<B>>_v \/ \neg(ENABLED <<Acts \/ B>>_v)' + THEN 0 + ELSE t + (now' - now) + UpperBound == IF STRflag = TRUE + THEN IF ub THEN t' =< max ELSE t' < max + ELSE B => IF ub THEN t =< max ELSE t < max + LowerBound == B => IF lb THEN t >= min ELSE t > min +IN /\ TNext + /\ UpperBound + /\ LowerBound + +IntervalUB(STRflag,t,Acts,B,v,max,ub)== +LET TNext == t' = IF <<B>>_v \/ \neg(ENABLED <<Acts \/ B>>_v)' + THEN 0 + ELSE t + (now' - now) + UpperBound == IF STRflag = TRUE + THEN IF ub THEN t' =< max ELSE t' < max + ELSE B => IF ub THEN t =< max ELSE t < max +IN /\ TNext + /\ UpperBound + +IntervalLB(t,Acts,B,v,min,lb) == +LET TNext == t' = IF <<B>>_v \/ \neg(ENABLED <<Acts \/ B>>_v)' + THEN 0 + ELSE t + (now' - now) + LowerBound == B => IF lb THEN t >= min ELSE t > min +IN /\ TNext + /\ LowerBound + +IntervalValue(STRflag,t,Acts,B,vars,val) == +LET TNext == t' = IF <<B>>_vars \/ \neg(ENABLED <<Acts \/ B>>_vars)' + THEN 0 + ELSE t + (now' - now) + ValueBound == IF STRflag = TRUE THEN t' = val ELSE B => t = val +IN /\ TNext + /\ ValueBound +---------------------------------------------------------------------------- +(***************************************************************************) +(* 4. Advanced Time Patterns *) +(***************************************************************************) +\* A execution is delayed by val time units +Delay(A,val,t,vars) == + DurationValue(TRUE,t,A,vars,val) + +\* A must terminate at max at t +Deadline(A,val,t,vars) == + DurationUB(TRUE,t,A,vars,val,TRUE) + +\* If A does not occur in val time units, then execute the action B +Timeout(A,B,val,t1,t2,vars) == + /\ DurationUB(FALSE,t1,A,vars,val,TRUE) + /\ DurationValue(TRUE,t2,B,vars,val) +(***************************************************************************) +(* Non-Zeno Condition *) +(***************************************************************************) +RTFairness(v) == + \A r \in Real : WF_now(NowNext(v) /\ (now' > r)) +============================================================================= +\* Modification History +\* Last modified Fri Feb 12 14:56:41 CET 2021 by felipe +\* Created Fri Feb 12 13:13:32 CET 2021 by felipe diff --git a/TLAplus/StandardModules/SequencesExt.tla b/TLAplus/StandardModules/SequencesExt.tla new file mode 100644 index 0000000000000000000000000000000000000000..8777a477b02c111b9220d748e01cee05bfe8572d --- /dev/null +++ b/TLAplus/StandardModules/SequencesExt.tla @@ -0,0 +1,145 @@ +---------------------------- MODULE SequencesExt ---------------------------- + +LOCAL INSTANCE Sequences +LOCAL INSTANCE Naturals +LOCAL INSTANCE FiniteSets +LOCAL INSTANCE Functions + (*************************************************************************) + (* Imports the definitions from the modules, but doesn't export them. *) + (*************************************************************************) + +----------------------------------------------------------------------------- + +ToSet(s) == + (*************************************************************************) + (* The image of the given sequence s. Cardinality(ToSet(s)) <= Len(s) *) + (* see https://en.wikipedia.org/wiki/Image_(mathematics) *) + (*************************************************************************) + { s[i] : i \in DOMAIN s } + +IsInjective(s) == + (*************************************************************************) + (* TRUE iff the sequence s contains no duplicates where two elements *) + (* a, b of s are defined to be duplicates iff a = b. In other words, *) + (* Cardinality(ToSet(s)) = Len(s) *) + (* *) + (* This definition is overridden by TLC in the Java class SequencesExt. *) + (* The operator is overridden by the Java method with the same name. *) + (* *) + (* Also see Functions!Injective operator. *) + (*************************************************************************) + \A i, j \in DOMAIN s: (s[i] = s[j]) => (i = j) + +SetToSeq(S) == + (**************************************************************************) + (* Convert a set to some sequence that contains all the elements of the *) + (* set exactly once, and contains no other elements. *) + (**************************************************************************) + CHOOSE f \in [1..Cardinality(S) -> S] : IsInjective(f) + +----------------------------------------------------------------------------- + +Contains(s, e) == + (**************************************************************************) + (* TRUE iff the element e \in ToSet(s). *) + (**************************************************************************) + \E i \in 1..Len(s) : s[i] = e + +Reverse(s) == + (**************************************************************************) + (* Reverse the given sequence s: Let l be Len(s) (length of s). *) + (* Equals a sequence s.t. << S[l], S[l-1], ..., S[1]>> *) + (**************************************************************************) + [ i \in 1..Len(s) |-> s[(Len(s) - i) + 1] ] + +Remove(s, e) == + (************************************************************************) + (* The sequence s with e removed or s iff e \notin Range(s) *) + (************************************************************************) + SelectSeq(s, LAMBDA t: t # e) + +ReplaceAll(s, old, new) == + (*************************************************************************) + (* Equals the sequence s except that all occurrences of element old are *) + (* replaced with the element new. *) + (*************************************************************************) + LET F[i \in 0..Len(s)] == + IF i = 0 THEN << >> + ELSE IF s[i] = old THEN Append(F[i-1], new) + ELSE Append(F[i-1], s[i]) + IN F[Len(s)] + +----------------------------------------------------------------------------- + +\* The operators below have been extracted from the TLAPS module +\* SequencesTheorems.tla as of 10/14/2019. The original comments have been +\* partially rewritten. + +InsertAt(s, i, e) == + (**************************************************************************) + (* Inserts element e at the position i moving the original element to i+1 *) + (* and so on. In other words, a sequence t s.t.: *) + (* /\ Len(t) = Len(s) + 1 *) + (* /\ t[i] = e *) + (* /\ \A j \in 1..(i - 1): t[j] = s[j] *) + (* /\ \A k \in (i + 1)..Len(s): t[k + 1] = s[k] *) + (**************************************************************************) + SubSeq(s, 1, i-1) \o <<e>> \o SubSeq(s, i, Len(s)) + +ReplaceAt(s, i, e) == + (**************************************************************************) + (* Replaces the element at position i with the element e. *) + (**************************************************************************) + [s EXCEPT ![i] = e] + +RemoveAt(s, i) == + (**************************************************************************) + (* Replaces the element at position i shortening the length of s by one. *) + (**************************************************************************) + SubSeq(s, 1, i-1) \o SubSeq(s, i+1, Len(s)) + +----------------------------------------------------------------------------- + +Front(s) == + (**************************************************************************) + (* The sequence formed by removing its last element. *) + (**************************************************************************) + SubSeq(s, 1, Len(s)-1) + +Last(s) == + (**************************************************************************) + (* The last element of the sequence. *) + (**************************************************************************) + s[Len(s)] + +----------------------------------------------------------------------------- + +IsPrefix(s, t) == + (**************************************************************************) + (* TRUE iff the sequence s is a prefix of the sequence t, s.t. *) + (* \E u \in Seq(Range(t)) : t = s \o u. In other words, there exists *) + (* a suffix u that with s prepended equals t. *) + (**************************************************************************) + DOMAIN s \subseteq DOMAIN t /\ \A i \in DOMAIN s: s[i] = t[i] + +IsStrictPrefix(s,t) == + (**************************************************************************) + (* TRUE iff the sequence s is a prefix of the sequence t and s # t *) + (**************************************************************************) + IsPrefix(s, t) /\ s # t + +IsSuffix(s, t) == + (**************************************************************************) + (* TRUE iff the sequence s is a suffix of the sequence t, s.t. *) + (* \E u \in Seq(Range(t)) : t = u \o s. In other words, there exists a *) + (* prefix that with s appended equals t. *) + (**************************************************************************) + IsPrefix(Reverse(s), Reverse(t)) + +IsStrictSuffix(s, t) == + (**************************************************************************) + (* TRUE iff the sequence s is a suffix of the sequence t and s # t *) + (**************************************************************************) + IsSuffix(s,t) /\ s # t + +============================================================================= \ No newline at end of file