{-# OPTIONS_GHC -Wall #-}

-- | Communication between Haskell and Spectre
module Spectre ( Analysis (..)
               , version
               , simulate
               ) where

import           Data.NutMeg         (NutMeg)
import qualified Data.NutMeg    as N
import           System.Command
import           System.IO.Temp

-- | Available Simulation Analyses
data Analysis = AC      -- ^ AC Analysis
              | DC      -- ^ DC Analysis
              | DCMATCH -- ^ Offset Analysis
              | STB     -- ^ Stability Analysis
              | TRAN    -- ^ Transient Analysis
              | NOISE   -- ^ Noise Analysis
              | XF      -- ^ XF Analysis
              | ALTER   -- ^ Alter Statement
              deriving (Analysis -> Analysis -> Bool
(Analysis -> Analysis -> Bool)
-> (Analysis -> Analysis -> Bool) -> Eq Analysis
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Analysis -> Analysis -> Bool
$c/= :: Analysis -> Analysis -> Bool
== :: Analysis -> Analysis -> Bool
$c== :: Analysis -> Analysis -> Bool
Eq)

-- | Show instance for analyses are lowercase
instance Show Analysis where
  show :: Analysis -> String
show Analysis
AC      = String
"ac"
  show Analysis
DC      = String
"dc"
  show Analysis
DCMATCH = String
"dcmatch"
  show Analysis
STB     = String
"stb"
  show Analysis
TRAN    = String
"tran"
  show Analysis
NOISE   = String
"noise"
  show Analysis
XF      = String
"xf"
  show Analysis
ALTER   = String
"alter"

-- | Read instance for analyses handle lowercase
instance Read Analysis where
  readsPrec :: Int -> ReadS Analysis
readsPrec Int
_ String
"ac"      = [(Analysis
AC, String
"")]
  readsPrec Int
_ String
"dc"      = [(Analysis
DC, String
"")]
  readsPrec Int
_ String
"dcmatch" = [(Analysis
DCMATCH, String
"")]
  readsPrec Int
_ String
"stb"     = [(Analysis
STB, String
"")]
  readsPrec Int
_ String
"tran"    = [(Analysis
TRAN, String
"")]
  readsPrec Int
_ String
"noise"   = [(Analysis
NOISE, String
"")]
  readsPrec Int
_ String
"xf"      = [(Analysis
XF, String
"")]
  readsPrec Int
_ String
"alter"   = [(Analysis
ALTER, String
"")]
  readsPrec Int
_ String
_         = [(Analysis, String)]
forall a. HasCallStack => a
undefined

-- | Get Spectre Version
version :: IO String
version :: IO String
version = do
    Stdout String
v <- [CmdOption] -> String -> [String] -> IO Stdout
forall r. CmdResult r => [CmdOption] -> String -> [String] -> IO r
command [] String
"spectre" [String
"-V"]
    String -> IO String
forall (f :: * -> *) a. Applicative f => a -> f a
pure String
v

-- | Simulate a netlist non interactively and return simulation results
simulate :: [String] -> String -> IO NutMeg
simulate :: [String] -> String -> IO NutMeg
simulate [String]
includes String
netlist = do
    String
tmp <- String -> String -> IO String
createTempDirectory String
"/tmp" String
"hspectre"
    let raw' :: String
raw' = String
tmp String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"/hspectre.raw"
        log' :: String
log' = String
tmp String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
"/hspectre.log"
    let args :: [String]
args = [ String
"-64", String
"-format nutbin", String
"-raw " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
raw', String
"=log " String -> ShowS
forall a. [a] -> [a] -> [a]
++ String
log' 
               ] [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String]
incs [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ [String
netlist]
    [CmdOption] -> String -> [String] -> IO ()
command_ [] String
spectre [String]
args
    String -> IO NutMeg
N.readFile String
raw'
  where
    spectre :: String
spectre = String
"spectre"
    incs :: [String]
incs    = ShowS -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String
"-I"String -> ShowS
forall a. [a] -> [a] -> [a]
++) [String]
includes