blob: 7f80216bd39185790b7f5593c91b5909f20a0679 [file] [log] [blame] [edit]
--
-- Copyright 2020, Data61, CSIRO (ABN 41 687 119 230)
--
-- SPDX-License-Identifier: BSD-2-Clause
--
module CapDL.PrintModel where
import CapDL.Model
import CapDL.PrintUtils
import Prelude ()
import Prelude.Compat
import Text.PrettyPrint
import Data.List.Compat
import qualified Data.Map as Map
indent = 2
prettyMapping :: (Show a, Show b) => (a,b) -> Doc
prettyMapping (a,b) = text (show a) <> text " -> " <> text (show b)
prettyBigList f xs = lbrack $+$ nest indent (vcat (map f xs)) $+$ rbrack
prettyMap m = prettyBigList prettyMapping (Map.toList m)
prettyNum :: Int -> Doc
prettyNum num = brackets $ int num
prettyNameDecl :: ObjID -> Int-> Doc
prettyNameDecl (n, Nothing) _ = text n <+> equals
prettyNameDecl (n, _) num = text n <> prettyNum num <+> equals
prettyNameRefr :: [ObjID]-> Doc
prettyNameRefr objs = (text.fst.head) objs <> (prettyBrackets $ map snd objs)
prettyObject :: ObjID -> Int -> KernelObject a -> Doc
prettyObject _ _ Untyped {} = empty
prettyObject n num obj = prettyNameDecl n num <+> prettyObjParams obj
prettyObjectsList :: [(ObjID, KernelObject a)] -> [Doc]
prettyObjectsList [] = []
prettyObjectsList list@((id, obj):_) =
prettyObject id len obj:prettyObjectsList (drop len list)
where len = length (takeWhile (sameName id) (map fst list))
prettyObjects :: ObjMap a -> Doc
prettyObjects m = vcat (prettyObjectsList (Map.toList m))
prettyCovered :: [ObjID] -> [Doc]
prettyCovered [] = []
prettyCovered list@(id:_) =
prettyNameRefr same:prettyCovered (drop (length same) list)
where same = takeWhile (sameName id) list
prettyIndexedUntyped :: CoverMap -> [(ObjID, KernelObject a)] -> Doc
prettyIndexedUntyped _ [] = empty
prettyIndexedUntyped covers ((name, obj@(Untyped _ _)):xs) =
if null cover
then prettyIndexedUntyped covers xs
else prettyNameRefr [name] <+> equals <+> prettyObjParams obj <+>
braces (fsep $ punctuate comma $ prettyCovered cover) $+$
prettyIndexedUntyped covers xs
where cover = getUTCover name covers
prettyIndexedUntyped _ _ = error "Untyped only"
prettyUntyped :: CoverMap -> [(ObjID, KernelObject a)] -> Doc
prettyUntyped covers list@((name, obj@(Untyped _ _)):_) =
if snd name == Nothing
then prettyNameDecl name len <+> prettyObjParams obj <+>
if null cover
then empty
else braces (fsep $ punctuate comma $ prettyCovered cover)
else prettyNameDecl name len <+> prettyObjParams obj $+$
prettyIndexedUntyped covers list
where len = length list
cover = getUTCover name covers
prettyUntyped _ _ = empty
prettyUntypedsList :: CoverMap -> [(ObjID, KernelObject a)] -> [Doc]
prettyUntypedsList _ [] = [empty]
prettyUntypedsList covers list@((name, _):_) =
prettyUntyped covers (take len list) :
prettyUntypedsList covers (drop len list)
where len = length $ takeWhile (sameName name) (map fst list)
prettyUntypeds :: ObjMap a -> CoverMap -> Doc
prettyUntypeds m covers = vcat (prettyUntypedsList covers (Map.toList m))
prettyCap :: Cap -> [Maybe Word] -> Doc
prettyCap cap range = printCap cap <> prettyBrackets range <+> maybeCapParams cap
prettySlot :: Printing a => (a, Cap) -> [Maybe Word] -> Doc
prettySlot (n, cap) range = num n <> colon <+> prettyCap cap range
prettySlotsRange :: Printing a => [(a, Cap)] -> Doc
prettySlotsRange [] = error "empty"
prettySlotsRange list@(x:_) =
prettySlot x (map (snd.objID.snd) list)
prettySlotsList :: Printing a => [(a, Cap)] -> [Doc]
prettySlotsList [] = []
prettySlotsList list@(first@(_, cap):xs) =
if hasObjID cap
then prettySlotsRange sameGroup : prettySlotsList (drop (length sameGroup) list)
else prettySlot first [Nothing] : prettySlotsList xs
where sameGroup = sameArray list
capHead :: ObjID -> [Maybe Word] -> Doc
capHead (name, _) range = text name <> prettyBrackets range
prettySlots :: Printing a => (ObjID, KernelObject a) -> [Maybe Word] -> Doc
prettySlots (n, obj) range =
let xs = prettySlotsList $ Map.toList $ slots obj
in case xs of
[] -> empty
[slot] -> capHead n range <+> braces slot $+$ text ""
xs -> hang (capHead n range <+> lbrace) indent (vcat xs)
$+$ rbrace $+$ text ""
prettyCapsGroup :: Printing a => [(ObjID, KernelObject a)] -> Doc
prettyCapsGroup list = prettySlots (head list) (map (snd.fst) list)
prettyCapsList :: Printing a => [(ObjID, KernelObject a)] -> [Doc]
prettyCapsList [] = []
prettyCapsList list@(first:xs)
| hasSlots (snd first) =
prettyCapsGroup sameCaps : prettyCapsList otherCaps
| otherwise = prettyCapsList xs
where (sameCaps, otherCaps) = partition (same first) list
prettyCaps :: Printing a => ObjMap a -> Doc
prettyCaps ms = vcat $ prettyCapsList $ Map.toList ms
prettyCapRef :: CapRef -> Doc
prettyCapRef (obj, slot) = parens $ text (showID obj) <> comma <+> num slot
prettyCDTDecl :: CapRef -> [CapRef] -> Doc
prettyCDTDecl parent children =
let parent' = prettyCapRef parent
children' = map prettyCapRef children
in case children' of
[child] -> parent' <+> braces child $+$ text ""
children -> hang (parent' <+> lbrace) indent (vcat children)
$+$ rbrace $+$ text ""
prettyCDTGroup :: [(CapRef, CapRef)] -> Doc
prettyCDTGroup list = prettyCDTDecl (snd (head list)) (map fst list)
prettyCDTList :: [(CapRef, CapRef)] -> [Doc]
prettyCDTList [] = []
prettyCDTList list =
prettyCDTGroup sameParents : prettyCDTList otherParents
where
(sameParents, otherParents) =
partition ((== firstParent) . snd) list
firstParent = snd $ head list
prettyCDT :: CDT -> Doc
prettyCDT cdt = vcat $ prettyCDTList $ Map.toList cdt
prettyIRQ :: ObjID -> [Maybe Word] -> Doc
prettyIRQ irq range = text (fst irq) <> prettyBrackets range
prettyIRQSlot :: (Word, ObjID) -> [Maybe Word] -> Doc
prettyIRQSlot (n, irq) range = num n <> colon <+> prettyIRQ irq range
prettyIRQSlotsRange :: [(Word, ObjID)] -> Doc
prettyIRQSlotsRange [] = error "empty"
prettyIRQSlotsRange list@(x:_) =
prettyIRQSlot x (map (snd.snd) list)
prettyIRQSlotsList :: [(Word, ObjID)] -> [Doc]
prettyIRQSlotsList [] = []
prettyIRQSlotsList list =
prettyIRQSlotsRange sameGroup : prettyIRQSlotsList (drop (length sameGroup) list)
where sameGroup = sameArray list
prettyIRQNode :: IRQMap -> Doc
prettyIRQNode irqNode =
let irqs = prettyIRQSlotsList (Map.toList irqNode)
in case irqs of
[] -> empty
[irq] -> irq $+$ text ""
irqs -> vcat irqs $+$ text ""
prettyMappings :: Printing a => Model a -> Doc
prettyMappings (Model _ ms irqNode cdt untypedCovers) =
text "objects {" $+$
text "" $+$
nest indent (prettyObjects ms) $+$
text "" $+$
nest indent (prettyUntypeds ms untypedCovers) $+$
text "" $+$
text "} caps {" $+$
text "" $+$
nest indent (prettyCaps ms) $+$
text "} cdt {" $+$
text "" $+$
nest indent (prettyCDT cdt) $+$
text "} irq maps {" $+$
text "" $+$
nest indent (prettyIRQNode irqNode) $+$
text "}"
prettyHeader arch =
text "arch" <+> prettyArch arch $+$
text ""
pretty model =
prettyHeader (arch model) $+$
prettyMappings model