-- Hoogle documentation, generated by Haddock
-- See Hoogle, http://www.haskell.org/hoogle/


-- | Netlist AST
--   
--   A very simplified and generic netlist designed to be compatible with
--   Hardware Description Languages (HDLs) like Verilog and VHDL. Includes
--   a simple inliner.
@package netlist
@version 0.3.1


-- | An abstract syntax tree (AST) for a generic netlist, kind of like a
--   high-level subset of Verilog and VHDL that is compatible with both
--   languages.
--   
--   There are no definitive semantics assigned to this AST.
--   
--   For example, the user may choose to treat the bindings as recursive,
--   so that expressions can reference variables before their declaration,
--   like in Haskell, which is not supported in Verilog and VHDL. in this
--   case, the user must fix the bindings when converting to an HDL.
--   
--   Also, the user may treat module instantiations and processes as having
--   an implict clock/reset, so that they are not explicitly named in those
--   constructs in this AST. Then, the clock and reset can be inserted when
--   generating HDL.
--   
--   When you instantiate a module but information about that module is
--   missing (e.g. the clock/reset are implicit and you need to know what
--   they are called in that module), you can use ExternDecl (TODO) to
--   declare a module's interface so that you know how to instantiate it,
--   or retrieve the interface from a user-maintained database or by
--   parsing and extracting from an HDL file.
module Language.Netlist.AST

-- | A Module corresponds to a "module" in Verilog or an "entity" in VHDL.
data Module
Module :: Ident -> [(Ident, Maybe Range)] -> [(Ident, Maybe Range)] -> [(Ident, ConstExpr)] -> [Decl] -> Module
[module_name] :: Module -> Ident
[module_inputs] :: Module -> [(Ident, Maybe Range)]
[module_outputs] :: Module -> [(Ident, Maybe Range)]
[module_statics] :: Module -> [(Ident, ConstExpr)]
[module_decls] :: Module -> [Decl]

-- | An identifier name.
type Ident = String

-- | The size of a wire.
type Size = Int

-- | A declaration, analogous to an "item" in the Verilog formal syntax.
data Decl

-- | A net (<tt>wire</tt> in Verilog) has a continuously assigned value.
--   The net can be declared and assigned at the same time (<tt>Just
--   Expr</tt>), or separately (<tt>Nothing</tt>) in a <tt>NetAssign</tt>.
NetDecl :: Ident -> Maybe Range -> Maybe Expr -> Decl
NetAssign :: Ident -> Expr -> Decl

