ersatz-viz-0: src/Ersatz/Bit/Display.hs
{-# language OverloadedStrings #-}
{-# language LambdaCase #-}
module Ersatz.Bit.Display where
import Ersatz.Bit (Bit(..))
import Ersatz.Internal.StableName
import Ersatz.Problem (runSAT')
import Control.Monad (void, forM, forM_)
import Control.Monad.RWS
import Data.HashMap.Lazy (HashMap)
import qualified Data.HashMap.Lazy as HashMap
import System.IO.Unsafe
import Control.Lens
import Data.Foldable (toList)
import Data.Text (Text)
import qualified Data.Text as T
import System.Process.Text
import System.Mem.StableName (StableName, makeStableName)
import Unsafe.Coerce (unsafeCoerce)
display m = dot $ fst $ runSAT' m
dot b = void $ readProcessWithExitCode "dot" [ "-Tx11" ] $ toDot b
toDot :: Bit -> Text
toDot b = snd
$ ( \ m -> evalRWS (do
tell "digraph Bit {"
tell "graph [ordering=\"out\"]"
tell "node [style=\"plane\"]"
m
tell "}"
) () s0 )
$ walk b
subs :: Bit -> [Bit]
subs b = case b of
Not (And xs) -> toList xs
And xs -> toList xs
Xor a b -> [a,b]
Mux a b c -> [a,b,c]
Not a -> [a]
Var {} -> []
Run {} -> []
name :: Bit -> Text
name b = case b of
Not (And {}) -> "nand"
And {} -> "and"
Xor {} -> "xor"
Mux {} -> "mux"
Not {} -> "not"
Var l -> T.pack $ show l
Run {} -> "run"
data State = State
{ _stableMap :: !(HashMap (StableName ()) Int)
, _next :: !Int
}
s0 :: State
s0 = State { _stableMap = HashMap.empty , _next = 0 }
stableMap :: Lens' State (HashMap (StableName ()) Int)
stableMap f (s@State {_stableMap = sm})
= fmap (\ sm' -> s { _stableMap = sm'} ) (f sm)
next :: Lens' State Int
next f (s@State { _next = n })
= fmap (\ n' -> s { _next = n' } ) (f n)
fresh :: RWST () Text State Identity Int
fresh = do this <- use next ; next += 1 ; return this
walk :: Bit -> RWST () Text State Identity Int
walk b = do
let sn = unsafePerformIO (makeStableName' b)
use (stableMap.at sn) >>= \ case
Just n -> return n
Nothing -> do
this <- fresh
stableMap.at sn ?= this
cs <- forM (subs b) walk
tell $ T.pack (show this) <> "[label=\"" <> name b <> "\"];"
forM_ cs $ \ c -> do
tell $ T.pack (show this) <> "->" <> T.pack (show c) <> ";"
return this