---- MODULE FlashMemory ----
EXTENDS TLC, Naturals, Integers
CONSTANTS N, Length
VARIABLES Programmed, SectorState
ASSUME N \in Nat /\ Length \in Nat
----
Sectors == 1..N
AddressSpace == 1..(N * Length)
----
Init == /\ Programmed = {}
/\ SectorState = [i \in Sectors |-> "unknown"]
TypeOk == /\ Programmed \subseteq AddressSpace
/\ \A s \in Sectors :SectorState[s] \in {"unknown", "erased", "programmed"}
SectorBytes == [s \in Sectors |-> (1 + (s-1)*Length)..(s*Length)]
ByteRange(start, n) == start..(start+n-1)
Write(start, n) == LET Bytes == ByteRange(start, n)
WriteSectors == {s \in Sectors : SectorBytes[s] \cap Bytes /= {}}
IN
/\ Bytes \subseteq AddressSpace \* Cannot write outside the range
/\ \A s \in WriteSectors : SectorState[s] /= "unknown" \* Only program sectors in a known state
/\ Programmed \cap Bytes = {} \* Cannot reprogram locations
/\ SectorState' = [s \in WriteSectors |-> "programmed"] @@ SectorState
/\ Programmed' = Programmed \cup Bytes
(* Erase a sector, clearing all programmed locations and setting the sector state *)
Erase(s) == /\ SectorState' = [SectorState EXCEPT ![s] = "erased"]
/\ Programmed' = Programmed \ SectorBytes[s]
Next == (\E start, len \in AddressSpace : Write(start, len)) \/ (\E sect \in Sectors : Erase(sect))
====