-- There must be a let at top level
let (CoreSyn.Let binds (CoreSyn.Var res)) = letexpr
-- TODO: Handle Nothing
- Just res' <- mkMap res
+ res' <- mkMap res
let vhdl_id = mkVHDLBasicId $ varToString fname ++ "_" ++ varToStringUniq fname
let ent_decl = createEntityAST vhdl_id args' res'
let signature = Entity vhdl_id args' res' ent_decl
createEntityAST ::
AST.VHDLId -- ^ The name of the function
-> [Port] -- ^ The entity's arguments
- -> Port -- ^ The entity's result
+ -> Maybe Port -- ^ The entity's result
-> AST.EntityDec -- ^ The entity with the ent_decl filled in as well
createEntityAST vhdl_id args res =
where
-- Create a basic Id, since VHDL doesn't grok filenames with extended Ids.
ports = map (mkIfaceSigDec AST.In) args
- ++ [mkIfaceSigDec AST.Out res]
+ ++ (Maybe.maybeToList res_port)
++ [clk_port]
-- Add a clk port if we have state
clk_port = AST.IfaceSigDec clockId AST.In std_logicTM
+ res_port = fmap (mkIfaceSigDec AST.Out) res
-- | Create a port declaration
mkIfaceSigDec ::
AST.Mode -- ^ The mode for the port (In / Out)
- -> (AST.VHDLId, AST.TypeMark) -- ^ The id and type for the port
+ -> Port -- ^ The id and type for the port
-> AST.IfaceSigDec -- ^ The resulting port declaration
mkIfaceSigDec mode (id, ty) = AST.IfaceSigDec id mode ty
iIface = ent_args signature
oIface = ent_res signature
iIds = map fst iIface
- oId = fst oIface
+ let (oId, oDec, oProc) = case oIface of
+ Just (id, ty) -> ( id
+ , [AST.SigDec id ty Nothing]
+ , [createOutputProc [id]])
+ -- No output port? Just use undefined for the output id, since it won't be
+ -- used by mkAssocElems when there is no output port.
+ Nothing -> (undefined, [], [])
let iDecs = map (\(vId, tm) -> AST.SigDec vId tm Nothing) iIface
let finalIDecs = iDecs ++
[AST.SigDec clockId std_logicTM (Just $ AST.PrimLit "'0'"),
AST.SigDec resetId std_logicTM (Just $ AST.PrimLit "'0'")]
- let oDecs = AST.SigDec (fst oIface) (snd oIface) Nothing
portmaps <- mkAssocElems (map idToVHDLExpr iIds) (AST.NSimple oId) signature
let mIns = mkComponentInst "totest" entId portmaps
(stimuliAssigns, stimuliDecs, cycles, used) <- createStimuliAssigns mCycles stimuli (head iIds)
(AST.Wform [AST.WformElem (AST.PrimLit "'1'") (Just $ AST.PrimLit "3 ns")])
Nothing)) : stimuliAssigns
let clkProc = createClkProc
- let outputProc = createOutputProc [oId]
let arch = AST.ArchBody
(AST.unsafeVHDLBasicId "test")
(AST.NSimple $ ent_id testent)
- (map AST.BDISD (finalIDecs ++ stimuliDecs ++ [oDecs]))
+ (map AST.BDISD (finalIDecs ++ stimuliDecs ++ oDec))
(mIns :
- ( (AST.CSPSm clkProc) : (AST.CSPSm outputProc) : finalAssigns ) )
+ ( (AST.CSPSm clkProc) : (fmap AST.CSPSm oProc) ++ finalAssigns ) )
return (arch, top : used)
createStimuliAssigns ::
-> Entity -- ^ The entity to map against.
-> TranslatorSession [AST.AssocElem] -- ^ The resulting port maps
mkAssocElems args res entity =
- -- Create the actual AssocElems
- return $ zipWith mkAssocElem ports sigs
+ return $ arg_maps ++ (Maybe.maybeToList res_map_maybe)
where
- -- Turn the ports and signals from a map into a flat list. This works,
- -- since the maps must have an identical form by definition. TODO: Check
- -- the similar form?
arg_ports = ent_args entity
- res_port = ent_res entity
- -- Extract the id part from the (id, type) tuple
- ports = map fst (res_port : arg_ports)
- -- Translate signal numbers into names
- sigs = (vhdlNameToVHDLExpr res : args)
+ res_port_maybe = ent_res entity
+ -- Create an expression of res to map against the output port
+ res_expr = vhdlNameToVHDLExpr res
+ -- Map each of the input ports
+ arg_maps = zipWith mkAssocElem (map fst arg_ports) args
+ -- Map the output port, if present
+ res_map_maybe = fmap (\port -> mkAssocElem (fst port) res_expr) res_port_maybe
-- | Create an VHDL port -> signal association
mkAssocElem :: AST.VHDLId -> AST.Expr -> AST.AssocElem
data Entity = Entity {
ent_id :: AST.VHDLId, -- ^ The id of the entity
ent_args :: [Port], -- ^ A port for each non-empty function argument
- ent_res :: Port, -- ^ The output port
+ ent_res :: Maybe Port, -- ^ The output port
ent_dec :: AST.EntityDec -- ^ The complete entity declaration
} deriving (Show);