module Language.Verilog.DSL
( Verilog
, elaborate
, getMeta
, setMeta
, genVar
, input
, output
, wire
, reg
, assign
, next
, var
, constant
, mappend
, mconcat
, (<>)
, mux
) where
import Data.Monoid
import MonadLib
import Data.BitVec
import Language.Verilog.AST
type Verilog a = StateT (Int, a, [ModuleItem]) Id
elaborate :: String -> a -> Verilog a () -> (a, Module)
elaborate name a m = (a', Module name (concatMap port items) items)
where
((), (_, a', items)) = runId $ runStateT (0, a, []) m
port :: ModuleItem -> [String]
port a = case a of
Input _ a -> a
Output _ a -> a
Inout _ a -> a
_ -> []
getMeta :: Verilog a a
getMeta = do
(_, a, _) <- get
return a
setMeta :: a -> Verilog a ()
setMeta a = do
(i, _, m) <- get
set (i, a, m)
genVar :: Verilog a String
genVar = do
(i, a, m) <- get
set (i + 1, a, m)
return $ "_verilog_" ++ show i
item :: ModuleItem -> Verilog a ()
item b = do
(i, a, m) <- get
set (i, a, m ++ [b])
input :: String -> Int -> Verilog a ()
input a w = item $ Input (range w) [a]
output :: String -> Int -> Verilog a ()
output a w = item $ Output (range w) [a]
wire :: String -> Int -> Maybe Expr -> Verilog a ()
wire a w b = item $ Wire (range w) [(a, b)]
reg :: String -> Int -> Verilog a ()
reg a w = item $ Reg (range w) [(a, Nothing)]
range :: Int -> Maybe Range
range w
| w == 1 = Nothing
| otherwise = Just (fromIntegral $ w 1, 0)
assign :: String -> Expr -> Verilog a ()
assign a b = item $ Assign (LHS a) b
next :: String -> Expr -> Verilog a ()
next a b = item $ Always (SensePosedge $ LHS "clock") $ If (ExprLHS $ LHS "reset") (NonBlockingAssignment (LHS a) 0) (NonBlockingAssignment (LHS a) b)
var :: String -> Expr
var = ExprLHS . LHS
constant :: Int -> Integer -> Expr
constant a b = Number $ bitVec a b
mux :: Expr -> Expr -> Expr -> Expr
mux = Mux