-- | A mem (<tt>reg</tt> in Verilog) is stateful. It can be assigned by a
--   non-blocking assignment (or blocking, but we don't support those yet)
--   within a process. TODO: support optional initial value
--   
--   The first range is the most significant dimension. So, <tt>MemDecl x
--   (0, 31) (7, 0)</tt> corresponds to the following in Verilog: <tt>reg
--   [7:0] x [0:31]</tt>
MemDecl :: Ident -> Maybe Range -> Maybe Range -> Maybe [Expr] -> Decl

-- | These are permanent assignments to memory locations, of the form
--   mem[addr] = val
MemAssign :: Ident -> Expr -> Expr -> Decl

-- | A module/entity instantiation. The arguments are the name of the
--   module, the name of the instance, the parameter assignments, the input
--   port connections, and the output port connections.
InstDecl :: Ident -> Ident -> [(Ident, Expr)] -> [(Ident, Expr)] -> [(Ident, Expr)] -> Decl

-- | A sequential process with clock and (optional) asynchronous reset.
ProcessDecl :: Event -> Maybe (Event, Stmt) -> Stmt -> Decl

-- | A statement that executes once at the beginning of simulation.
--   Equivalent to Verilog "initial" statement.
InitProcessDecl :: Stmt -> Decl

-- | A basic comment (typically is placed above a decl of interest).
--   Newlines are allowed, and generate new single line comments.
CommentDecl :: String -> Decl

-- | A <a>Range</a> tells us the type of a bit vector. It can count up or
--   down.
data Range
Range :: ConstExpr -> ConstExpr -> Range

-- | A constant expression is simply an expression that must be a constant
--   (i.e. the only free variables are static parameters). This restriction
--   is not made in the AST.
type ConstExpr = Expr
data Event
Event :: Expr -> Edge -> Event

-- | An event can be triggered by the rising edge (<a>PosEdge</a>) or
--   falling edge (<a>NegEdge</a>) of a signal.
data Edge
PosEdge :: Edge
NegEdge :: Edge

-- | Expr is a combination of VHDL and Verilog expressions.
--   
--   In VHDL, concatenation is a binary operator, but in Verilog it takes
--   any number of arguments. In this AST, we define it like the Verilog
--   operator. If we translate to VHDL, we have to convert it to the VHDL
--   binary operator.
--   
--   There are some HDL operators that we don't represent here. For
--   example, in Verilog there is a multiple concatenation (a.k.a.
--   replication) operator, which we don't bother to support.
data Expr

-- | a sized or unsized literal
ExprLit :: Maybe Size -> ExprLit -> Expr

-- | a variable ference
ExprVar :: Ident -> Expr

-- | a quoted string (useful for parameters)
ExprString :: String -> Expr

-- | <pre>
--   x[e]
--   </pre>
ExprIndex :: Ident -> Expr -> Expr

-- | <pre>
--   x[e1 : e2]
--   </pre>
ExprSlice :: Ident -> Expr -> Expr -> Expr

-- | <tt>x[e : e+i]</tt>, where <tt>i</tt> can be negative
ExprSliceOff :: Ident -> Expr -> Int -> Expr

-- | case expression. supports multiple matches per result value, and an
--   optional default value
ExprCase :: Expr -> [([ConstExpr], Expr)] -> Maybe Expr -> Expr

-- | concatenation
ExprConcat :: [Expr] -> Expr

-- | conditional expression
ExprCond :: Expr -> Expr -> Expr -> Expr

-- | application of a unary operator
ExprUnary :: UnaryOp -> Expr -> Expr

-- | application of a binary operator
ExprBinary :: BinaryOp -> Expr -> Expr -> Expr

-- | a function application
ExprFunCall :: Ident -> [Expr] -> Expr
data ExprLit

-- | a number
ExprNum :: Integer -> ExprLit

-- | a single bit. in vhdl, bits are different than 1-bit bitvectors
ExprBit :: Bit -> ExprLit
ExprBitVector :: [Bit] -> ExprLit
data Bit
T :: Bit
F :: Bit
U :: Bit
Z :: Bit

-- | Behavioral sequential statement
data Stmt

-- | non-blocking assignment
Assign :: LValue -> Expr -> Stmt

-- | <tt>if</tt> statement
If :: Expr -> Stmt -> Maybe Stmt -> Stmt

-- | case statement, with optional default case
Case :: Expr -> [([Expr], Stmt)] -> Maybe Stmt -> Stmt

-- | multiple statements in sequence
Seq :: [Stmt] -> Stmt

-- | a function call that can appear as a statement, useful for calling
--   Verilog tasks (e.g. $readmem).
FunCallStmt :: Ident -> [Expr] -> Stmt

-- | An <a>LValue</a> is something that can appear on the left-hand side of
--   an assignment. We're lazy and do not enforce any restriction, and
--   define this simply to be <a>Expr</a>.
type LValue = Expr

-- | Unary operators
--   
--   <a>LNeg</a> is logical negation, <a>Neg</a> is bitwise negation.
--   <a>UAnd</a>, <a>UNand</a>, <a>UOr</a>, <a>UNor</a>, <a>UXor</a>, and
--   <a>UXnor</a> are sometimes called "reduction operators".
data UnaryOp
UPlus :: UnaryOp
UMinus :: UnaryOp
LNeg :: UnaryOp
Neg :: UnaryOp
UAnd :: UnaryOp
UNand :: UnaryOp
UOr :: UnaryOp
UNor :: UnaryOp
UXor :: UnaryOp
UXnor :: UnaryOp

-- | Binary operators.
--   
--   These operators include almost all VHDL and Verilog operators.
--   
--   <ul>
--   <li>precedence and pretty-printing are language specific, and defined
--   elsewhere.</li>
--   <li>exponentation operators were introduced in Verilog-2001.</li>
--   <li>some operators are not prefix/infix, such as verilog concatenation
--   and the conditional (<tt>x ? y : z</tt>) operator. those operators are
--   defined in <a>Expr</a>.</li>
--   <li>VHDL has both "logical" and "barithmetic" shift operators, which
--   we don't yet distinguish between here.</li>
--   <li>VHDL has both a <tt>mod</tt> and a <tt>rem</tt> operator, but so
--   far we only define <a>Modulo</a>.</li>
--   <li>VHDL has a concat operator (<tt>&amp;</tt>) that isn't yet
--   supported here. Use <a>ExprConcat</a> instead.</li>
--   <li>VHDL has an <tt>abs</tt> operator that isn't yet supported
--   here.</li>
--   </ul>
data BinaryOp
Pow :: BinaryOp
Plus :: BinaryOp
Minus :: BinaryOp
Times :: BinaryOp
Divide :: BinaryOp
Modulo :: BinaryOp
Equals :: BinaryOp
NotEquals :: BinaryOp
CEquals :: BinaryOp
CNotEquals :: BinaryOp
LAnd :: BinaryOp
LOr :: BinaryOp
LessThan :: BinaryOp
LessEqual :: BinaryOp
GreaterThan :: BinaryOp
GreaterEqual :: BinaryOp
And :: BinaryOp
Nand :: BinaryOp
Or :: BinaryOp
Nor :: BinaryOp
Xor :: BinaryOp
Xnor :: BinaryOp
ShiftLeft :: BinaryOp
ShiftRight :: BinaryOp
RotateLeft :: BinaryOp
RotateRight :: BinaryOp
ShiftLeftArith :: BinaryOp
ShiftRightArith :: BinaryOp
instance Data.Binary.Class.Binary Language.Netlist.AST.BinaryOp
instance Data.Binary.Class.Binary Language.Netlist.AST.Bit
instance Data.Binary.Class.Binary Language.Netlist.AST.Decl
instance Data.Binary.Class.Binary Language.Netlist.AST.Edge
instance Data.Binary.Class.Binary Language.Netlist.AST.Event
instance Data.Binary.Class.Binary Language.Netlist.AST.Expr
instance Data.Binary.Class.Binary Language.Netlist.AST.ExprLit
instance Data.Binary.Class.Binary Language.Netlist.AST.Module
instance Data.Binary.Class.Binary Language.Netlist.AST.Range
instance Data.Binary.Class.Binary Language.Netlist.AST.Stmt
instance Data.Binary.Class.Binary Language.Netlist.AST.UnaryOp
instance GHC.Internal.Data.Data.Data Language.Netlist.AST.BinaryOp
instance GHC.Internal.Data.Data.Data Language.Netlist.AST.Bit
instance GHC.Internal.Data.Data.Data Language.Netlist.AST.Decl
instance GHC.Internal.Data.Data.Data Language.Netlist.AST.Edge
instance GHC.Internal.Data.Data.Data Language.Netlist.AST.Event
instance GHC.Internal.Data.Data.Data Language.Netlist.AST.Expr
instance GHC.Internal.Data.Data.Data Language.Netlist.AST.ExprLit
instance GHC.Internal.Data.Data.Data Language.Netlist.AST.Module
instance GHC.Internal.Data.Data.Data Language.Netlist.AST.Range
instance GHC.Internal.Data.Data.Data Language.Netlist.AST.Stmt
instance GHC.Internal.Data.Data.Data Language.Netlist.AST.UnaryOp
instance GHC.Classes.Eq Language.Netlist.AST.BinaryOp
instance GHC.Classes.Eq Language.Netlist.AST.Bit
instance GHC.Classes.Eq Language.Netlist.AST.Decl
instance GHC.Classes.Eq Language.Netlist.AST.Edge
instance GHC.Classes.Eq Language.Netlist.AST.Event
instance GHC.Classes.Eq Language.Netlist.AST.Expr
instance GHC.Classes.Eq Language.Netlist.AST.ExprLit
instance GHC.Classes.Eq Language.Netlist.AST.Module
instance GHC.Classes.Eq Language.Netlist.AST.Range
instance GHC.Classes.Eq Language.Netlist.AST.Stmt
instance GHC.Classes.Eq Language.Netlist.AST.UnaryOp
instance GHC.Classes.Ord Language.Netlist.AST.BinaryOp
instance GHC.Classes.Ord Language.Netlist.AST.Bit
instance GHC.Classes.Ord Language.Netlist.AST.Decl
instance GHC.Classes.Ord Language.Netlist.AST.Edge
instance GHC.Classes.Ord Language.Netlist.AST.Event
instance GHC.Classes.Ord Language.Netlist.AST.Expr
instance GHC.Classes.Ord Language.Netlist.AST.ExprLit
instance GHC.Classes.Ord Language.Netlist.AST.Module
instance GHC.Classes.Ord Language.Netlist.AST.Range
instance GHC.Classes.Ord Language.Netlist.AST.Stmt
instance GHC.Classes.Ord Language.Netlist.AST.UnaryOp
instance GHC.Internal.Show.Show Language.Netlist.AST.BinaryOp
instance GHC.Internal.Show.Show Language.Netlist.AST.Bit
instance GHC.Internal.Show.Show Language.Netlist.AST.Decl
instance GHC.Internal.Show.Show Language.Netlist.AST.Edge
instance GHC.Internal.Show.Show Language.Netlist.AST.Event
instance GHC.Internal.Show.Show Language.Netlist.AST.Expr
instance GHC.Internal.Show.Show Language.Netlist.AST.ExprLit
instance GHC.Internal.Show.Show Language.Netlist.AST.Module
instance GHC.Internal.Show.Show Language.Netlist.AST.Range
instance GHC.Internal.Show.Show Language.Netlist.AST.Stmt
instance GHC.Internal.Show.Show Language.Netlist.AST.UnaryOp


-- | A simple inliner for a Netlist AST (<a>AST</a>).
module Language.Netlist.Inline

-- | Produce a new module in which some variables have been inlined. An
--   expression is inlined (and it's declaration removed) if it only used
--   in one place in the entire module.
inlineModule :: Module -> Module


-- | Utility functions for constructing Netlist AST elements.
module Language.Netlist.Util
data Direction
Up :: Direction
Down :: Direction
unsizedInteger :: Integer -> Expr
unsizedIntegral :: Integral a => a -> Expr
sizedInteger :: Int -> Integer -> Expr
sizedIntegral :: Integral a => Int -> a -> Expr

-- | Given a direction and size, maybe generate a <a>Range</a>, where a
--   size of 1 yields <a>Nothing</a>.
makeRange :: Direction -> Size -> Maybe Range

-- | Concatenate a list of expressions, unless there is just one
--   expression.
exprConcat :: [Expr] -> Expr

-- | Make a <a>Seq</a> statement from a list of statements, unless there is
--   just one statement.
statements :: [Stmt] -> Stmt

-- | generate a process declaration for a generic register based on the
--   following:
--   
--   <ul>
--   <li>the register name (as an expression)</li>
--   <li>clock expression</li>
--   <li>width of the register</li>
--   <li>optional asynchronous reset and initial value</li>
--   <li>optional clock enable</li>
--   <li>optional synchronous restart and initial value</li>
--   <li>optional load enable</li>
--   <li>when enabled, the expression to assign to the identifier</li>
--   </ul>
--   
--   You can implement a shift register by passing in a concatenation for
--   the register expression and the input expression, though that is not
--   compatible with VHDL.
generateReg :: Expr -> Expr -> Maybe (Expr, Expr) -> Maybe (Expr, Expr) -> Maybe Expr -> Expr -> Decl
