{-|
Copyright  :  (C) 2018, Google Inc
                  2019, Myrtle Software Ltd
                  2023,      QBayLogic B.V.
License    :  BSD2 (see the file LICENSE)
Maintainer :  QBayLogic B.V. <devops@qbaylogic.com>

Generic clock related utilities.
-}

{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}

{-# OPTIONS_GHC "-Wno-orphans" #-}

module Clash.Clocks
  ( Clocks(..)
  , ClocksSync(..)
  , ClocksSyncCxt
  , NumOutClocksSync
  ) where

import Clash.Clocks.Internal
  (Clocks(..), ClocksSync(..), deriveClocksInstances, deriveClocksSyncInstances)
import Clash.Signal.Internal (Domain, KnownDomain)

Clock domIn
-> Reset domIn
-> (Clock c1, Clock c2, Clock c3, Signal pllLock Bool)
Clock domIn
-> Reset domIn -> (Clock c1, Clock c2, Signal pllLock Bool)
Clock domIn -> Reset domIn -> (Clock c1, Signal pllLock Bool)
(forall (domIn :: Domain).
 (KnownDomain domIn, ClocksCxt (Clock c1, Signal pllLock Bool)) =>
 Clock domIn -> Reset domIn -> (Clock c1, Signal pllLock Bool))
-> Clocks (Clock c1, Signal pllLock Bool)
(forall (domIn :: Domain).
 (KnownDomain domIn,
  ClocksCxt (Clock c1, Clock c2, Signal pllLock Bool)) =>
 Clock domIn
 -> Reset domIn -> (Clock c1, Clock c2, Signal pllLock Bool))
-> Clocks (Clock c1, Clock c2, Signal pllLock Bool)
(forall (domIn :: Domain).
 (KnownDomain domIn,
  ClocksCxt (Clock c1, Clock c2, Clock c3, Signal pllLock Bool)) =>
 Clock domIn
 -> Reset domIn
 -> (Clock c1, Clock c2, Clock c3, Signal pllLock Bool))
-> Clocks (Clock c1, Clock c2, Clock c3, Signal pllLock Bool)
forall t.
(forall (domIn :: Domain).
 (KnownDomain domIn, ClocksCxt t) =>
 Clock domIn -> Reset domIn -> t)
-> Clocks t
forall (domIn :: Domain).
(KnownDomain domIn, ClocksCxt (Clock c1, Signal pllLock Bool)) =>
Clock domIn -> Reset domIn -> (Clock c1, Signal pllLock Bool)
forall (domIn :: Domain).
(KnownDomain domIn,
 ClocksCxt (Clock c1, Clock c2, Signal pllLock Bool)) =>
Clock domIn
-> Reset domIn -> (Clock c1, Clock c2, Signal pllLock Bool)
forall (domIn :: Domain).
(KnownDomain domIn,
 ClocksCxt (Clock c1, Clock c2, Clock c3, Signal pllLock Bool)) =>
Clock domIn
-> Reset domIn
-> (Clock c1, Clock c2, Clock c3, Signal pllLock Bool)
forall (c1 :: Domain) (pllLock :: Domain) (domIn :: Domain).
(KnownDomain domIn, ClocksCxt (Clock c1, Signal pllLock Bool)) =>
Clock domIn -> Reset domIn -> (Clock c1, Signal pllLock Bool)
forall (c1 :: Domain) (c2 :: Domain) (pllLock :: Domain)
       (domIn :: Domain).
(KnownDomain domIn,
 ClocksCxt (Clock c1, Clock c2, Signal pllLock Bool)) =>
Clock domIn
-> Reset domIn -> (Clock c1, Clock c2, Signal pllLock Bool)
forall (c1 :: Domain) (c2 :: Domain) (c3 :: Domain)
       (pllLock :: Domain) (domIn :: Domain).
(KnownDomain domIn,
 ClocksCxt (Clock c1, Clock c2, Clock c3, Signal pllLock Bool)) =>
Clock domIn
-> Reset domIn
-> (Clock c1, Clock c2, Clock c3, Signal pllLock Bool)
clocks :: Clock domIn -> Reset domIn -> (Clock c1, Signal pllLock Bool)
$cclocks :: forall (c1 :: Domain) (pllLock :: Domain) (domIn :: Domain).
(KnownDomain domIn, ClocksCxt (Clock c1, Signal pllLock Bool)) =>
Clock domIn -> Reset domIn -> (Clock c1, Signal pllLock Bool)
clocks :: Clock domIn
-> Reset domIn -> (Clock c1, Clock c2, Signal pllLock Bool)
$cclocks :: forall (c1 :: Domain) (c2 :: Domain) (pllLock :: Domain)
       (domIn :: Domain).
(KnownDomain domIn,
 ClocksCxt (Clock c1, Clock c2, Signal pllLock Bool)) =>
Clock domIn
-> Reset domIn -> (Clock c1, Clock c2, Signal pllLock Bool)
clocks :: Clock domIn
-> Reset domIn
-> (Clock c1, Clock c2, Clock c3, Signal pllLock Bool)
$cclocks :: forall (c1 :: Domain) (c2 :: Domain) (c3 :: Domain)
       (pllLock :: Domain) (domIn :: Domain).
(KnownDomain domIn,
 ClocksCxt (Clock c1, Clock c2, Clock c3, Signal pllLock Bool)) =>
Clock domIn
-> Reset domIn
-> (Clock c1, Clock c2, Clock c3, Signal pllLock Bool)
deriveClocksInstances

type ClocksSyncCxt t (domIn :: Domain) =
  ( KnownDomain domIn
  , ClocksSync t
  , ClocksResetSynchronizerCxt t
  , Clocks (ClocksSyncClocksInst t domIn)
  , ClocksCxt (ClocksSyncClocksInst t domIn)
  )

type NumOutClocksSync t (domIn :: Domain) =
  NumOutClocks (ClocksSyncClocksInst t domIn)

ClocksSyncClocksInst (Clock c1, Reset c1) domIn
-> Clock domIn -> (Clock c1, Reset c1)
ClocksSyncClocksInst (Clock c1, Reset c1, Clock c2, Reset c2) domIn
-> Clock domIn -> (Clock c1, Reset c1, Clock c2, Reset c2)
ClocksSyncClocksInst
  (Clock c1, Reset c1, Clock c2, Reset c2, Clock c3, Reset c3) domIn
-> Clock domIn
-> (Clock c1, Reset c1, Clock c2, Reset c2, Clock c3, Reset c3)
(forall (domIn :: Domain).
 (KnownDomain domIn,
  ClocksResetSynchronizerCxt (Clock c1, Reset c1)) =>
 ClocksSyncClocksInst (Clock c1, Reset c1) domIn
 -> Clock domIn -> (Clock c1, Reset c1))
-> ClocksSync (Clock c1, Reset c1)
(forall (domIn :: Domain).
 (KnownDomain domIn,
  ClocksResetSynchronizerCxt
    (Clock c1, Reset c1, Clock c2, Reset c2)) =>
 ClocksSyncClocksInst (Clock c1, Reset c1, Clock c2, Reset c2) domIn
 -> Clock domIn -> (Clock c1, Reset c1, Clock c2, Reset c2))
-> ClocksSync (Clock c1, Reset c1, Clock c2, Reset c2)
(forall (domIn :: Domain).
 (KnownDomain domIn,
  ClocksResetSynchronizerCxt
    (Clock c1, Reset c1, Clock c2, Reset c2, Clock c3, Reset c3)) =>
 ClocksSyncClocksInst
   (Clock c1, Reset c1, Clock c2, Reset c2, Clock c3, Reset c3) domIn
 -> Clock domIn
 -> (Clock c1, Reset c1, Clock c2, Reset c2, Clock c3, Reset c3))
-> ClocksSync
     (Clock c1, Reset c1, Clock c2, Reset c2, Clock c3, Reset c3)
forall t.
(forall (domIn :: Domain).
 (KnownDomain domIn, ClocksResetSynchronizerCxt t) =>
 ClocksSyncClocksInst t domIn -> Clock domIn -> t)
-> ClocksSync t
forall (domIn :: Domain).
(KnownDomain domIn,
 ClocksResetSynchronizerCxt (Clock c1, Reset c1)) =>
ClocksSyncClocksInst (Clock c1, Reset c1) domIn
-> Clock domIn -> (Clock c1, Reset c1)
forall (domIn :: Domain).
(KnownDomain domIn,
 ClocksResetSynchronizerCxt
   (Clock c1, Reset c1, Clock c2, Reset c2)) =>
ClocksSyncClocksInst (Clock c1, Reset c1, Clock c2, Reset c2) domIn
-> Clock domIn -> (Clock c1, Reset c1, Clock c2, Reset c2)
forall (domIn :: Domain).
(KnownDomain domIn,
 ClocksResetSynchronizerCxt
   (Clock c1, Reset c1, Clock c2, Reset c2, Clock c3, Reset c3)) =>
ClocksSyncClocksInst
  (Clock c1, Reset c1, Clock c2, Reset c2, Clock c3, Reset c3) domIn
-> Clock domIn
-> (Clock c1, Reset c1, Clock c2, Reset c2, Clock c3, Reset c3)
forall (c1 :: Domain) (domIn :: Domain).
(KnownDomain domIn,
 ClocksResetSynchronizerCxt (Clock c1, Reset c1)) =>
ClocksSyncClocksInst (Clock c1, Reset c1) domIn
-> Clock domIn -> (Clock c1, Reset c1)
forall (c1 :: Domain) (c2 :: Domain) (domIn :: Domain).
(KnownDomain domIn,
 ClocksResetSynchronizerCxt
   (Clock c1, Reset c1, Clock c2, Reset c2)) =>
ClocksSyncClocksInst (Clock c1, Reset c1, Clock c2, Reset c2) domIn
-> Clock domIn -> (Clock c1, Reset c1, Clock c2, Reset c2)
forall (c1 :: Domain) (c2 :: Domain) (c3 :: Domain)
       (domIn :: Domain).
(KnownDomain domIn,
 ClocksResetSynchronizerCxt
   (Clock c1, Reset c1, Clock c2, Reset c2, Clock c3, Reset c3)) =>
ClocksSyncClocksInst
  (Clock c1, Reset c1, Clock c2, Reset c2, Clock c3, Reset c3) domIn
-> Clock domIn
-> (Clock c1, Reset c1, Clock c2, Reset c2, Clock c3, Reset c3)
clocksResetSynchronizer :: ClocksSyncClocksInst (Clock c1, Reset c1) domIn
-> Clock domIn -> (Clock c1, Reset c1)
$cclocksResetSynchronizer :: forall (c1 :: Domain) (domIn :: Domain).
(KnownDomain domIn,
 ClocksResetSynchronizerCxt (Clock c1, Reset c1)) =>
ClocksSyncClocksInst (Clock c1, Reset c1) domIn
-> Clock domIn -> (Clock c1, Reset c1)
clocksResetSynchronizer :: ClocksSyncClocksInst (Clock c1, Reset c1, Clock c2, Reset c2) domIn
-> Clock domIn -> (Clock c1, Reset c1, Clock c2, Reset c2)
$cclocksResetSynchronizer :: forall (c1 :: Domain) (c2 :: Domain) (domIn :: Domain).
(KnownDomain domIn,
 ClocksResetSynchronizerCxt
   (Clock c1, Reset c1, Clock c2, Reset c2)) =>
ClocksSyncClocksInst (Clock c1, Reset c1, Clock c2, Reset c2) domIn
-> Clock domIn -> (Clock c1, Reset c1, Clock c2, Reset c2)
clocksResetSynchronizer :: ClocksSyncClocksInst
  (Clock c1, Reset c1, Clock c2, Reset c2, Clock c3, Reset c3) domIn
-> Clock domIn
-> (Clock c1, Reset c1, Clock c2, Reset c2, Clock c3, Reset c3)
$cclocksResetSynchronizer :: forall (c1 :: Domain) (c2 :: Domain) (c3 :: Domain)
       (domIn :: Domain).
(KnownDomain domIn,
 ClocksResetSynchronizerCxt
   (Clock c1, Reset c1, Clock c2, Reset c2, Clock c3, Reset c3)) =>
ClocksSyncClocksInst
  (Clock c1, Reset c1, Clock c2, Reset c2, Clock c3, Reset c3) domIn
-> Clock domIn
-> (Clock c1, Reset c1, Clock c2, Reset c2, Clock c3, Reset c3)
deriveClocksSyncInstances