packages feed

clash-lib 0.5.1 → 0.5.2

raw patch · 12 files changed

+444/−70 lines, 12 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

- CLaSH.Netlist.Types: [output] :: Component -> (Identifier, HWType)
- CLaSH.Primitives.Util: decodeAndReport :: (FromJSON a) => ByteString -> Maybe a
+ CLaSH.Driver.TopWrapper: [Clk] :: Text -> Int -> Clock
+ CLaSH.Driver.TopWrapper: [ClockPath] :: Maybe (Text, Text) -> [(Text, Clock)] -> ClockPath
+ CLaSH.Driver.TopWrapper: [ClockSource] :: Text -> [ClockPath] -> Maybe (Text, Text) -> Text -> Bool -> ClockSource
+ CLaSH.Driver.TopWrapper: [TopEntity] :: Text -> [Text] -> [Text] -> [(Text, Int)] -> [(Text, Int)] -> [ClockSource] -> TopEntity
+ CLaSH.Driver.TopWrapper: [c_lock] :: ClockSource -> Text
+ CLaSH.Driver.TopWrapper: [c_name] :: ClockSource -> Text
+ CLaSH.Driver.TopWrapper: [c_paths] :: ClockSource -> [ClockPath]
+ CLaSH.Driver.TopWrapper: [c_reset] :: ClockSource -> Maybe (Text, Text)
+ CLaSH.Driver.TopWrapper: [c_sync] :: ClockSource -> Bool
+ CLaSH.Driver.TopWrapper: [clk_name] :: Clock -> Text
+ CLaSH.Driver.TopWrapper: [clk_rate] :: Clock -> Int
+ CLaSH.Driver.TopWrapper: [cp_inp] :: ClockPath -> Maybe (Text, Text)
+ CLaSH.Driver.TopWrapper: [cp_outp] :: ClockPath -> [(Text, Clock)]
+ CLaSH.Driver.TopWrapper: [t_clocks] :: TopEntity -> [ClockSource]
+ CLaSH.Driver.TopWrapper: [t_extraIn] :: TopEntity -> [(Text, Int)]
+ CLaSH.Driver.TopWrapper: [t_extraOut] :: TopEntity -> [(Text, Int)]
+ CLaSH.Driver.TopWrapper: [t_inputs] :: TopEntity -> [Text]
+ CLaSH.Driver.TopWrapper: [t_name] :: TopEntity -> Text
+ CLaSH.Driver.TopWrapper: [t_outputs] :: TopEntity -> [Text]
+ CLaSH.Driver.TopWrapper: clockPorts :: ClockPath -> ([(Identifier, Expr)], [Clock])
+ CLaSH.Driver.TopWrapper: data Clock
+ CLaSH.Driver.TopWrapper: data ClockPath
+ CLaSH.Driver.TopWrapper: data ClockSource
+ CLaSH.Driver.TopWrapper: data TopEntity
+ CLaSH.Driver.TopWrapper: extraIn :: Maybe TopEntity -> [(Identifier, HWType)]
+ CLaSH.Driver.TopWrapper: extraOut :: Maybe TopEntity -> [(Identifier, HWType)]
+ CLaSH.Driver.TopWrapper: genSyncReset :: PrimMap -> Identifier -> Identifier -> Clock -> NetlistMonad [Declaration]
+ CLaSH.Driver.TopWrapper: generateTopEnt :: String -> IO (Maybe TopEntity)
+ CLaSH.Driver.TopWrapper: instance Eq Clock
+ CLaSH.Driver.TopWrapper: instance FromJSON Clock
+ CLaSH.Driver.TopWrapper: instance FromJSON ClockPath
+ CLaSH.Driver.TopWrapper: instance FromJSON ClockSource
+ CLaSH.Driver.TopWrapper: instance FromJSON TopEntity
+ CLaSH.Driver.TopWrapper: instance Show Clock
+ CLaSH.Driver.TopWrapper: instance Show ClockPath
+ CLaSH.Driver.TopWrapper: instance Show ClockSource
+ CLaSH.Driver.TopWrapper: instance Show TopEntity
+ CLaSH.Driver.TopWrapper: mkClock :: ClockSource -> ([Declaration], (Identifier, [Clock], Bool))
+ CLaSH.Driver.TopWrapper: mkClocks :: PrimMap -> [(Identifier, HWType)] -> Maybe TopEntity -> [Declaration]
+ CLaSH.Driver.TopWrapper: mkInput :: [Identifier] -> (Identifier, HWType) -> Int -> ([Identifier], ([(Identifier, HWType)], ([Declaration], Identifier)))
+ CLaSH.Driver.TopWrapper: mkOutput :: [Identifier] -> (Identifier, HWType) -> Int -> ([Identifier], ([(Identifier, HWType)], ([Declaration], Identifier)))
+ CLaSH.Driver.TopWrapper: mkResets :: PrimMap -> [(Identifier, HWType)] -> [(Identifier, [Clock], Bool)] -> [Declaration]
+ CLaSH.Driver.TopWrapper: mkTopWrapper :: PrimMap -> Maybe TopEntity -> Component -> Component
+ CLaSH.Driver.TopWrapper: mkVectorChain :: Int -> HWType -> [Identifier] -> Expr
+ CLaSH.Driver.TopWrapper: unsafeRunNetlist :: NetlistMonad a -> a
+ CLaSH.Netlist.Types: [outputs] :: Component -> [(Identifier, HWType)]
- CLaSH.Driver: generateHDL :: Backend backend => BindingMap -> Maybe backend -> PrimMap -> HashMap TyConName TyCon -> (HashMap TyConName TyCon -> Type -> Maybe (Either String HWType)) -> (HashMap TyConName TyCon -> Term -> Term) -> DebugLevel -> IO ()
+ CLaSH.Driver: generateHDL :: Backend backend => BindingMap -> Maybe backend -> PrimMap -> HashMap TyConName TyCon -> (HashMap TyConName TyCon -> Type -> Maybe (Either String HWType)) -> (HashMap TyConName TyCon -> Term -> Term) -> Maybe TopEntity -> DebugLevel -> IO ()
- CLaSH.Netlist.Types: [Clock] :: Int -> HWType
+ CLaSH.Netlist.Types: [Clock] :: Identifier -> Int -> HWType
- CLaSH.Netlist.Types: [Component] :: Identifier -> [(Identifier, HWType)] -> [(Identifier, HWType)] -> (Identifier, HWType) -> [Declaration] -> Component
+ CLaSH.Netlist.Types: [Component] :: Identifier -> [(Identifier, HWType)] -> [(Identifier, HWType)] -> [(Identifier, HWType)] -> [Declaration] -> Component
- CLaSH.Netlist.Types: [Reset] :: Int -> HWType
+ CLaSH.Netlist.Types: [Reset] :: Identifier -> Int -> HWType

