Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
78 lines (65 sloc) 2.9 KB
module Hardware.MMU (
Pending, RAMStatus(..), RAMAction(..),
initiate, next, service, check
) where
import CLaSH.Prelude
import Hardware.Model (SKI,Ptr)
import Hardware.Defs (MemRequest(..),MemResponse(..),Some(Zero,One,Two),Write(..),Read(..))
data Pending = Pending Reading Reading Writing Writing deriving Show
data Reading = NotReading | Reading Ptr | DidRead SKI deriving Show
data Writing = NotWriting | Writing Ptr SKI | Written deriving Show
data RAMStatus = NoUpdate | ReadComplete SKI | WriteComplete
data RAMAction = R Ptr -- Read
| W Ptr SKI -- Write
| X -- Nothing
deriving Show
-- Take a fresh MemRequest and turn it into a pending memory operation.
initiate :: MemRequest -> Pending
initiate (MemRequest reads writes) = Pending r1 r2 w1 w2
where
(r1,r2) = case reads of
Zero -> (NotReading, NotReading)
One (Read pa) -> (Reading pa, NotReading)
Two (Read pa) (Read pb) -> (Reading pa, Reading pb)
(w1,w2) = case writes of
Zero -> (NotWriting, NotWriting)
One (Write va pa) -> (Writing pa va, NotWriting)
Two (Write va pa) (Write vb pb) -> (Writing pa va, Writing pb vb)
-- Calculate the next action required to satisfy the memory operation.
next :: Pending -> RAMAction
next pending = case pending of
Pending (Reading ptr) _ _ _ -> R ptr
Pending _ (Reading ptr) _ _ -> R ptr
Pending _ _ (Writing p x) _ -> W p x
Pending _ _ _ (Writing p x) -> W p x
Pending _ _ _ _ -> X
-- Given the current pending request, as well as the state of RAM
-- (e.g. waiting for read to complete), generate the new pending state.
service :: Pending -> RAMStatus -> Pending
service pending NoUpdate = pending
service pending (ReadComplete ski) = case pending of
Pending (Reading _) n o p -> Pending (DidRead ski) n o p
Pending (DidRead m) (Reading _) o p -> Pending (DidRead m) (DidRead ski) o p
_ -> error "Unexpected ReadComplete"
service pending WriteComplete = case pending of
Pending (Reading _) _ _ _ -> error "WriteComplete before reading finished"
Pending _ (Reading _) _ _ -> error "WriteComplete before reading finished (2)"
Pending m n (Writing _ _) p -> Pending m n Written p
Pending m n Written (Writing _ _) -> Pending m n Written Written
_ -> error "Unexpected WriteComplete"
-- Determine if the pending request has finished.
-- If it has, return a MemResponse.
check :: Pending -> Maybe MemResponse
check (Pending r1 r2 w1 w2) = if doneWriting
then MemResponse <$> reads
else Nothing
where
doneWriting = case (w1,w2) of
(Writing _ _, _) -> False
(_, Writing _ _) -> False
_ -> True
reads = case (r1,r2) of
(NotReading, NotReading) -> Just $ Zero
(DidRead v1, NotReading) -> Just $ One v1
(DidRead v1, DidRead v2) -> Just $ Two v1 v2
_ -> Nothing