{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE TypeFamilies #-}
{-# OPTIONS_GHC -Wno-deprecations #-}
module Clash.Backend.Verilog.Time where
import Clash.Class.HasDomain.HasSingleDomain
(TryDomain, TryDomainResult(NotFound))
import Control.DeepSeq (NFData)
import Data.Char (toLower, isDigit)
import Data.Hashable (Hashable)
import Data.List (find)
import Data.Word (Word64)
import GHC.Generics (Generic)
import Text.Read (readMaybe)
data Unit = Fs | Ps | Ns | Us | Ms | S
deriving (Int -> Unit -> ShowS
[Unit] -> ShowS
Unit -> String
(Int -> Unit -> ShowS)
-> (Unit -> String) -> ([Unit] -> ShowS) -> Show Unit
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Unit] -> ShowS
$cshowList :: [Unit] -> ShowS
show :: Unit -> String
$cshow :: Unit -> String
showsPrec :: Int -> Unit -> ShowS
$cshowsPrec :: Int -> Unit -> ShowS
Show, Int -> Unit
Unit -> Int
Unit -> [Unit]
Unit -> Unit
Unit -> Unit -> [Unit]
Unit -> Unit -> Unit -> [Unit]
(Unit -> Unit)
-> (Unit -> Unit)
-> (Int -> Unit)
-> (Unit -> Int)
-> (Unit -> [Unit])
-> (Unit -> Unit -> [Unit])
-> (Unit -> Unit -> [Unit])
-> (Unit -> Unit -> Unit -> [Unit])
-> Enum Unit
forall a.
(a -> a)
-> (a -> a)
-> (Int -> a)
-> (a -> Int)
-> (a -> [a])
-> (a -> a -> [a])
-> (a -> a -> [a])
-> (a -> a -> a -> [a])
-> Enum a
enumFromThenTo :: Unit -> Unit -> Unit -> [Unit]
$cenumFromThenTo :: Unit -> Unit -> Unit -> [Unit]
enumFromTo :: Unit -> Unit -> [Unit]
$cenumFromTo :: Unit -> Unit -> [Unit]
enumFromThen :: Unit -> Unit -> [Unit]
$cenumFromThen :: Unit -> Unit -> [Unit]
enumFrom :: Unit -> [Unit]
$cenumFrom :: Unit -> [Unit]
fromEnum :: Unit -> Int
$cfromEnum :: Unit -> Int
toEnum :: Int -> Unit
$ctoEnum :: Int -> Unit
pred :: Unit -> Unit
$cpred :: Unit -> Unit
succ :: Unit -> Unit
$csucc :: Unit -> Unit
Enum, Unit
Unit -> Unit -> Bounded Unit
forall a. a -> a -> Bounded a
maxBound :: Unit
$cmaxBound :: Unit
minBound :: Unit
$cminBound :: Unit
Bounded, Unit -> Unit -> Bool
(Unit -> Unit -> Bool) -> (Unit -> Unit -> Bool) -> Eq Unit
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Unit -> Unit -> Bool
$c/= :: Unit -> Unit -> Bool
== :: Unit -> Unit -> Bool
$c== :: Unit -> Unit -> Bool
Eq, Eq Unit
Eq Unit
-> (Unit -> Unit -> Ordering)
-> (Unit -> Unit -> Bool)
-> (Unit -> Unit -> Bool)
-> (Unit -> Unit -> Bool)
-> (Unit -> Unit -> Bool)
-> (Unit -> Unit -> Unit)
-> (Unit -> Unit -> Unit)
-> Ord Unit
Unit -> Unit -> Bool
Unit -> Unit -> Ordering
Unit -> Unit -> Unit
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
min :: Unit -> Unit -> Unit
$cmin :: Unit -> Unit -> Unit
max :: Unit -> Unit -> Unit
$cmax :: Unit -> Unit -> Unit
>= :: Unit -> Unit -> Bool
$c>= :: Unit -> Unit -> Bool
> :: Unit -> Unit -> Bool
$c> :: Unit -> Unit -> Bool
<= :: Unit -> Unit -> Bool
$c<= :: Unit -> Unit -> Bool
< :: Unit -> Unit -> Bool
$c< :: Unit -> Unit -> Bool
compare :: Unit -> Unit -> Ordering
$ccompare :: Unit -> Unit -> Ordering
$cp1Ord :: Eq Unit
Ord, (forall x. Unit -> Rep Unit x)
-> (forall x. Rep Unit x -> Unit) -> Generic Unit
forall x. Rep Unit x -> Unit
forall x. Unit -> Rep Unit x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Unit x -> Unit
$cfrom :: forall x. Unit -> Rep Unit x
Generic, Eq Unit
Eq Unit -> (Int -> Unit -> Int) -> (Unit -> Int) -> Hashable Unit
Int -> Unit -> Int
Unit -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Unit -> Int
$chash :: Unit -> Int
hashWithSalt :: Int -> Unit -> Int
$chashWithSalt :: Int -> Unit -> Int
$cp1Hashable :: Eq Unit
Hashable, Unit -> ()
(Unit -> ()) -> NFData Unit
forall a. (a -> ()) -> NFData a
rnf :: Unit -> ()
$crnf :: Unit -> ()
NFData)
type instance TryDomain t Unit = 'NotFound
data Period = Period Word64 Unit
deriving (Int -> Period -> ShowS
[Period] -> ShowS
Period -> String
(Int -> Period -> ShowS)
-> (Period -> String) -> ([Period] -> ShowS) -> Show Period
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Period] -> ShowS
$cshowList :: [Period] -> ShowS
show :: Period -> String
$cshow :: Period -> String
showsPrec :: Int -> Period -> ShowS
$cshowsPrec :: Int -> Period -> ShowS
Show, (forall x. Period -> Rep Period x)
-> (forall x. Rep Period x -> Period) -> Generic Period
forall x. Rep Period x -> Period
forall x. Period -> Rep Period x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Period x -> Period
$cfrom :: forall x. Period -> Rep Period x
Generic, Eq Period
Eq Period
-> (Int -> Period -> Int) -> (Period -> Int) -> Hashable Period
Int -> Period -> Int
Period -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Period -> Int
$chash :: Period -> Int
hashWithSalt :: Int -> Period -> Int
$chashWithSalt :: Int -> Period -> Int
$cp1Hashable :: Eq Period
Hashable, Period -> Period -> Bool
(Period -> Period -> Bool)
-> (Period -> Period -> Bool) -> Eq Period
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Period -> Period -> Bool
$c/= :: Period -> Period -> Bool
== :: Period -> Period -> Bool
$c== :: Period -> Period -> Bool
Eq, Period -> ()
(Period -> ()) -> NFData Period
forall a. (a -> ()) -> NFData a
rnf :: Period -> ()
$crnf :: Period -> ()
NFData)
data Scale = Scale
{
Scale -> Period
step :: Period
, Scale -> Period
precision :: Period
}
deriving (Int -> Scale -> ShowS
[Scale] -> ShowS
Scale -> String
(Int -> Scale -> ShowS)
-> (Scale -> String) -> ([Scale] -> ShowS) -> Show Scale
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Scale] -> ShowS
$cshowList :: [Scale] -> ShowS
show :: Scale -> String
$cshow :: Scale -> String
showsPrec :: Int -> Scale -> ShowS
$cshowsPrec :: Int -> Scale -> ShowS
Show, (forall x. Scale -> Rep Scale x)
-> (forall x. Rep Scale x -> Scale) -> Generic Scale
forall x. Rep Scale x -> Scale
forall x. Scale -> Rep Scale x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep Scale x -> Scale
$cfrom :: forall x. Scale -> Rep Scale x
Generic, Eq Scale
Eq Scale
-> (Int -> Scale -> Int) -> (Scale -> Int) -> Hashable Scale
Int -> Scale -> Int
Scale -> Int
forall a. Eq a -> (Int -> a -> Int) -> (a -> Int) -> Hashable a
hash :: Scale -> Int
$chash :: Scale -> Int
hashWithSalt :: Int -> Scale -> Int
$chashWithSalt :: Int -> Scale -> Int
$cp1Hashable :: Eq Scale
Hashable, Scale -> Scale -> Bool
(Scale -> Scale -> Bool) -> (Scale -> Scale -> Bool) -> Eq Scale
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Scale -> Scale -> Bool
$c/= :: Scale -> Scale -> Bool
== :: Scale -> Scale -> Bool
$c== :: Scale -> Scale -> Bool
Eq, Scale -> ()
(Scale -> ()) -> NFData Scale
forall a. (a -> ()) -> NFData a
rnf :: Scale -> ()
$crnf :: Scale -> ()
NFData)
scaleToString :: Scale -> String
scaleToString :: Scale -> String
scaleToString (Scale{Period
step :: Period
step :: Scale -> Period
step, Period
precision :: Period
precision :: Scale -> Period
precision}) =
String
"`timescale " String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Period -> String
periodToString Period
step String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
"/" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Period -> String
periodToString Period
precision
periodToString :: Period -> String
periodToString :: Period -> String
periodToString (Period Word64
len Unit
unit) = Word64 -> String
forall a. Show a => a -> String
show Word64
len String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Unit -> String
unitToString Unit
unit
unitToString :: Unit -> String
unitToString :: Unit -> String
unitToString = (Char -> Char) -> ShowS
forall a b. (a -> b) -> [a] -> [b]
map Char -> Char
toLower ShowS -> (Unit -> String) -> Unit -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Unit -> String
forall a. Show a => a -> String
show
parseUnit :: String -> Maybe Unit
parseUnit :: String -> Maybe Unit
parseUnit String
s = (Unit -> Bool) -> [Unit] -> Maybe Unit
forall (t :: Type -> Type) a.
Foldable t =>
(a -> Bool) -> t a -> Maybe a
find Unit -> Bool
tryUnit [Unit
forall a. Bounded a => a
minBound..]
where
tryUnit :: Unit -> Bool
tryUnit :: Unit -> Bool
tryUnit Unit
u = Unit -> String
unitToString Unit
u String -> String -> Bool
forall a. Eq a => a -> a -> Bool
== String
s
parsePeriod :: String -> Maybe Period
parsePeriod :: String -> Maybe Period
parsePeriod String
s =
case (Char -> Bool) -> String -> (String, String)
forall a. (a -> Bool) -> [a] -> ([a], [a])
span Char -> Bool
isDigit String
s of
(String
len0, String
unit0) -> do
Word64
len1 <- String -> Maybe Word64
forall a. Read a => String -> Maybe a
readMaybe String
len0
Unit
unit1 <- String -> Maybe Unit
parseUnit String
unit0
Period -> Maybe Period
forall (f :: Type -> Type) a. Applicative f => a -> f a
pure (Word64 -> Unit -> Period
Period Word64
len1 Unit
unit1)
convertUnit :: Unit -> Period -> Word64
convertUnit :: Unit -> Period -> Word64
convertUnit Unit
targetUnit = Period -> Word64
go
where
go :: Period -> Word64
go (Period Word64
len Unit
unit) =
case Unit -> Unit -> Ordering
forall a. Ord a => a -> a -> Ordering
compare Unit
unit Unit
targetUnit of
Ordering
LT -> Period -> Word64
go (Word64 -> Unit -> Period
Period (Word64
len Word64 -> Word64 -> Word64
forall a. Integral a => a -> a -> a
`div` Word64
1000) (Unit -> Unit
forall a. Enum a => a -> a
succ Unit
unit))
Ordering
EQ -> Word64 -> Word64 -> Word64
forall a. Ord a => a -> a -> a
max Word64
1 Word64
len
Ordering
GT -> Period -> Word64
go (Word64 -> Unit -> Period
Period (Word64
len Word64 -> Word64 -> Word64
forall a. Num a => a -> a -> a
* Word64
1000) (Unit -> Unit
forall a. Enum a => a -> a
pred Unit
unit))