-- 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.5
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
-- | Does this instruction force a word boundary?
boundary :: Instruction -> Bool
-- | Resolves labels into addresses, assuming the program starts at the
-- given memory location.
labels :: F18Word -> Program -> Program
-- | Insert extra nops to account for instructions that cannot go into the
-- last slot.
fixSlot3 :: Program -> Program
-- | 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