module Lava.Internal ( module Lava.Model , module Lava.Patterns , module Lava.Loop , module Lava.Port , module Lava.Interpret , input , inputList , cell , label , toLava2000 , simulateSeq , simulate , verify , depth , fanout , size ) where import Control.Monad import qualified Data.Foldable as Fold import qualified Data.Map as Map import Data.Hardware.Internal import Lava.Model import Lava.Patterns import Lava.Loop import Lava.Port import Lava.Interpret import qualified Lava2000 as L import qualified Lava2000.Ref as L input :: forall lib m p . (MonadLava lib m, PortFixed p Signal) => Name -> m p input nm = liftM fromListFP $ replicateM (lengthFP (T::TypeOf p)) (inputSig nm) -- Declare a primary input inputList :: (MonadLava lib m, PortFixed p Signal) => Int -> Name -> m [p] inputList n nm = replicateM n $ input nm cell :: forall m lib pi po . ( MonadLava lib m , PortFixed pi Signal , PortFixed po Signal , CellLibrary lib ) => lib -> pi -> m po cell cid pi = liftM fromListFP $ cellList cid ins where ins = Fold.toList $ port pi -- Declare a cell label :: (MonadLava lib m, PortStruct p Signal t) => Tag -> p -> m p label tag = mapPortM (labelSig tag) -- Declare a label; only side-effect important. toLava2000 :: ( CellLibrary lib , PortStruct pli (L.Signal Bool) ti , PortStruct psi Signal ti , PortStruct pso Signal to , PortStruct plo (L.Signal Bool) to ) => (psi -> Lava lib pso) -> (pli -> plo) toLava2000 circ = fst . interpretFunc lava2000Interp circ simulateSeq :: ( CellLibrary lib , PortStruct pni Int ti , PortStruct psi Signal ti , PortStruct pso Signal to , PortStruct pno Int to ) => (psi -> Lava lib pso) -> ([pni] -> [pno]) simulateSeq circ = map (unport . fmap sigToInt) . L.simulateSeq circP . map (fmap intToSig . port) where circP = fst . interpretFuncP lava2000Interp (liftM port . circ . unport) intToSig 0 = L.low intToSig 1 = L.high intToSig _ = error "Only values 0 and 1 allowed" sigToInt (L.Signal (L.Symbol r)) = case L.deref r of L.Bool False -> 0 L.Bool True -> 1 simulate :: ( CellLibrary lib , PortStruct pni Int ti , PortStruct psi Signal ti , PortStruct pso Signal to , PortStruct pno Int to ) => (psi -> Lava lib pso) -> (pni -> pno) simulate circ = head . simulateSeq circ . return verify :: forall lib ps . (CellLibrary lib, PortFixed ps Signal) => (ps -> Lava lib Signal) -> IO () verify circ = L.smv (L.forAll (L.list n) circP) >> return () where n = lengthFP (T::TypeOf ps) circP = toLava2000 (circ . fromListFP) depth :: (CellLibrary lib, PortStruct ps Signal t, PortStruct pd Int t) => Lava lib ps -> (pd, InterpDesignDB lib Int) depth circ | hasLoopDB True db = error "depth: Combinational feedback loop" | otherwise = pd_idb where pd_idb@(_,(db,_)) = interpret depthInterp circ fanout :: CellLibrary lib => Lava lib a -> InterpDesignDB lib Int fanout circ = (db, fmap length $ fanoutDB db) where (_,db) = runLava circ size :: CellLibrary lib => Lava lib p -> Int size = length . Map.toList . cellDB . snd . runLava