aboutsummaryrefslogtreecommitdiffstats
path: root/src/VeriFuzz/Graph/CodeGen.hs
blob: 56b28aa6b7e99a10141d54a276a1b169cd01393d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
{-|
Module      : VeriFuzz.Graph.Random
Description : Code generation directly from DAG.
Copyright   : (c) 2018-2019, Yann Herklotz Grave
License     : BSD-3
Maintainer  : ymherklotz [at] gmail [dot] com
Stability   : experimental
Portability : POSIX

Define the code generation directly from the random DAG.
-}

module VeriFuzz.Graph.CodeGen
  ( generate
  )
where

import           Data.Foldable                  ( fold )
import           Data.Graph.Inductive           ( Graph
                                                , LNode
                                                , Node
                                                , labNodes
                                                , pre
                                                )
import           Data.Maybe                     ( fromMaybe )
import           Data.Text                      ( Text )
import qualified Data.Text                     as T
import           VeriFuzz.Circuit
import           VeriFuzz.Internal.Gen
import           VeriFuzz.Internal.Shared

toOperator :: Gate -> Text
toOperator And = " & "
toOperator Or  = " | "
toOperator Xor = " ^ "

statList :: Gate -> [Node] -> Maybe Text
statList g n = toStr <$> safe tail n where toStr = fold . fmap ((<> toOperator g) . fromNode)

lastEl :: [Node] -> Maybe Text
lastEl n = fromNode <$> safe head n

toStmnt :: (Graph gr) => gr Gate e -> LNode Gate -> Text
toStmnt graph (n, g) =
  fromMaybe T.empty
    $  Just "  assign "
    <> Just (fromNode n)
    <> Just " = "
    <> statList g nodeL
    <> lastEl nodeL
    <> Just ";\n"
  where nodeL = pre graph n

generate :: (Graph gr) => gr Gate e -> Text
generate graph =
  "module generated_module(\n"
    <> fold (imap "  input wire " ",\n" inp)
    <> T.intercalate ",\n" (imap "  output wire " "" out)
    <> ");\n"
    <> fold (toStmnt graph <$> labNodes graph)
    <> "endmodule\n\nmodule main;\n  initial\n    begin\n      "
    <> "$display(\"Hello, world\");\n      $finish;\n    "
    <> "end\nendmodule"
 where
  inp = inputs graph
  out = outputs graph
  imap b e = fmap ((\s -> b <> s <> e) . fromNode)