-module Main(main) where
+module Translator where
import GHC
import CoreSyn
import qualified CoreUtils
--core <- GHC.compileToCoreSimplified "Adders.hs"
core <- GHC.compileToCoreSimplified "Adders.hs"
--liftIO $ printBinds (cm_binds core)
- let binds = Maybe.mapMaybe (findBind (cm_binds core)) ["full_adder", "half_adder"]
+ let binds = Maybe.mapMaybe (findBind (cm_binds core)) ["dff"]
liftIO $ printBinds binds
-- Turn bind into VHDL
- let vhdl = State.evalState (mkVHDL binds) (VHDLSession 0 [])
+ let (vhdl, sess) = State.runState (mkVHDL binds) (VHDLSession 0 [])
liftIO $ putStr $ render $ ForSyDe.Backend.Ppr.ppr vhdl
liftIO $ ForSyDe.Backend.VHDL.FileIO.writeDesignFile vhdl "../vhdl/vhdl/output.vhdl"
+ liftIO $ putStr $ "\n\nFinal session:\n" ++ show sess
return ()
where
-- Turns the given bind into VHDL
mkVHDL binds = do
-- Add the builtin functions
mapM (uncurry addFunc) builtin_funcs
- -- Get the function signatures
- funcs <- mapM mkHWFunction binds
- -- Add them to the session
- mapM (uncurry addFunc) funcs
- let entities = map getEntity (snd $ unzip funcs)
- -- Create architectures for them
- archs <- mapM getArchitecture binds
+ -- Create entities and architectures for them
+ units <- mapM expandBind binds
return $ AST.DesignFile
[]
- ((map AST.LUEntity entities) ++ (map AST.LUArch archs))
+ (concat units)
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 (Signal portname _) (Signal signame _) =
+getPortMapEntry (Single (portname, _)) (Single (signame, _)) =
(Just portname) AST.:=>: (AST.ADName (AST.NSimple signame))
expandExpr ::
[(CoreBndr, SignalNameMap)]
-- Find the type of the binder
let (arg_ty, _) = Type.splitFunTy (CoreUtils.exprType lam)
-- Create signal names for the binder
- let arg_signal = getPortNameMapForTy ("xxx") arg_ty
+ -- TODO: We assume arguments are ports here
+ let arg_signal = getPortNameMapForTy signal_name arg_ty (useAsPort arg_ty)
-- Create the corresponding signal declarations
let signal_decls = mkSignalsFromMap arg_signal
-- Add the binder to the list of binds
res_signal')
expandExpr binds (Var id) =
- return ([], [], [], Signal signal_id ty)
+ return ([], [], [], bind)
where
-- Lookup the id in our binds map
- Signal signal_id ty = Maybe.fromMaybe
+ bind = Maybe.fromMaybe
(error $ "Argument " ++ getOccString id ++ "is unknown")
(lookup id binds)
res_signals')
expandExpr binds app@(App _ _) = do
- let ((Var f), args) = collectArgs app
- if isTupleConstructor f
- then
- expandBuildTupleExpr binds args
- else
+ -- Is this a data constructor application?
+ case CoreUtils.exprIsConApp_maybe app of
+ -- Is this a tuple construction?
+ Just (dc, args) -> if DataCon.isTupleCon dc
+ then
+ expandBuildTupleExpr binds (dataConAppArgs dc args)
+ else
+ error "Data constructors other than tuples not supported"
+ otherise ->
+ -- Normal function application, should map to a component instantiation
+ let ((Var f), args) = collectArgs app in
expandApplicationExpr binds (CoreUtils.exprType app) f args
expandExpr binds expr@(Case (Var v) b _ alts) =
-- See expandExpr
expandBuildTupleExpr binds args = do
-- Split the tuple constructor arguments into types and actual values.
- let (_, vals) = splitTupleConstructorArgs args
-- Expand each of the values in the tuple
(signals_declss, statementss, arg_signalss, res_signals) <-
- (Monad.liftM List.unzip4) $ mapM (expandExpr binds) vals
+ (Monad.liftM List.unzip4) $ mapM (expandExpr binds) args
if any (not . null) arg_signalss
then error "Putting high order functions in tuples not supported"
else
-- Generate a unique name for the application
appname <- uniqueName ("app_" ++ name)
-- Lookup the hwfunction to instantiate
- HWFunction vhdl_id inports outport <- getHWFunc name
+ HWFunction vhdl_id inports outport <- getHWFunc (appToHsFunction f args ty)
-- Expand each of the args, so each of them is reduced to output signals
(arg_signal_decls, arg_statements, arg_res_signals) <- expandArgs binds args
-- Bind each of the input ports to the expanded arguments
let inmaps = concat $ zipWith createAssocElems inports arg_res_signals
-- Create signal names for our result
- let res_signal = getPortNameMapForTy (appname ++ "_out") ty
+ -- TODO: We assume the result is a port here
+ let res_signal = getPortNameMapForTy (appname ++ "_out") ty (useAsPort ty)
-- Create the corresponding signal declarations
let signal_decls = mkSignalsFromMap res_signal
-- Bind each of the output ports to our output signals
-> SignalNameMap -- The signals to bind to it
-> [AST.AssocElem] -- The resulting port map lines
-createAssocElems (Signal port_id _) (Signal signal_id _) =
+createAssocElems (Single (port_id, _)) (Single (signal_id, _)) =
[(Just port_id) AST.:=>: (AST.ADName (AST.NSimple signal_id))]
createAssocElems (Tuple ports) (Tuple signals) =
SignalNameMap
-> [AST.SigDec]
-mkSignalsFromMap (Signal id ty) =
+mkSignalsFromMap (Single (id, ty)) =
[mkSignalFromId id ty]
mkSignalsFromMap (Tuple signals) =
expandArgs _ [] = return ([], [], [])
--- Is the given name a (binary) tuple constructor
-isTupleConstructor :: Var.Var -> Bool
-isTupleConstructor var =
- Name.isWiredInName name
- && Name.nameModule name == tuple_mod
- && (Name.occNameString $ Name.nameOccName name) == "(,)"
- where
- 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)
+-- Extract the arguments from a data constructor application (that is, the
+-- normal args, leaving out the type args).
+dataConAppArgs :: DataCon -> [CoreExpr] -> [CoreExpr]
+dataConAppArgs dc args =
+ drop tycount args
where
- (tys, vals) = splitTupleConstructorArgs es
-
-splitTupleConstructorArgs [] = ([], [])
+ tycount = length $ DataCon.dataConAllTyVars dc
mapOutputPorts ::
SignalNameMap -- The output portnames of the component
-- Map the output port of a component to the output port of the containing
-- entity.
-mapOutputPorts (Signal portname _) (Signal signalname _) =
+mapOutputPorts (Single (portname, _)) (Single (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)
+expandBind ::
+ CoreBind -- The binder to expand into VHDL
+ -> VHDLState [AST.LibraryUnit] -- The resulting VHDL
+
+expandBind (Rec _) = error "Recursive binders not supported"
+
+expandBind bind@(NonRec var expr) = do
+ -- Create the function signature
+ let ty = CoreUtils.exprType expr
+ let hsfunc = mkHsFunction var ty
+ hwfunc <- mkHWFunction bind hsfunc
+ -- Add it to the session
+ addFunc hsfunc hwfunc
+ arch <- getArchitecture hsfunc hwfunc expr
+ -- Give every entity a clock port
+ -- TODO: Omit this for stateless entities
+ let clk_port = AST.IfaceSigDec (mkVHDLId "clk") AST.In vhdl_bit_ty
+ let entity = getEntity hwfunc [clk_port]
+ return $ [
+ AST.LUEntity entity,
+ AST.LUArch arch ]
+
getArchitecture ::
- CoreBind -- The binder to expand into an architecture
+ HsFunction -- The function interface
+ -> HWFunction -- The function to generate an architecture for
+ -> CoreExpr -- The expression that is bound to the function
-> VHDLState AST.ArchBody -- The resulting architecture
-getArchitecture (Rec _) = error "Recursive binders not supported"
-
-getArchitecture (NonRec var expr) = do
- let name = (getOccString var)
- HWFunction vhdl_id inports outport <- getHWFunc name
- sess <- State.get
+getArchitecture hsfunc hwfunc expr = do
+ -- Unpack our hwfunc
+ let HWFunction vhdl_id inports outport = hwfunc
+ -- Expand the expression into an architecture body
(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
+ let (inport_assigns, instate_map) = concat_elements $ unzip $ zipWith3 createSignalAssignments arg_signals inports (hsArgs hsfunc)
+ let (outport_assigns, outstate_map) = createSignalAssignments outport res_signal (hsRes hsfunc)
+ let state_procs = map AST.CSPSm $ createStateProcs (sortMap instate_map) (sortMap outstate_map)
return $ AST.ArchBody
(AST.unsafeVHDLBasicId "structural")
(AST.NSimple vhdl_id)
(map AST.BDISD signal_decls)
- (inport_assigns ++ outport_assigns ++ statements)
+ (state_procs ++ inport_assigns ++ outport_assigns ++ statements)
+
+-- | Sorts a map modeled as a list of (key,value) pairs by key
+sortMap :: Ord a => [(a, b)] -> [(a, b)]
+sortMap = List.sortBy (\(a, _) (b, _) -> compare a b)
+
+-- | Generate procs for state variables
+createStateProcs ::
+ [(Int, AST.VHDLId)]
+ -- ^ The sorted list of signals that should be assigned
+ -- to each state
+ -> [(Int, AST.VHDLId)]
+ -- ^ The sorted list of signals that contain each new state
+ -> [AST.ProcSm] -- ^ The resulting procs
+
+createStateProcs ((old_num, old_id):olds) ((new_num, new_id):news) =
+ if (old_num == new_num)
+ then
+ AST.ProcSm label [clk] [statement] : createStateProcs olds news
+ else
+ error "State numbers don't match!"
+ where
+ label = mkVHDLId $ "state_" ++ (show old_num)
+ clk = mkVHDLId "clk"
+ rising_edge = AST.NSimple $ mkVHDLId "rising_edge"
+ wform = AST.Wform [AST.WformElem (AST.PrimName $ AST.NSimple $ new_id) Nothing]
+ assign = AST.SigAssign (AST.NSimple old_id) wform
+ rising_edge_clk = AST.PrimFCall $ AST.FCall rising_edge [Nothing AST.:=>: (AST.ADName $ AST.NSimple clk)]
+ statement = AST.IfSm rising_edge_clk [assign] [] Nothing
+
+createStateProcs [] [] = []
-- Generate a VHDL entity declaration for the given function
-getEntity :: HWFunction -> AST.EntityDec
-getEntity (HWFunction vhdl_id inports outport) =
+getEntity :: HWFunction -> [AST.IfaceSigDec] -> AST.EntityDec
+getEntity (HWFunction vhdl_id inports outport) extra_ports =
AST.EntityDec vhdl_id ports
where
ports =
(concat $ map (mkIfaceSigDecs AST.In) inports)
++ mkIfaceSigDecs AST.Out outport
+ ++ extra_ports
mkIfaceSigDecs ::
AST.Mode -- The port's mode (In or Out)
-> SignalNameMap -- The ports to generate a map for
-> [AST.IfaceSigDec] -- The resulting ports
-mkIfaceSigDecs mode (Signal port_id ty) =
+mkIfaceSigDecs mode (Single (port_id, ty)) =
[AST.IfaceSigDec port_id mode ty]
mkIfaceSigDecs mode (Tuple ports) =
concat $ map (mkIfaceSigDecs mode) ports
+-- Unused values (state) don't generate ports
+mkIfaceSigDecs mode Unused =
+ []
+
-- Create concurrent assignments of one map of signals to another. The maps
-- should have a similar form.
createSignalAssignments ::
- SignalNameMap -- The signals to assign to
- -> SignalNameMap -- The signals to assign
- -> [AST.ConcSm] -- The resulting assignments
+ SignalNameMap -- The signals to assign to
+ -> SignalNameMap -- The signals to assign
+ -> HsUseMap -- What function does each of the signals have?
+ -> ([AST.ConcSm], -- The resulting assignments
+ [(Int, AST.VHDLId)]) -- The resulting state -> signal mappings
-- 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]
+createSignalAssignments (Single (dst, _)) (Single (src, _)) (Single Port)=
+ ([AST.CSSASm assign], [])
where
src_name = AST.NSimple src
src_expr = AST.PrimName src_name
dst_name = (AST.NSimple dst)
assign = dst_name AST.:<==: (AST.ConWforms [] src_wform Nothing)
-createSignalAssignments (Tuple dsts) (Tuple srcs) =
- concat $ zipWith createSignalAssignments dsts srcs
-
-createSignalAssignments dst src =
- error $ "Non matching source and destination: " ++ show dst ++ "\nand\n" ++ show src
-
-data SignalNameMap =
- Tuple [SignalNameMap]
- | Signal AST.VHDLId AST.TypeMark -- A signal (or port) of the given (VDHL) type
- deriving (Show)
+createSignalAssignments (Tuple dsts) (Tuple srcs) (Tuple uses) =
+ concat_elements $ unzip $ zipWith3 createSignalAssignments dsts srcs uses
+
+createSignalAssignments Unused (Single (src, _)) (Single (State n)) =
+ -- Write state
+ ([], [(n, src)])
+
+createSignalAssignments (Single (dst, _)) Unused (Single (State n)) =
+ -- Read state
+ ([], [(n, dst)])
+
+createSignalAssignments dst src use =
+ error $ "Non matching source and destination: " ++ show dst ++ " <= " ++ show src ++ " (Used as " ++ show use ++ ")"
+
+type SignalNameMap = HsValueMap (AST.VHDLId, AST.TypeMark)
+
+-- | A datatype that maps each of the single values in a haskell structure to
+-- a mapto. The map has the same structure as the haskell type mapped, ie
+-- nested tuples etc.
+data HsValueMap mapto =
+ Tuple [HsValueMap mapto]
+ | Single mapto
+ | Unused
+ deriving (Show, Eq)
+
+-- | Creates a HsValueMap with the same structure as the given type, using the
+-- given function for mapping the single types.
+mkHsValueMap ::
+ ((Type, s) -> (HsValueMap mapto, s))
+ -- ^ A function to map single value Types
+ -- (basically anything but tuples) to a
+ -- HsValueMap (not limited to the Single
+ -- constructor) Also accepts and produces a
+ -- state that will be passed on between
+ -- each call to the function.
+ -> s -- ^ The initial state
+ -> Type -- ^ The type to map to a HsValueMap
+ -> (HsValueMap mapto, s) -- ^ The resulting map and state
+
+mkHsValueMap f s ty =
+ case Type.splitTyConApp_maybe ty of
+ Just (tycon, args) ->
+ if (TyCon.isTupleTyCon tycon)
+ then
+ let (args', s') = mapTuple f s args in
+ -- Handle tuple construction especially
+ (Tuple args', s')
+ else
+ -- And let f handle the rest
+ f (ty, s)
+ -- And let f handle the rest
+ Nothing -> f (ty, s)
+ where
+ mapTuple f s (ty:tys) =
+ let (map, s') = mkHsValueMap f s ty in
+ let (maps, s'') = mapTuple f s' tys in
+ (map: maps, s'')
+ mapTuple f s [] = ([], s)
-- Generate a port name map (or multiple for tuple types) in the given direction for
-- each type given.
-getPortNameMapForTys :: String -> Int -> [Type] -> [SignalNameMap]
-getPortNameMapForTys prefix num [] = []
-getPortNameMapForTys prefix num (t:ts) =
- (getPortNameMapForTy (prefix ++ show num) t) : getPortNameMapForTys prefix (num + 1) ts
+getPortNameMapForTys :: String -> Int -> [Type] -> [HsUseMap] -> [SignalNameMap]
+getPortNameMapForTys prefix num [] [] = []
+getPortNameMapForTys prefix num (t:ts) (u:us) =
+ (getPortNameMapForTy (prefix ++ show num) t u) : getPortNameMapForTys prefix (num + 1) ts us
+
+getPortNameMapForTy :: String -> Type -> HsUseMap -> SignalNameMap
+getPortNameMapForTy name _ (Single (State _)) =
+ Unused
-getPortNameMapForTy :: String -> Type -> SignalNameMap
-getPortNameMapForTy name ty =
+getPortNameMapForTy name ty use =
if (TyCon.isTupleTyCon tycon) then
+ let (Tuple uses) = use in
-- Expand tuples we find
- Tuple (getPortNameMapForTys name 0 args)
+ Tuple (getPortNameMapForTys name 0 args uses)
else -- Assume it's a type constructor application, ie simple data type
- Signal (AST.unsafeVHDLBasicId name) (vhdl_ty ty)
+ Single ((AST.unsafeVHDLBasicId name), (vhdl_ty ty))
where
(tycon, args) = Type.splitTyConApp ty
-- output ports.
mkHWFunction ::
CoreBind -- The core binder to generate the interface for
- -> VHDLState (String, HWFunction) -- The name of the function and its interface
+ -> HsFunction -- The HsFunction describing the function
+ -> VHDLState HWFunction -- The function interface
-mkHWFunction (NonRec var expr) =
- return (name, HWFunction (mkVHDLId name) inports outport)
+mkHWFunction (NonRec var expr) hsfunc =
+ return $ HWFunction (mkVHDLId name) 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)
+ (args, res) = Type.splitFunTys ty
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
+ [port] -> [getPortNameMapForTy "portin" port (head $ hsArgs hsfunc)]
+ ps -> getPortNameMapForTys "portin" 0 ps (hsArgs hsfunc)
+ outport = getPortNameMapForTy "portout" res (hsRes hsfunc)
-mkHWFunction (Rec _) =
+mkHWFunction (Rec _) _ =
error "Recursive binders not supported"
+-- | How is a given (single) value in a function's type (ie, argument or
+-- return value) used?
+data HsValueUse =
+ Port -- ^ Use it as a port (input or output)
+ | State Int -- ^ Use it as state (input or output). The int is used to
+ -- match input state to output state.
+ deriving (Show, Eq)
+
+useAsPort :: Type -> HsUseMap
+useAsPort = fst . (mkHsValueMap (\(ty, s) -> (Single Port, s)) 0)
+useAsState :: Type -> HsUseMap
+useAsState = fst . (mkHsValueMap (\(ty, s) -> (Single $ State s, s + 1)) 0)
+
+type HsUseMap = HsValueMap HsValueUse
+
+-- | This type describes a particular use of a Haskell function and is used to
+-- look up an appropriate hardware description.
+data HsFunction = HsFunction {
+ hsName :: String, -- ^ What was the name of the original Haskell function?
+ hsArgs :: [HsUseMap], -- ^ How are the arguments used?
+ hsRes :: HsUseMap -- ^ How is the result value used?
+} deriving (Show, Eq)
+
+-- | Translate a function application to a HsFunction. i.e., which function
+-- do you need to translate this function application.
+appToHsFunction ::
+ Var.Var -- ^ The function to call
+ -> [CoreExpr] -- ^ The function arguments
+ -> Type -- ^ The return type
+ -> HsFunction -- ^ The needed HsFunction
+
+appToHsFunction f args ty =
+ HsFunction hsname hsargs hsres
+ where
+ hsargs = map (useAsPort . CoreUtils.exprType) args
+ hsres = useAsPort ty
+ hsname = getOccString f
+
+-- | Translate a top level function declaration to a HsFunction. i.e., which
+-- interface will be provided by this function. This function essentially
+-- defines the "calling convention" for hardware models.
+mkHsFunction ::
+ Var.Var -- ^ The function defined
+ -> Type -- ^ The function type (including arguments!)
+ -> HsFunction -- ^ The resulting HsFunction
+
+mkHsFunction f ty =
+ HsFunction hsname hsargs hsres
+ where
+ hsname = getOccString f
+ (arg_tys, res_ty) = Type.splitFunTys ty
+ -- The last argument must be state
+ state_ty = last arg_tys
+ state = useAsState state_ty
+ -- All but the last argument are inports
+ inports = map useAsPort (init arg_tys)
+ hsargs = inports ++ [state]
+ hsres = case splitTupleType res_ty of
+ -- Result type must be a two tuple (state, ports)
+ Just [outstate_ty, outport_ty] -> if Type.coreEqType state_ty outstate_ty
+ then
+ Tuple [state, useAsPort outport_ty]
+ else
+ error $ "Input state type of function " ++ hsname ++ ": " ++ (showSDoc $ ppr state_ty) ++ " does not match output state type: " ++ (showSDoc $ ppr outstate_ty)
+ otherwise -> error $ "Return type of top-level function " ++ hsname ++ " must be a two-tuple containing a state and output ports."
+
data VHDLSession = VHDLSession {
- nameCount :: Int, -- A counter that can be used to generate unique names
- funcs :: [(String, HWFunction)] -- All functions available, indexed by name
+ nameCount :: Int, -- A counter that can be used to generate unique names
+ funcs :: [(HsFunction, HWFunction)] -- All functions available
} deriving (Show)
type VHDLState = State.State VHDLSession
-- Add the function to the session
-addFunc :: String -> HWFunction -> VHDLState ()
-addFunc name f = do
+addFunc :: HsFunction -> HWFunction -> VHDLState ()
+addFunc hsfunc hwfunc = do
fs <- State.gets funcs -- Get the funcs element from the session
- State.modify (\x -> x {funcs = (name, f) : fs }) -- Prepend name and f
+ State.modify (\x -> x {funcs = (hsfunc, hwfunc) : 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
+getHWFunc :: HsFunction -> VHDLState HWFunction
+getHWFunc hsfunc = 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)
+ (error $ "Function " ++ (hsName hsfunc) ++ "is unknown? This should not happen!")
+ (lookup hsfunc fs)
+
+-- | Splits a tuple type into a list of element types, or Nothing if the type
+-- is not a tuple type.
+splitTupleType ::
+ Type -- ^ The type to split
+ -> Maybe [Type] -- ^ The tuples element types
+
+splitTupleType ty =
+ case Type.splitTyConApp_maybe ty of
+ Just (tycon, args) -> if TyCon.isTupleTyCon tycon
+ then
+ Just args
+ else
+ Nothing
+ Nothing -> Nothing
-- Makes the given name unique by appending a unique number.
-- This does not do any checking against existing names, so it only guarantees
mkVHDLId :: String -> AST.VHDLId
mkVHDLId = AST.unsafeVHDLBasicId
+-- Concatenate each of the lists of lists inside the given tuple.
+-- Since the element types in the lists might differ, we can't generalize
+-- this (unless we pass in f twice).
+concat_elements :: ([[a]], [[b]]) -> ([a], [b])
+concat_elements (a, b) = (concat a, concat b)
+
builtin_funcs =
[
- ("hwxor", HWFunction (mkVHDLId "hwxor") [Signal (mkVHDLId "a") vhdl_bit_ty, Signal (mkVHDLId "b") vhdl_bit_ty] (Signal (mkVHDLId "o") vhdl_bit_ty)),
- ("hwand", HWFunction (mkVHDLId "hwand") [Signal (mkVHDLId "a") vhdl_bit_ty, Signal (mkVHDLId "b") vhdl_bit_ty] (Signal (mkVHDLId "o") vhdl_bit_ty)),
- ("hwor", HWFunction (mkVHDLId "hwor") [Signal (mkVHDLId "a") vhdl_bit_ty, Signal (mkVHDLId "b") vhdl_bit_ty] (Signal (mkVHDLId "o") vhdl_bit_ty)),
- ("hwnot", HWFunction (mkVHDLId "hwnot") [Signal (mkVHDLId "i") vhdl_bit_ty] (Signal (mkVHDLId "o") vhdl_bit_ty))
+ (HsFunction "hwxor" [(Single Port), (Single Port)] (Single Port), HWFunction (mkVHDLId "hwxor") [Single (mkVHDLId "a", vhdl_bit_ty), Single (mkVHDLId "b", vhdl_bit_ty)] (Single (mkVHDLId "o", vhdl_bit_ty))),
+ (HsFunction "hwand" [(Single Port), (Single Port)] (Single Port), HWFunction (mkVHDLId "hwand") [Single (mkVHDLId "a", vhdl_bit_ty), Single (mkVHDLId "b", vhdl_bit_ty)] (Single (mkVHDLId "o", vhdl_bit_ty))),
+ (HsFunction "hwor" [(Single Port), (Single Port)] (Single Port), HWFunction (mkVHDLId "hwor") [Single (mkVHDLId "a", vhdl_bit_ty), Single (mkVHDLId "b", vhdl_bit_ty)] (Single (mkVHDLId "o", vhdl_bit_ty))),
+ (HsFunction "hwnot" [(Single Port)] (Single Port), HWFunction (mkVHDLId "hwnot") [Single (mkVHDLId "i", vhdl_bit_ty)] (Single (mkVHDLId "o", vhdl_bit_ty)))
]
vhdl_bit_ty :: AST.TypeMark