Files

CHANGELOG.md view
@@ -1,5 +1,9 @@ # Changelog for the [`clash-lib`](http://hackage.haskell.org/package/clash-lib) package +## 0.5.2 *May 1st 2015*+* New features:+  * Generate wrappers around `topEntity` that have constant names and types+ ## 0.5.1 *April 20th 2015* * GHC 7.10 support 
clash-lib.cabal view
@@ -1,5 +1,5 @@ Name:                 clash-lib-Version:              0.5.1+Version:              0.5.2 Synopsis:             CAES Language for Synchronous Hardware - As a Library Description:   CλaSH (pronounced ‘clash’) is a functional hardware description language that@@ -94,6 +94,7 @@                        CLaSH.Driver                       CLaSH.Driver.TestbenchGen+                      CLaSH.Driver.TopWrapper                       CLaSH.Driver.Types                        CLaSH.Netlist@@ -120,5 +121,6 @@                        CLaSH.Util -  Other-Modules:      Paths_clash_lib+  Other-Modules:      Data.Aeson.Extra+                      Paths_clash_lib                       Unbound.Generics.LocallyNameless.Extra
src/CLaSH/Driver.hs view
@@ -25,6 +25,7 @@ import           CLaSH.Core.Type                  (Type) import           CLaSH.Core.TyCon                 (TyCon, TyConName) import           CLaSH.Driver.TestbenchGen+import           CLaSH.Driver.TopWrapper import           CLaSH.Driver.Types import           CLaSH.Netlist                    (genNetlist) import           CLaSH.Netlist.Types              (Component (..), HWType)@@ -42,9 +43,10 @@             -> HashMap TyConName TyCon -- ^ TyCon cache             -> (HashMap TyConName TyCon -> Type -> Maybe (Either String HWType)) -- ^ Hardcoded 'Type' -> 'HWType' translator             -> (HashMap TyConName TyCon -> Term -> Term) -- ^ Hardcoded evaluator (delta-reduction)+            -> Maybe TopEntity             -> DebugLevel -- ^ Debug information level for the normalization process             -> IO ()-generateHDL bindingsMap hdlState primMap tcm typeTrans eval dbgLevel = do+generateHDL bindingsMap hdlState primMap tcm typeTrans eval teM dbgLevel = do   start <- Clock.getCurrentTime   prepTime <- start `deepseq` bindingsMap `deepseq` tcm `deepseq` Clock.getCurrentTime   let prepStartDiff = Clock.diffUTCTime prepTime start@@ -105,7 +107,8 @@       putStrLn $ "Testbench generation took " ++ show netTBDiff        let hdlState' = fromMaybe (initBackend :: backend) hdlState-          hdlDocs = createHDL hdlState' (netlist ++ testBench)+          topWrapper = mkTopWrapper primMap teM topComponent+          hdlDocs = createHDL hdlState' (topWrapper : netlist ++ testBench)           dir = concat [ "./" ++ CLaSH.Backend.name hdlState' ++ "/"                        , takeWhile (/= '.') (name2String $ fst topEntity)                        , "/"@@ -122,8 +125,8 @@  -- | Pretty print Components to HDL Documents createHDL :: Backend backend-           => backend-           -> [Component]+           => backend     -- ^ Backend+           -> [Component] -- ^ List of components            -> [(String,Doc)] createHDL backend components = flip evalState backend $ do   (hdlNms,hdlDocs) <- unzip <$> mapM genHDL components
src/CLaSH/Driver/TestbenchGen.hs view
@@ -45,7 +45,7 @@              -> Component                    -- ^ Component to generate TB for              -> IO ([Component]) genTestBench dbgLvl supply primMap typeTrans tcm eval cmpCnt globals stimuliNmM expectedNmM-  (Component cName hidden [inp] outp _) = do+  (Component cName hidden [inp] [outp] _) = do   let ioDecl  = [ uncurry NetDecl inp                 , uncurry NetDecl outp                 ]@@ -61,8 +61,8 @@   (expInst,expComps,hidden'') <- maybe (return (finExpr,[],hidden'))                                                  (genVerifier cmpCnt' primMap globals typeTrans tcm normalizeSignal hidden' outp)                                                  expectedNmM-  let clkNms = mapMaybe (\hd -> case hd of (clkNm,Clock _) -> Just clkNm ; _ -> Nothing) hidden-      rstNms = mapMaybe (\hd -> case hd of (clkNm,Reset _) -> Just clkNm ; _ -> Nothing) hidden+  let clkNms = mapMaybe (\hd -> case hd of (clkNm,Clock _ _) -> Just clkNm ; _ -> Nothing) hidden+      rstNms = mapMaybe (\hd -> case hd of (clkNm,Reset _ _) -> Just clkNm ; _ -> Nothing) hidden       clks   = mapMaybe (genClock primMap) hidden''       rsts   = mapMaybe (genReset primMap) hidden'' @@ -71,7 +71,7 @@                         (concat [ clkNms, rstNms, [fst inp], [fst outp] ])                    ) -      tbComp = Component "testbench" [] [] ("done",Bool)+      tbComp = Component "testbench" [] [] [("done",Bool)]                   (concat [ finDecl                           , concat clks                           , concat rsts@@ -92,13 +92,13 @@ genClock :: PrimMap          -> (Identifier,HWType)          -> Maybe [Declaration]-genClock primMap (clkName,Clock rate) = Just clkDecls+genClock primMap (clkName,Clock clkSym rate) = Just clkDecls   where     clkGenDecl = case HashMap.lookup "CLaSH.Driver.TestbenchGen.clockGen" primMap of       Just (BlackBox _ (Left templ)) -> let (rising,rest) = divMod (toInteger rate) 2                                             falling       = rising + rest                                             ctx = emptyBBContext-                                                    { bbResult = (Left (Identifier clkName Nothing), Clock rate)+                                                    { bbResult = (Left (Identifier clkName Nothing), Clock clkSym rate)                                                     , bbInputs = [ (Left (N.Literal Nothing (NumLit 2)),Integer,True)                                                                  , (Left (N.Literal Nothing (NumLit rising)),Integer,True)                                                                  , (Left (N.Literal Nothing (NumLit falling)),Integer,True)@@ -107,7 +107,7 @@                                         in  BlackBoxD "CLaSH.Driver.TestbenchGen.clockGen" (parseFail templ) ctx       pM -> error $ $(curLoc) ++ ("Can't make clock declaration for: " ++ show pM) -    clkDecls   = [ NetDecl clkName (Clock rate)+    clkDecls   = [ NetDecl clkName (Clock clkSym rate)                  , clkGenDecl                  ] @@ -116,17 +116,17 @@ genReset :: PrimMap          -> (Identifier,HWType)          -> Maybe [Declaration]-genReset primMap (rstName,Reset clk) = Just rstDecls+genReset primMap (rstName,Reset clkSym rate) = Just rstDecls   where     resetGenDecl = case HashMap.lookup "CLaSH.Driver.TestbenchGen.resetGen" primMap of       Just (BlackBox _ (Left templ)) -> let ctx = emptyBBContext-                                                    { bbResult = (Left (Identifier rstName Nothing), Reset clk)+                                                    { bbResult = (Left (Identifier rstName Nothing), Reset clkSym rate)                                                     , bbInputs = [(Left (N.Literal Nothing (NumLit 1)),Integer,True)]                                                     }                                         in  BlackBoxD "CLaSH.Driver.TestbenchGen.resetGen" (parseFail templ) ctx       pM -> error $ $(curLoc) ++ ("Can't make reset declaration for: " ++ show pM) -    rstDecls = [ NetDecl rstName (Reset clk)+    rstDecls = [ NetDecl rstName (Reset clkSym rate)                , resetGenDecl                ] @@ -173,11 +173,11 @@                   Nothing -> error $ $(curLoc) ++ "Can't locate component for stimuli gen: " ++ (show $ pack $ name2String signalNm) ++ show (map (componentName) comps)        (cName,hidden',outp) = case sigComp of-                               (Component a b [] (c,_) _) -> (a,b,c)-                               (Component a _ is _ _)     -> error $ $(curLoc) ++ "Stimuli gen " ++ show a ++ " has unexpected inputs: " ++ show is+                               (Component a b [] [(c,_)] _) -> (a,b,c)+                               (Component a _ is _ _)       -> error $ $(curLoc) ++ "Stimuli gen " ++ show a ++ " has unexpected inputs: " ++ show is       hidden'' = nub (hidden ++ hidden')-      clkNms   = mapMaybe (\hd -> case hd of (clkNm,Clock _) -> Just clkNm ; _ -> Nothing) hidden'-      rstNms   = mapMaybe (\hd -> case hd of (clkNm,Reset _) -> Just clkNm ; _ -> Nothing) hidden'+      clkNms   = mapMaybe (\hd -> case hd of (clkNm,Clock _ _) -> Just clkNm ; _ -> Nothing) hidden'+      rstNms   = mapMaybe (\hd -> case hd of (clkNm,Reset _ _) -> Just clkNm ; _ -> Nothing) hidden'       decl     = InstDecl cName "stimuli"                    (map (\i -> (i,Identifier i Nothing))                         (concat [ clkNms, rstNms ]) ++@@ -205,11 +205,11 @@                   Just c -> c                   Nothing -> error $ $(curLoc) ++ "Can't locate component for Verifier: " ++ (show $ pack $ name2String signalNm) ++ show (map (componentName) comps)       (cName,hidden',inp,fin) = case sigComp of-        (Component a b [(c,_)] (d,_) _) -> (a,b,c,d)-        (Component a _ is _ _)     -> error $ $(curLoc) ++ "Verifier " ++ show a ++ " has unexpected inputs: " ++ show is+        (Component a b [(c,_)] [(d,_)] _) -> (a,b,c,d)+        (Component a _ is _ _)            -> error $ $(curLoc) ++ "Verifier " ++ show a ++ " has unexpected inputs: " ++ show is       hidden'' = nub (hidden ++ hidden')-      clkNms   = mapMaybe (\hd -> case hd of (clkNm,Clock _) -> Just clkNm ; _ -> Nothing) hidden'-      rstNms   = mapMaybe (\hd -> case hd of (clkNm,Reset _) -> Just clkNm ; _ -> Nothing) hidden'+      clkNms   = mapMaybe (\hd -> case hd of (clkNm,Clock _ _) -> Just clkNm ; _ -> Nothing) hidden'+      rstNms   = mapMaybe (\hd -> case hd of (clkNm,Reset _ _) -> Just clkNm ; _ -> Nothing) hidden'       decl     = InstDecl cName "verify"                    (map (\i -> (i,Identifier i Nothing))                         (concat [ clkNms, rstNms ]) ++
+ src/CLaSH/Driver/TopWrapper.hs view
@@ -0,0 +1,372 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RecordWildCards   #-}+{-# LANGUAGE TupleSections     #-}+{-# LANGUAGE TemplateHaskell   #-}++{-# OPTIONS_HADDOCK show-extensions #-}++{-|+Copyright  :  (C) 2015, University of Twente+License    :  BSD2 (see the file LICENSE)+Maintainer :  Christiaan Baaij <christiaan.baaij@gmail.com>+-}+module CLaSH.Driver.TopWrapper where++import           Data.Aeson           (FromJSON (..), Value (..), (.:), (.:?),+                                       (.!=))+import           Data.Aeson.Extra     (decodeAndReport)+import qualified Data.ByteString.Lazy as B+import qualified Data.HashMap.Strict  as H+import qualified Data.HashMap.Lazy    as HashMap+import           Data.List            (mapAccumL)+import           Data.Text.Lazy       (Text, append, pack)+import           System.Directory     (doesFileExist)+import           System.IO.Unsafe     (unsafePerformIO)++import CLaSH.Netlist                  (runNetlistMonad)+import CLaSH.Netlist.BlackBox         (prepareBlackBox)+import CLaSH.Netlist.Types            (BlackBoxContext (..), Component (..),+                                       Declaration (..), Expr (..), Identifier,+                                       HWType (..), Modifier (..), NetlistMonad,+                                       emptyBBContext)+import CLaSH.Primitives.Types         (PrimMap, Primitive (..))+import CLaSH.Util++-- | TopEntity specifications, fields are self-explanatory+data TopEntity+  = TopEntity+  { t_name     :: Text+  , t_inputs   :: [Text]        -- optional+  , t_outputs  :: [Text]        -- optional+  , t_extraIn  :: [(Text,Int)]  -- optional+  , t_extraOut :: [(Text,Int)]  -- optional+  , t_clocks   :: [ClockSource] -- optional+  }+  deriving Show++-- | A clock source+data ClockSource+  = ClockSource+  { c_name  :: Text              -- ^ Component name+  , c_paths :: [ClockPath]       -- ^ Number of clock paths+  , c_reset :: Maybe (Text,Text) -- ^ optional: Asynchronous reset input+  , c_lock  :: Text              -- ^ Port name that indicates clock is stable+  , c_sync  :: Bool              -- ^ optional: devices connected this clock+                                 -- source should be pulled out of reset in-sync+  }+  deriving Show++-- | A clock path+data ClockPath+  = ClockPath+  { cp_inp   :: Maybe (Text,Text) -- optional: (Input port, clock pin)+  , cp_outp  :: [(Text,Clock)]    -- [(output port,clock signal)]+  }+  deriving Show++-- | A clock+data Clock+  = Clk { clk_name :: Text, clk_rate :: Int }+  deriving (Eq,Show)++instance FromJSON TopEntity where+  parseJSON (Object v) = case H.toList v of+    [(conKey,Object conVal)] -> case conKey of+      "TopEntity"  -> TopEntity <$> conVal .: "name"+                                <*> (conVal .:? "inputs" .!= [])+                                <*> (conVal .:? "outputs" .!= [])+                                <*> (conVal .:? "extra_in" .!= [])+                                <*> (conVal .:? "extra_out" .!= [])+                                <*> (conVal .:? "clocks" .!= [])+      _ -> error "Expected: TopEntity"+    _ -> error "Expected: TopEntity object"+  parseJSON _ = error "Expected: TopEntity object"++instance FromJSON ClockSource where+  parseJSON (Object v) = case H.toList v of+    [(conKey,Object conVal)] -> case conKey of+      "Source" -> ClockSource <$> conVal .: "name" <*> conVal .: "paths"+                              <*> conVal .:? "reset" <*> conVal .: "lock"+                              <*> (conVal .:? "sync" .!= False)+      _ -> error "Expected: Source"+    _ -> error "Expected: Source object"+  parseJSON _ = error "Expected: Source object"++instance FromJSON ClockPath where+  parseJSON (Object v) = case H.toList v of+    [(conKey,Object conVal)] -> case conKey of+      "Path" -> ClockPath <$> conVal .:? "inp" <*> conVal .: "outp"+      _ -> error "Expected: Path"+    _ -> error "Expected: Path object"+  parseJSON _ = error "Expected: Path object"++instance FromJSON Clock where+  parseJSON (Object v) = case H.toList v of+    [(conKey,Object conVal)] -> case conKey of+      "Clk" -> Clk <$> conVal .: "name" <*> conVal .: "rate"+      _ -> error "Expected: Clk"+    _ -> error "Expected: Clk object"+  parseJSON (String "System") = pure (Clk "system" 1000)+  parseJSON _ = error "Expected: System, or, Clk object"++-- | Create a 'TopEntity' data type from the JSON encoded @.topentity@ file.+generateTopEnt :: String+               -> IO (Maybe TopEntity)+generateTopEnt modName = do+  let topEntityFile = modName ++ ".topentity"+  exists <- doesFileExist topEntityFile+  if exists+    then return . decodeAndReport <=< B.readFile $ topEntityFile+    else return Nothing++-- | Create a wrapper around a component, potentially initiating clock sources+mkTopWrapper :: PrimMap+             -> Maybe TopEntity -- ^ TopEntity specifications+             -> Component       -- ^ Entity to wrap+             -> Component+mkTopWrapper primMap teM topComponent+  = Component+  { componentName = maybe "topEntity" t_name teM+  , inputs        = inputs'' ++ extraIn teM+  , outputs       = outputs'' ++ extraOut teM+  , hiddenPorts   = case maybe [] t_clocks teM of+                      [] -> originalHidden+                      _  -> []+  , declarations  = concat [ mkClocks primMap originalHidden teM+                           , wrappers+                           , instDecl:unwrappers+                           ]+  }+  where+    iNameSupply                = maybe [] t_inputs teM+    originalHidden             = hiddenPorts topComponent++    inputs'                    = map (first (const "input"))+                                     (inputs topComponent)+    (inputs'',(wrappers,idsI)) = (concat *** (first concat . unzip))+                               . unzip+                               . snd+                               $ mapAccumL (\nm (i,c) -> mkInput nm i c)+                                            iNameSupply+                                            (zip inputs' [0..])++    oNameSupply                   = maybe [] t_outputs teM+    outputs'                      = map (first (const "output"))+                                        (outputs topComponent)+    (outputs'',(unwrappers,idsO)) = (concat *** (first concat . unzip))+                                  . unzip+                                  . snd+                                  $ mapAccumL (\nm (o,c) -> mkOutput nm o c)+                                              oNameSupply+                                              (zip outputs' [0..])++    instDecl = InstDecl (componentName topComponent)+                        (append (componentName topComponent) (pack "_inst"))+                        (zipWith (\(p,_) i -> (p,Identifier i Nothing))+                                 (inputs topComponent)+                                 idsI+                         +++                         map (\(p,_) -> (p,Identifier p Nothing))+                             (hiddenPorts topComponent)+                         +++                         zipWith (\(p,_) i -> (p,Identifier i Nothing))+                                 (outputs topComponent)+                                 idsO)++-- | Create extra input ports for the wrapper+extraIn :: Maybe TopEntity -> [(Identifier,HWType)]+extraIn = maybe [] ((map (second BitVector)) . t_extraIn)++-- | Create extra output ports for the wrapper+extraOut :: Maybe TopEntity -> [(Identifier,HWType)]+extraOut = maybe [] ((map (second BitVector)) . t_extraOut)++-- | Generate input port mappings+mkInput :: [Identifier]+        -> (Identifier,HWType)+        -> Int+        -> ( [Identifier]+           , ( [(Identifier,HWType)]+             , ( [Declaration]+               , Identifier+               )+             )+           )+mkInput nms (i,hwty) cnt = case hwty of+  Vector sz hwty' ->+    let (nms',(ports',(decls',ids)))+                 = second ( (concat *** (first concat . unzip))+                          . unzip+                          )+                 $ mapAccumL+                    (\nm c -> mkInput nm (iName,hwty') c)+                    nms [0..(sz-1)]+        netdecl  = NetDecl iName hwty+        netassgn = Assignment iName (mkVectorChain sz hwty' ids)+    in  (nms',(ports',(netdecl:decls' ++ [netassgn],iName)))+  Product _ hwtys ->+    let (nms',(ports',(decls',ids)))+                 = second ( (concat *** (first concat . unzip))+                          . unzip+                          )+                 $ mapAccumL+                    (\nm (inp,c) -> mkInput nm inp c)+                    nms (zip (map (iName,) hwtys) [0..])+        netdecl  = NetDecl iName hwty+        ids'     = map (`Identifier` Nothing) ids+        netassgn = Assignment iName (DataCon hwty (DC (hwty,0)) ids')+    in  (nms',(ports',(netdecl:decls' ++ [netassgn],iName)))+  _ -> case nms of+         []       -> (nms,([(iName,hwty)],([],iName)))+         (n:nms') -> (nms',([(n,hwty)],([],n)))+  where++    iName = append i (pack ("_" ++ show cnt))++-- | Create a Vector chain for a list of 'Identifier's+mkVectorChain :: Int+              -> HWType+              -> [Identifier]+              -> Expr+mkVectorChain _ elTy []      = DataCon (Vector 0 elTy) VecAppend []+mkVectorChain _ elTy [i]     = DataCon (Vector 1 elTy) VecAppend+                                [Identifier i Nothing]+mkVectorChain sz elTy (i:is) = DataCon (Vector sz elTy) VecAppend+                                [ Identifier i Nothing+                                , mkVectorChain (sz-1) elTy is+                                ]++-- | Generate output port mappings+mkOutput :: [Identifier]+         -> (Identifier,HWType)+         -> Int+         -> ( [Identifier]+            , ( [(Identifier,HWType)]+              , ( [Declaration]+                , Identifier+                )+              )+            )+mkOutput nms (i,hwty) cnt = case hwty of+  Vector sz hwty' ->+    let (nms',(ports',(decls',ids)))+                = second ( (concat *** (first concat . unzip))+                         . unzip+                         )+                $ mapAccumL+                   (\nm c -> mkOutput nm (iName,hwty') c)+                   nms [0..(sz-1)]+        netdecl = NetDecl iName hwty+        assigns = zipWith+                    (\id_ n -> Assignment id_+                                 (Identifier iName (Just (Indexed (hwty,1,n)))))+                    ids+                    [0..]+    in  (nms',(ports',(netdecl:assigns ++ decls',iName)))+  Product _ hwtys ->+    let (nms',(ports',(decls',ids)))+                = second ( (concat *** (first concat . unzip))+                         . unzip+                         )+                $ mapAccumL+                   (\nm (inp,c) -> mkOutput nm inp c)+                   nms (zip (map (iName,) hwtys) [0..])+        netdecl = NetDecl iName hwty+        assigns = zipWith+                    (\id_ n -> Assignment id_+                                (Identifier iName (Just (Indexed (hwty,0,n)))))+                    ids+                    [0..]+    in  (nms',(ports',(netdecl:assigns ++ decls',iName)))+  _ -> case nms of+         []       -> (nms,([(iName,hwty)],([],iName)))+         (n:nms') -> (nms',([(n,hwty)],([],n)))+  where+    iName = append i (pack ("_" ++ show cnt))++-- | Create clock generators+mkClocks :: PrimMap -> [(Identifier,HWType)] -> Maybe TopEntity -> [Declaration]+mkClocks primMap hidden teM = concat+    [ hiddenSigDecs+    , clockGens+    , resets+    ]+  where+    hiddenSigDecs        = map (uncurry NetDecl) hidden+    (clockGens,clkLocks) = maybe ([],[])+                                 (first concat . unzip . map mkClock . t_clocks)+                                 teM+    resets               = mkResets primMap hidden clkLocks++-- | Create a single clock generator+mkClock :: ClockSource -> ([Declaration],(Identifier,[Clock],Bool))+mkClock (ClockSource {..}) = ([lockedDecl,instDecl],(lockedName,clks,c_sync))+  where+    lockedName   = append c_name "_locked"+    lockedDecl   = NetDecl lockedName (Reset lockedName 0)+    (ports,clks) = (concat *** concat) . unzip $ map clockPorts c_paths+    instDecl     = InstDecl c_name (append c_name "_inst")+                 $ concat [ ports+                          , maybe [] ((:[]) . second (`Identifier` Nothing))+                                  c_reset+                          , [(c_lock,Identifier lockedName Nothing)]+                          ]++-- | Create a single clock path+clockPorts :: ClockPath -> ([(Identifier,Expr)],[Clock])+clockPorts (ClockPath {..}) = (inp ++ outp,clks)+  where+    inp  = maybe [] ((:[]) . second (`Identifier` Nothing)) cp_inp+    outp = map (second ((`Identifier` Nothing) . clkToId)) cp_outp+    clks = map snd cp_outp++    clkToId (Clk nm r) = append nm (pack (show r))++-- | Generate resets+mkResets :: PrimMap+         -> [(Identifier,HWType)]+         -> [(Identifier,[Clock],Bool)]+         -> [Declaration]+mkResets primMap hidden = unsafeRunNetlist . fmap concat . mapM assingReset+  where+    assingReset (lock,clks,doSync) = concat <$> mapM connectReset matched+      where+        matched = filter match hidden+        match (_,(Reset nm r)) = elem (Clk nm r) clks+        match _                = False++        connectReset (rst,(Reset nm r)) = if doSync+            then return [Assignment rst (Identifier lock Nothing)]+            else genSyncReset primMap lock rst (Clk nm r)+        connectReset _ = return []++-- | Generate a reset synchroniser that synchronously de-asserts an+-- asynchronous reset signal+genSyncReset :: PrimMap+             -> Identifier+             -> Identifier+             -> Clock+             -> NetlistMonad [Declaration]+genSyncReset primMap lock rst (Clk nm r) = do+  let resetType = Reset rst 0+      ctx = emptyBBContext+              { bbResult = (Right ((Identifier rst Nothing),(nm,r)), resetType)+              , bbInputs = [(Left (Identifier lock Nothing),resetType,False)]+              }+      bbName = "CLaSH.TopWrapper.syncReset"+  resetGenDecl <- case HashMap.lookup bbName primMap of+        Just (BlackBox _ (Left templ)) -> do+          templ' <- prepareBlackBox bbName templ ctx+          return (BlackBoxD bbName templ' ctx)+        pM -> error $ $(curLoc) ++ ("Can't make reset sync for: " ++ show pM)++  return [resetGenDecl]++-- | The 'NetListMonad' is an transformer stack with 'IO' at the bottom.+-- So we must use 'unsafePerformIO'.+unsafeRunNetlist :: NetlistMonad a+                 -> a+unsafeRunNetlist = unsafePerformIO+                 . fmap fst+                 . runNetlistMonad Nothing HashMap.empty HashMap.empty+                     HashMap.empty (\_ _ -> Nothing)
src/CLaSH/Netlist.hs view
@@ -137,7 +137,7 @@    let compInps       = zip (map (mkBasicId . Text.pack . name2String . varName) arguments) argTypes       compOutp       = (mkBasicId . Text.pack $ name2String result, resType)-      component      = Component componentName' (nub clks) compInps compOutp (netDecls ++ decls)+      component      = Component componentName' (nub clks) compInps [compOutp] (netDecls ++ decls)   return component  -- | Generate a list of Declarations for a let-binder@@ -234,7 +234,7 @@   normalized <- Lens.use bindings   case HashMap.lookup fun normalized of     Just _ -> do-      (Component compName hidden compInps compOutp _) <- preserveVarEnv $ genComponent fun Nothing+      (Component compName hidden compInps [compOutp] _) <- preserveVarEnv $ genComponent fun Nothing       if length args == length compInps         then do tcm <- Lens.use tcCache                 argTys              <- mapM (termType tcm) args
src/CLaSH/Netlist/BlackBox.hs view
@@ -228,7 +228,7 @@               normalized <- Lens.use bindings               case HashMap.lookup fun normalized of                 Just _ -> do-                  (Component compName hidden compInps compOutp _) <- preserveVarEnv $ genComponent fun Nothing+                  (Component compName hidden compInps [compOutp] _) <- preserveVarEnv $ genComponent fun Nothing                   let hiddenAssigns = map (\(i,_) -> (i,Identifier i Nothing)) hidden                       inpAssigns    = zip (map fst compInps) [ Identifier (pack ("~ARG[" ++ show x ++ "]")) Nothing | x <- [(0::Int)..] ]                       outpAssign    = (fst compOutp,Identifier (pack "~RESULT") Nothing)
src/CLaSH/Netlist/BlackBox/Util.hs view
@@ -88,17 +88,20 @@     setClocks' (SigD e m)     = SigD <$> (head <$> setClocks bc [e]) <*> pure m      setClocks' (Clk Nothing)  = let (clk,rate) = clkSyncId $ fst $ bbResult bc-                                in  tell [(clk,Clock rate)] >> return (C clk)+                                    clkName    = Text.append clk (Text.pack (show rate))+                                in  tell [(clkName,Clock clk rate)] >> return (C clkName)     setClocks' (Clk (Just n)) = let (e,_,_)    = bbInputs bc !! n                                     (clk,rate) = clkSyncId e-                                in  tell [(clk,Clock rate)] >> return (C clk)+                                    clkName    = Text.append clk (Text.pack (show rate))+                                in  tell [(clkName,Clock clk rate)] >> return (C clkName) -    setClocks' (Rst Nothing)  = let (rst,rate) = (first (`Text.append` "_rst")) . clkSyncId $ fst $ bbResult bc-                                in  tell [(rst,Reset rate)] >> return (C rst)+    setClocks' (Rst Nothing)  = let (rst,rate) = clkSyncId $ fst $ bbResult bc+                                    rstName    = Text.concat [rst,Text.pack (show rate),"_rstn"]+                                in  tell [(rstName,Reset rst rate)] >> return (C rstName)     setClocks' (Rst (Just n)) = let (e,_,_)    = bbInputs bc !! n                                     (rst,rate) = clkSyncId e-                                    rst'       = Text.append rst "_rst"-                                in  tell [(rst',Reset rate)] >> return (C rst')+                                    rstName    = Text.concat [rst,Text.pack (show rate),"_rstn"]+                                in  tell [(rstName,Reset rst rate)] >> return (C rstName)      setClocks' e = return e 
src/CLaSH/Netlist/Types.hs view
@@ -57,7 +57,7 @@   { componentName :: Identifier -- ^ Name of the component   , hiddenPorts   :: [(Identifier,HWType)] -- ^ Ports that have no correspondence the original function definition   , inputs        :: [(Identifier,HWType)] -- ^ Input ports-  , output        :: (Identifier,HWType) -- ^ Output port+  , outputs       :: [(Identifier,HWType)] -- ^ Output ports   , declarations  :: [Declaration] -- ^ Internal declarations   }   deriving Show@@ -83,26 +83,12 @@   | Sum      Identifier [Identifier] -- ^ Sum type: Name and Constructor names   | Product  Identifier [HWType] -- ^ Product type: Name and field types   | SP       Identifier [(Identifier,[HWType])] -- ^ Sum-of-Product type: Name and Constructor names + field types-  | Clock    Int -- ^ Clock type with specified period-  | Reset    Int -- ^ Reset type corresponding to clock with a specified period+  | Clock    Identifier Int -- ^ Clock type with specified name and period+  | Reset    Identifier Int -- ^ Reset type corresponding to clock with a specified name and period   deriving (Eq,Show,Generic)  instance Hashable HWType-instance NFData HWType where-  rnf hwty = case hwty of-    Void -> ()-    Bool -> ()-    Integer -> ()-    BitVector s -> rnf s-    Index u -> rnf u-    Signed s -> rnf s-    Unsigned s -> rnf s-    Vector s el -> rnf s `seq` rnf el-    Sum i ids -> rnf i `seq` rnf ids-    Product i ids -> rnf i `seq` rnf ids-    SP i ids -> rnf i `seq` rnf ids-    Clock i -> rnf i-    Reset i -> rnf i+instance NFData HWType  -- | Internals of a Component data Declaration
src/CLaSH/Netlist/Util.hs view
@@ -82,10 +82,10 @@   = case name2String tyCon of       "CLaSH.Sized.Vector.Vec"        -> synchronizedClk tcm (args!!1)       "CLaSH.Signal.Internal.SClock" -> case splitTyConAppM (head args) of-                                          Just (_,[LitTy (SymTy s),LitTy (NumTy i)]) -> Just (pack (s ++ show i),i)+                                          Just (_,[LitTy (SymTy s),LitTy (NumTy i)]) -> Just (pack s,i)                                           _ -> error $ $(curLoc) ++ "Clock period not a simple literal: " ++ showDoc ty       "CLaSH.Signal.Internal.Signal'" -> case splitTyConAppM (head args) of-                                           Just (_,[LitTy (SymTy s),LitTy (NumTy i)]) -> Just (pack (s ++ show i),i)+                                           Just (_,[LitTy (SymTy s),LitTy (NumTy i)]) -> Just (pack s,i)                                            _ -> error $ $(curLoc) ++ "Clock period not a simple literal: " ++ showDoc ty       _                               -> case tyConDataCons (tcm HashMap.! tyCon) of                                            [dc] -> let argTys   = dcArgTys dc@@ -165,8 +165,8 @@          -> Int typeSize Void = 1 typeSize Bool = 1-typeSize (Clock _) = 1-typeSize (Reset _) = 1+typeSize (Clock _ _) = 1+typeSize (Reset _ _) = 1 typeSize Integer = 32 typeSize (BitVector i) = i typeSize (Index u) = clog2 (max 2 u)
src/CLaSH/Primitives/Util.hs view
@@ -1,9 +1,7 @@ -- | Utility functions to generate Primitives module CLaSH.Primitives.Util where -import           Data.Aeson             (FromJSON, Result (..), fromJSON, json)-import qualified Data.Attoparsec.Lazy   as L-import           Data.ByteString.Lazy   (ByteString)+import           Data.Aeson.Extra       (decodeAndReport) import qualified Data.ByteString.Lazy   as LZ import qualified Data.HashMap.Lazy      as HashMap import           Data.List              (isSuffixOf)@@ -36,15 +34,3 @@   let primMap = HashMap.fromList $ zip (map name primitives) primitives    return primMap---- | Parse a ByteString according to the given JSON template. Prints failures--- on @stdout@, and returns 'Nothing' if parsing fails.-decodeAndReport :: (FromJSON a)-                => ByteString -- ^ Bytestring to parse-                -> Maybe a-decodeAndReport s =-  case L.parse json s of-    L.Done _ v -> case fromJSON v of-                    Success a -> Just a-                    Error msg -> traceIf True msg Nothing-    L.Fail _ _ msg -> traceIf True msg Nothing
+ src/Data/Aeson/Extra.hs view
@@ -0,0 +1,18 @@+module Data.Aeson.Extra where++import Data.Aeson           (FromJSON, Result (..), fromJSON, json)+import Data.Attoparsec.Lazy (Result (..), parse)+import Data.ByteString.Lazy (ByteString)+import CLaSH.Util           (traceIf)++-- | Parse a ByteString according to the given JSON template. Prints failures+-- on @stdout@, and returns 'Nothing' if parsing fails.+decodeAndReport :: (FromJSON a)+                => ByteString -- ^ Bytestring to parse+                -> Maybe a+decodeAndReport s =+  case parse json s of+    Done _ v -> case fromJSON v of+                    Success a -> Just a+                    Error msg -> traceIf True msg Nothing+    Fail _ _ msg -> traceIf True msg Nothing