- name = Var.varName var
- mod = nameModule name
- tuple_mod = Module.mkModule (Module.stringToPackageId "ghc-prim") (Module.mkModuleName "GHC.Tuple")
-
--- Split arguments into type arguments and value arguments This is probably
--- not really sufficient (not sure if Types can actually occur as value
--- arguments...)
-splitTupleConstructorArgs :: [CoreExpr] -> ([CoreExpr], [CoreExpr])
-splitTupleConstructorArgs (e:es) =
- case e of
- Type t -> (e:tys, vals)
- otherwise -> (tys, e:vals)
- where
- (tys, vals) = splitTupleConstructorArgs es
-
-splitTupleConstructorArgs [] = ([], [])
-
-mapOutputPorts ::
- SignalNameMap AST.VHDLId -- The output portnames of the component
- -> SignalNameMap AST.VHDLId -- The output portnames and/or signals to map these to
- -> [AST.AssocElem] -- The resulting output ports
-
--- Map the output port of a component to the output port of the containing
--- entity.
-mapOutputPorts (Signal portname) (Signal signalname) =
- [(Just portname) AST.:=>: (AST.ADName (AST.NSimple signalname))]
-
--- Map matching output ports in the tuple
-mapOutputPorts (Tuple ports) (Tuple signals) =
- concat (zipWith mapOutputPorts ports signals)
-
-getArchitecture ::
- CoreBind -- The binder to expand into an architecture
- -> VHDLState AST.ArchBody -- The resulting architecture
-
-getArchitecture (Rec _) = error "Recursive binders not supported"
-
-getArchitecture (NonRec var expr) = do
- let name = (getOccString var)
- HWFunction inports outport <- getHWFunc name
- sess <- State.get
- (signal_decls, statements, arg_signals, res_signal) <- expandExpr [] expr
- let inport_assigns = concat $ zipWith createSignalAssignments arg_signals inports
- let outport_assigns = createSignalAssignments outport res_signal
- return $ AST.ArchBody
- (AST.unsafeVHDLBasicId "structural")
- -- Use unsafe for now, to prevent pulling in ForSyDe error handling
- (AST.NSimple (AST.unsafeVHDLBasicId name))
- (map AST.BDISD signal_decls)
- (inport_assigns ++ outport_assigns ++ statements)
-
--- Create concurrent assignments of one map of signals to another. The maps
--- should have a similar form.
-createSignalAssignments ::
- SignalNameMap AST.VHDLId -- The signals to assign to
- -> SignalNameMap AST.VHDLId -- The signals to assign
- -> [AST.ConcSm] -- The resulting assignments
-
--- A simple assignment of one signal to another (greatly complicated because
--- signal assignments can be conditional with multiple conditions in VHDL).
-createSignalAssignments (Signal dst) (Signal src) =
- [AST.CSSASm assign]
- where
- src_name = AST.NSimple src
- src_expr = AST.PrimName src_name
- src_wform = AST.Wform [AST.WformElem src_expr Nothing]
- dst_name = (AST.NSimple dst)
- assign = dst_name AST.:<==: (AST.ConWforms [] src_wform Nothing)
-
-createSignalAssignments (Tuple dsts) (Tuple srcs) =
- concat $ zipWith createSignalAssignments dsts srcs
-
-data SignalNameMap t =
- Tuple [SignalNameMap t]
- | Signal t
- deriving (Show)
-
--- Generate a port name map (or multiple for tuple types) in the given direction for
--- each type given.
-getPortNameMapForTys :: String -> Int -> [Type] -> [SignalNameMap AST.VHDLId]
-getPortNameMapForTys prefix num [] = []
-getPortNameMapForTys prefix num (t:ts) =
- (getPortNameMapForTy (prefix ++ show num) t) : getPortNameMapForTys prefix (num + 1) ts
-
-getPortNameMapForTy :: String -> Type -> SignalNameMap AST.VHDLId
-getPortNameMapForTy name ty =
- if (TyCon.isTupleTyCon tycon) then
- -- Expand tuples we find
- Tuple (getPortNameMapForTys name 0 args)
- else -- Assume it's a type constructor application, ie simple data type
- -- TODO: Add type?
- Signal (AST.unsafeVHDLBasicId name)
- where
- (tycon, args) = Type.splitTyConApp ty
-
-data HWFunction = HWFunction { -- A function that is available in hardware
- inPorts :: [SignalNameMap AST.VHDLId],
- outPort :: SignalNameMap AST.VHDLId
- --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)
-
--- Makes the given name unique by appending a unique number.
--- This does not do any checking against existing names, so it only guarantees
--- uniqueness with other names generated by uniqueName.
-uniqueName :: String -> VHDLState String
-uniqueName name = do
- count <- State.gets nameCount -- Get the funcs element from the session
- State.modify (\s -> s {nameCount = count + 1})
- return $ name ++ "-" ++ (show count)
-
--- Shortcut
-mkVHDLId :: String -> AST.VHDLId
-mkVHDLId = AST.unsafeVHDLBasicId
-
-builtin_funcs =
- [
- ("hwxor", HWFunction [Signal $ mkVHDLId "a", Signal $ mkVHDLId "b"] (Signal $ mkVHDLId "o")),
- ("hwand", HWFunction [Signal $ mkVHDLId "a", Signal $ mkVHDLId "b"] (Signal $ mkVHDLId "o")),
- ("hwnot", HWFunction [Signal $ mkVHDLId "i"] (Signal $ mkVHDLId "o"))
- ]
-
-vhdl_bit_ty :: AST.TypeMark
-vhdl_bit_ty = AST.unsafeVHDLBasicId "Bit"