aboutsummaryrefslogtreecommitdiffstats
path: root/src/Test/VeriFuzz/CodeGen.hs
blob: 85f1d1c39cd067fa6edd81d702a68be42b4f2ccb (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
68
69
70
71
72
73
74
75
{-# LANGUAGE OverloadedStrings #-}

module Test.VeriFuzz.CodeGen where

import           Control.Lens
import           Data.Text                     (Text)
import qualified Data.Text                     as T
import qualified Data.Text.IO                  as T
import           Test.VeriFuzz.Internal.Shared
import           Test.VeriFuzz.VerilogAST

genSourceText :: SourceText -> Text
genSourceText source =
  fromList $ genDescription <$> source ^. getSourceText

genDescription :: Description -> Text
genDescription desc =
  genModuleDecl $ desc ^. getDescription

genModuleDecl :: ModuleDecl -> Text
genModuleDecl mod =
  "module " <> mod ^. moduleId . getIdentifier
  <> "(\n" <> ports <> "\n);\n"
  <> modItems
  <> "endmodule\n"
  where
    ports = sep ",\n" $ genPort <$> mod ^. modPorts
    modItems = fromList $ genModuleItem <$> mod ^. moduleItems

genPort :: Port -> Text
genPort port =
  "  " <> dir <> " " <> name
  where
    dir = genPortDir $ port ^. portDir
    name = port ^. portName . getIdentifier

genPortDir :: PortDir -> Text
genPortDir Input  = "input"
genPortDir Output = "output"
genPortDir InOut  = "inout"

genModuleItem :: ModuleItem -> Text
genModuleItem (Assign assign) = genContAssign assign

genContAssign :: ContAssign -> Text
genContAssign assign =
  "  assign " <> name <> " = " <> expr <> ";\n"
  where
    name = assign ^. contAssignNetLVal . getIdentifier
    expr = genExpr $ assign ^. contAssignExpr

genExpr :: Expression -> Text
genExpr (OpExpr exprRhs bin exprLhs) =
  genExpr exprRhs <> genBinaryOperator bin <> genExpr exprLhs
genExpr (PrimExpr prim) =
  genPrimary prim
genExpr _ = "TODO"

genPrimary :: Primary -> Text
genPrimary (PrimNum num) =
  neg <> sh (num ^. numSize) <> "'d" <> (sh . abs) n
  where
    sh = T.pack . show
    abs x = if x <= 0 then -x else x
    n = num ^. numVal
    neg = if n <= 0 then "-" else ""
genPrimary (PrimId ident) = ident ^. getIdentifier

genBinaryOperator :: BinaryOperator -> Text
genBinaryOperator BinAnd = " & "
genBinaryOperator BinOr  = " | "
genBinaryOperator BinXor = " ^ "

render :: Text -> IO ()
render = T.putStrLn