content: {-# LANGUAGE CPP #-}
  {-# LANGUAGE DeriveDataTypeable #-}
  module Wires(ClockId, ClockDomain(..), ResetId,
               nextClockId, nextClockDomain, nextResetId,
               initClockId, initClockDomain, initResetId,
               noClockId, noClockDomain, noResetId,
               noDefaultClockId, noDefaultResetId,
               WireProps(..), emptyWireProps,
               writeClockDomain, readClockDomain,
               writeResetId, readResetId
               ) where
  
  #if defined(__GLASGOW_HASKELL__) && (__GLASGOW_HASKELL__ >= 804)
  import Prelude hiding ((<>))
  #endif
  
  import Eval
  import PPrint
  import qualified Data.Generics as Generic
  -- Primitives for describing special wires (e.g. clock and reset)
  
  data ClockId = ClockId !Int
    deriving (Show, Eq, Ord, Generic.Data, Generic.Typeable)
  
  instance Hyper ClockId where
    hyper (ClockId a) y = hyper a y
  
  data ClockDomain = ClockDomain !Int
    deriving (Show, Eq, Ord, Generic.Data, Generic.Typeable)
  
  instance PPrint ClockDomain where
    pPrint d p (ClockDomain i) = pPrint d p i
  
  instance Hyper ClockDomain where
    hyper (ClockDomain a) y = hyper a y
  
  data ResetId = ResetId !Int
    deriving (Show, Eq, Ord, Generic.Data, Generic.Typeable)
  
  instance Hyper ResetId where
    hyper (ResetId a) y = hyper a y
  
  instance PPrint ResetId where
    pPrint d p (ResetId i) = pPrint d p i
  
  {-# INLINE nextClockId #-}
  nextClockId :: ClockId -> ClockId
  nextClockId (ClockId i) = (ClockId (i + 1))
  
  {-# INLINE nextResetId #-}
  nextResetId :: ResetId -> ResetId
  nextResetId (ResetId i) = (ResetId (i + 1))
  
  {-# INLINE nextClockDomain #-}
  nextClockDomain :: ClockDomain -> ClockDomain
  nextClockDomain (ClockDomain d) = (ClockDomain (d + 1))
  
  {-# INLINE initClockId #-}
  initClockId :: ClockId
  initClockId = (ClockId 0)
  
  {-# INLINE initResetId #-}
  initResetId :: ResetId
  initResetId = (ResetId 0)
  
  {-# INLINE initClockDomain #-}
  initClockDomain :: ClockDomain
  initClockDomain = (ClockDomain 0)
  
  noClockId :: ClockId
  noClockId = (ClockId (-1))
  
  noDefaultClockId :: ClockId
  noDefaultClockId = ClockId (-2)
  
  noClockDomain :: ClockDomain
  noClockDomain = (ClockDomain (-1))
  
  noResetId :: ResetId
  noResetId = (ResetId (-1))
  
  noDefaultResetId :: ResetId
  noDefaultResetId = ResetId (-2)
  
  data WireProps = WireProps { -- clock domain of object, Nothing if object crosses clock domains
                               wpClockDomain :: Maybe ClockDomain,
                               -- identifiers of reset signals connected to object
                               -- more than one implies "unsafe reset crossing"
                               wpResets :: [ResetId]
                             }
     deriving(Eq, Ord, Show, Generic.Data, Generic.Typeable)
  
  emptyWireProps :: WireProps
  emptyWireProps = WireProps { wpClockDomain = Nothing, wpResets = [] }
  
  instance Hyper WireProps where
    hyper (WireProps a b) y = hyper2 a b y
  
  instance PPrint WireProps where
    pPrint d p wp = text ("clock domain = ") <> (pPrint d 0 (wpClockDomain wp)) <> text (",") <+>
                    text ("resets = ") <> (pPrint d 0 (wpResets wp))
  
  -----
  
  -- Functions for writing and reading ClockDomain to a file
  
  writeClockDomain :: ClockDomain -> Int
  writeClockDomain (ClockDomain i) = i
  
  readClockDomain :: Int -> ClockDomain
  readClockDomain i = ClockDomain i
  
  -----
  
  -- Functions for writing and reading ResetId to a file
  
  writeResetId :: ResetId -> Int
  writeResetId (ResetId i) = i
  
  readResetId :: Int -> ResetId
  readResetId i = ResetId i
  
  -----
  