-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | A simple interpreter for arrayForth, the language used on GreenArrays chips. -- -- This is a package for working with arrayForth. This is a variant of -- Forth used by GreenArrays chips. This package contains an arrayForth -- simulator, two different representations of arrayForth programs and -- some utilities like parsing. It also supports synthesizing arrayForth -- programs using MCMC. The basic idea is to find arrayForth programs by -- taking a simple prior distribution of programs and using a randomized -- hill-climbing algorithm to find a program fulfilling certain tests. @package array-forth @version 0.2.0.4 module Language.ArrayForth.Parse -- | Possible ways the input string can be malformed. data ParseError BadOpcode :: String -> ParseError NotSlot3 :: String -> ParseError NotJump :: String -> ParseError NoAddr :: String -> ParseError BadNumber :: String -> ParseError -- | Is the given string a valid number with no other tokens? isNumber :: String -> Bool -- | Tries to read a word, giving an error if it fails. readWord :: Read a => String -> Either ParseError a instance Show ParseError module Language.ArrayForth.Opcode -- | The 18-bit word type used by Greenarrays chips. type F18Word = Word18 -- | Each F18A instruction, ordered by opcode. data Opcode Ret :: Opcode Exec :: Opcode Jmp :: Opcode Call :: Opcode Unext :: Opcode Next :: Opcode If :: Opcode MinusIf :: Opcode FetchP :: Opcode FetchPlus :: Opcode FetchB :: Opcode Fetch :: Opcode StoreP :: Opcode StorePlus :: Opcode StoreB :: Opcode Store :: Opcode MultiplyStep :: Opcode Times2 :: Opcode Div2 :: Opcode Not :: Opcode Plus :: Opcode And :: Opcode Or :: Opcode Drop :: Opcode Dup :: Opcode Pop :: Opcode Over :: Opcode ReadA :: Opcode Nop :: Opcode Push :: Opcode SetB :: Opcode SetA :: Opcode -- | The names of the different instructions, ordered by opcode. names :: [String] -- | All of the opcodes, in order. opcodes :: [Opcode] -- | Tries to read a given string as an opcode from the list of names. readOpcode :: String -> Either ParseError Opcode -- | Converts a word to an opcode. The word has to be < 32. toOpcode :: F18Word -> Opcode -- | Converts an Opcode to its 18-bit word representation. fromOpcode :: Opcode -> F18Word -- | Returns whether the given opcode is a jump instruction expecting an -- address. isJump :: Opcode -> Bool -- | Can the given opcode go in the last slot? slot3 :: Opcode -> Bool -- | Estimates how long a given opcode will take to execute. Normal opcodes -- take 1.5 nanoseconds where ones that access the memory take 5 -- nanoseconds. opcodeTime :: Opcode -> Double instance Eq Opcode instance Bounded Opcode instance Enum Opcode instance Read Opcode instance Show Opcode module Language.ArrayForth.NativeProgram -- | Represents a word in memory. This word can either contain opcodes, -- opcodes and a jump address or just a constant number. data Instrs Instrs :: Opcode -> Opcode -> Opcode -> Opcode -> Instrs Jump3 :: Opcode -> Opcode -> Opcode -> F18Word -> Instrs Jump2 :: Opcode -> Opcode -> F18Word -> Instrs Jump1 :: Opcode -> F18Word -> Instrs Constant :: F18Word -> Instrs -- | A program in the F18A instruction set. type NativeProgram = [Instrs] -- | Splits a list into chunks of at most four, breaking off a chunk -- whenever it sees an element matching the given predicate. This is -- useful for splitting a program along word boundaries, accounting for -- jump addresses. splitWords :: (a -> Bool) -> [a] -> [[a]] -- | Read a whole program, splitting instructions up into words. readNativeProgram :: String -> Either ParseError NativeProgram -- | Returns the given instructions as an actual word. This assumes the -- address is sized appropriately. toBits :: Instrs -> F18Word -- | Reads in a word as a set of opcodes. fromBits :: F18Word -> Instrs -- | Returns the opcodes in the given instruction word. A constant -- corresponds to not having any opcodes. toOpcodes :: Instrs -> [Opcode] -- | Estimates the running time of the program in nanoseconds. This is -- based on the numbers provided in the manual: faster instructions take -- 1.5 nanoseconds and slower ones take 5. For now, this estimate ignores -- control flow like ifs and loops. runningTime :: NativeProgram -> Double instance [overlap ok] Eq Instrs instance [overlap ok] IsString NativeProgram instance [overlap ok] Read NativeProgram instance [overlap ok] Show Instrs module Language.ArrayForth.Stack -- | A stack containing only 0s. empty :: Stack -- | Pushes the given element on top of the stack, discarding the last -- element. push :: Stack -> F18Word -> Stack -- | Pops the top of the stack, returning the value and the new stack. pop :: Stack -> (Stack, F18Word) -- | Push the given elements onto the stack one-by-one. fill :: Stack -> [F18Word] -> Stack data Stack instance Eq Stack instance Show Stack module Language.ArrayForth.State -- | The chip's RAM and ROM type Memory = Vector Int emptyMem :: Memory -- | A state representing the registers, stacks and memory of a core. data State State :: !F18Word -> !F18Word -> !F18Word -> !F18Word -> !F18Word -> !F18Word -> !F18Word -> !Stack -> !Stack -> !Memory -> State a :: State -> !F18Word b :: State -> !F18Word i :: State -> !F18Word p :: State -> !F18Word r :: State -> !F18Word s :: State -> !F18Word t :: State -> !F18Word dataStack :: State -> !Stack returnStack :: State -> !Stack memory :: State -> !Memory -- | The state corresponding to a core with no programs loaded and no -- instructions executed. startState :: State -- | The next word of instructions to execute in the given state. next :: State -> Instrs -- | Pops the data stack of the given state, updating s and t. dpop :: State -> (State, F18Word) -- | Push a word onto the data stack, updating s and t. dpush :: State -> F18Word -> State -- | Pops the return stack of the given state, updating r. rpop :: State -> (State, F18Word) -- | Push a word onto the return stack, updating r. rpush :: State -> F18Word -> State -- | Force an address to be in range of memory: [0,64). toMem :: (Integral a, Integral b) => a -> b -- | Read the memory at a location given by a Forth word. (!) :: Memory -> F18Word -> F18Word -- | Set the memory using Forth words. set :: Memory -> F18Word -> F18Word -> Memory -- | Loads the given program into memory at the given starting position. setProgram :: F18Word -> NativeProgram -> State -> State instance Show State module Language.ArrayForth.Interpreter -- | Runs a single word's worth of instructions starting from the given -- state. word :: Instrs -> State -> State -- | Executes a single instruction in the given state, incrementing the -- program counter. step :: State -> State -- | Returns a trace of the program's execution. The trace is a list of the -- state of the chip after each step. traceProgram :: State -> [State] -- | Trace a program until it either hits four nops or all 0s. stepProgram :: State -> [State] -- | Runs the program unil it hits a terminal state, returning only the -- resulting state. eval :: State -> State -- | Executes the specified program on the given state until it hits a -- terminal word--a word made up of four nops or all 0s. runNativeProgram :: State -> NativeProgram -> State -- | Estimates the execution time of a program trace. countTime :: [State] -> Double -- | Checks that the program trace terminated in at most n steps, returning -- Nothing otherwise. throttle :: Int -> [State] -> Either [State] [State] -- | Does the given opcode cause the current word to stop executing? endWord :: Opcode -> Bool -- | Executes an opcode on the given state. execute :: Opcode -> State -> State -- | Execute a jump instruction to the given address. jump :: Opcode -> F18Word -> State -> State module Language.ArrayForth.Program data Addr Concrete :: F18Word -> Addr Abstract :: String -> Addr -- | Represents a single instruction as viewed by the synthesizer. This can -- be an opcode, a numeric literal or a token representing an unused -- slot. data Instruction Opcode :: Opcode -> Instruction Jump :: Opcode -> Addr -> Instruction Number :: F18Word -> Instruction Label :: String -> Instruction Unused :: Instruction -- | A program to be manipulated by the MCMC synthesizer type Program = [Instruction] -- | Tries to parse the given string as an instruction, which can either be -- a number, an opcode or _ representing Unused. readInstruction :: String -> Either ParseError Instruction -- | Reads a program in the synthesizer's format. readProgram :: String -> Either ParseError Program toNative :: Program -> NativeProgram -- | Gets a synthesizer program from a native program. Currently does not -- support jumps. fromNative :: NativeProgram -> Program -- | Runs a given program from the default starting state. runProgram :: State -> Program -> State -- | Loads the given synthesizer-friendly program into the given state. load :: Program -> State -> State instance [overlap ok] Eq Addr instance [overlap ok] Eq Instruction instance [overlap ok] IsString Program instance [overlap ok] Read Program instance [overlap ok] Show Instruction instance [overlap ok] Show Addr module Language.ArrayForth.Distance -- | A function that computes a measure of distance between two -- states. The larger the returned number, the more different the states. type Distance = State -> State -> Double -- | Counts the number of bits that differ between two numbers. countBits :: (Integral n, Bits n) => n -> n -> Int -- | Return a distance function that counts the different bits between the -- given registers. You could use it like `compareRegisters [s, t]`. registers :: [State -> F18Word] -> Distance -- | Returns a distance function that counts the different bits between the -- given memory locations. locations :: [F18Word] -> Distance -- | Combines multiple distance functions to create a new one, by summing -- the different distances. distances :: [Distance] -> Distance module Language.ArrayForth.Synthesis -- | Given a specification program and some inputs, evaluate a program -- against the specification for both performance and correctness. evaluate :: Program -> [State] -> Distance -> Program -> Double -- | The default distribution of instructions. For now, we do not support -- any sort of jumps. All the other possible instructions along with -- constant numbers and unused slots are equally likely. The numeric -- value of constants is currently a uniform distribution over 18-bit -- words. defaultOps :: Distr Instruction -- | The default mutations to try. For now, this will either change an -- instruction or swap two instructions in the program, with equal -- probability. defaultMutations :: Mutation Program instance [overlap ok] Random F18Word