import qualified DataCon
import qualified Maybe
import qualified Module
+import qualified Control.Monad.State as State
import Name
import Data.Generics
import NameEnv ( lookupNameEnv )
liftIO $ printBinds (cm_binds core)
let bind = findBind "half_adder" (cm_binds core)
let NonRec var expr = bind
- let sess = VHDLSession 0 builtin_funcs
+ -- Turn bind into VHDL
+ let vhdl = State.evalState (mkVHDL bind) (VHDLSession 0 builtin_funcs)
liftIO $ putStr $ showSDoc $ ppr expr
liftIO $ putStr "\n\n"
- liftIO $ putStr $ render $ ForSyDe.Backend.Ppr.ppr $ getArchitecture sess bind
+ liftIO $ putStr $ render $ ForSyDe.Backend.Ppr.ppr $ vhdl
return expr
+ where
+ -- Turns the given bind into VHDL
+ mkVHDL bind = do
+ -- Get the function signature
+ (name, f) <- mkHWFunction bind
+ -- Add it to the session
+ addFunc name f
+ arch <- getArchitecture bind
+ return arch
printTarget (Target (TargetFile file (Just x)) obj Nothing) =
print $ show file
-- Accepts a port name and an argument to map to it.
-- Returns the appropriate line for in the port map
-getPortMapEntry binds portname (Var id) =
+getPortMapEntry binds (Port portname) (Var id) =
(Just (AST.unsafeVHDLBasicId portname)) AST.:=>: (AST.ADName (AST.NSimple (AST.unsafeVHDLBasicId signalname)))
where
Port signalname = Maybe.fromMaybe
getInstantiations ::
VHDLSession
- -> PortNameMap -- The arguments that need to be applied to the
- -- expression. Should always be the Args
- -- constructor.
+ -> [PortNameMap] -- The arguments that need to be applied to the
+ -- expression.
-> PortNameMap -- The output ports that the expression should generate.
-> [(CoreBndr, PortNameMap)] -- A list of bindings in effect
-> CoreSyn.CoreExpr -- The expression to generate an architecture for
-> [AST.ConcSm] -- The resulting VHDL code
-- A lambda expression binds the first argument (a) to the binder b.
-getInstantiations sess (Args (a:as)) outs binds (Lam b expr) =
- getInstantiations sess (Args as) outs ((b, a):binds) expr
+getInstantiations sess (a:as) outs binds (Lam b expr) =
+ getInstantiations sess as outs ((b, a):binds) expr
-- A case expression that checks a single variable and has a single
-- alternative, can be used to take tuples apart
hwfunc = Maybe.fromMaybe
(error $ "Function " ++ compname ++ "is unknown")
(lookup compname (funcs sess))
- HWFunction inports outports = hwfunc
+ HWFunction inports outport = hwfunc
ports =
- zipWith (getPortMapEntry binds) ["portin0", "portin1"] fargs
- ++ mapOutputPorts outports outs
+ zipWith (getPortMapEntry binds) inports fargs
+ ++ mapOutputPorts outport outs
getInstantiations sess args outs binds expr =
error $ "Unsupported expression" ++ (showSDoc $ ppr $ expr)
concat (zipWith mapOutputPorts ports signals)
getArchitecture ::
- VHDLSession
- -> CoreBind -- The binder to expand into an architecture
- -> AST.ArchBody -- The resulting architecture
+ CoreBind -- The binder to expand into an architecture
+ -> VHDLState AST.ArchBody -- The resulting architecture
-getArchitecture sess (Rec _) = error "Recursive binders not supported"
+getArchitecture (Rec _) = error "Recursive binders not supported"
-getArchitecture sess (NonRec var expr) =
- AST.ArchBody
+getArchitecture (NonRec var expr) = do
+ HWFunction inports outport <- getHWFunc name
+ sess <- State.get
+ return $ AST.ArchBody
(AST.unsafeVHDLBasicId "structural")
-- Use unsafe for now, to prevent pulling in ForSyDe error handling
(AST.NSimple (AST.unsafeVHDLBasicId name))
[]
- (getInstantiations sess (Args inportnames) outport [] expr)
+ (getInstantiations sess inports outport [] expr)
where
name = (getOccString var)
- ty = CoreUtils.exprType expr
- (fargs, res) = Type.splitFunTys ty
- --state = if length fargs == 1 then () else (last fargs)
- ports = if length fargs == 1 then fargs else (init fargs)
- inportnames = case ports of
- [port] -> [getPortNameMapForTy "portin" port]
- ps -> getPortNameMapForTys "portin" 0 ps
- outport = getPortNameMapForTy "portout" res
data PortNameMap =
- Args [PortNameMap] -- Each of the submaps represent an argument to the
- -- function. Should only occur at top level.
- | Tuple [PortNameMap]
+ Tuple [PortNameMap]
| Port String
+ deriving (Show)
-- Generate a port name map (or multiple for tuple types) in the given direction for
-- each type given.
(tycon, args) = Type.splitTyConApp ty
data HWFunction = HWFunction { -- A function that is available in hardware
- inPorts :: PortNameMap,
- outPorts :: PortNameMap
+ inPorts :: [PortNameMap],
+ outPort :: PortNameMap
--entity :: AST.EntityDec
-}
+} deriving (Show)
+
+-- Turns a CoreExpr describing a function into a description of its input and
+-- output ports.
+mkHWFunction ::
+ CoreBind -- The core binder to generate the interface for
+ -> VHDLState (String, HWFunction) -- The name of the function and its interface
+
+mkHWFunction (NonRec var expr) =
+ return (name, HWFunction inports outport)
+ where
+ name = (getOccString var)
+ ty = CoreUtils.exprType expr
+ (fargs, res) = Type.splitFunTys ty
+ args = if length fargs == 1 then fargs else (init fargs)
+ --state = if length fargs == 1 then () else (last fargs)
+ inports = case args of
+ -- Handle a single port specially, to prevent an extra 0 in the name
+ [port] -> [getPortNameMapForTy "portin" port]
+ ps -> getPortNameMapForTys "portin" 0 ps
+ outport = getPortNameMapForTy "portout" res
+
+mkHWFunction (Rec _) =
+ error "Recursive binders not supported"
data VHDLSession = VHDLSession {
nameCount :: Int, -- A counter that can be used to generate unique names
funcs :: [(String, HWFunction)] -- All functions available, indexed by name
-}
+} deriving (Show)
+
+type VHDLState = State.State VHDLSession
+
+-- Add the function to the session
+addFunc :: String -> HWFunction -> VHDLState ()
+addFunc name f = do
+ fs <- State.gets funcs -- Get the funcs element from the session
+ State.modify (\x -> x {funcs = (name, f) : fs }) -- Prepend name and f
+
+-- Lookup the function with the given name in the current session. Errors if
+-- it was not found.
+getHWFunc :: String -> VHDLState HWFunction
+getHWFunc name = do
+ fs <- State.gets funcs -- Get the funcs element from the session
+ return $ Maybe.fromMaybe
+ (error $ "Function " ++ name ++ "is unknown? This should not happen!")
+ (lookup name fs)
builtin_funcs =
[
- ("hwxor", HWFunction (Args [Port "a", Port "b"]) (Port "o")),
- ("hwand", HWFunction (Args [Port "a", Port "b"]) (Port "o"))
+ ("hwxor", HWFunction [Port "a", Port "b"] (Port "o")),
+ ("hwand", HWFunction [Port "a", Port "b"] (Port "o"))
]