netlist-0.3.1: Language/Netlist/AST.hs
--------------------------------------------------------------------------------
-- |
-- Module : Language.Netlist.AST
-- Copyright : (c) Signali Corp. 2010
-- License : All rights reserved
--
-- Maintainer : pweaver@signalicorp.com
-- Stability : experimental
-- Portability : non-portable (DeriveDataTypeable)
--
-- 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.
--------------------------------------------------------------------------------
{-# LANGUAGE DeriveDataTypeable #-}
{-# OPTIONS_GHC -Wall #-}
{-# OPTIONS_DERIVE --append -d Binary #-}
module Language.Netlist.AST where
import Data.Binary ( Binary(..), putWord8, getWord8 )
import Data.Generics ( Data, Typeable )
-- -----------------------------------------------------------------------------
-- | A Module corresponds to a \"module\" in Verilog or an \"entity\" in VHDL.
data Module = Module
{ module_name :: Ident
, module_inputs :: [(Ident, Maybe Range)]
, module_outputs :: [(Ident, Maybe Range)]
, module_statics :: [(Ident, ConstExpr)]
-- static parameters (VHDL "generic", Verilog "parameter")
, module_decls :: [Decl]
}
deriving (Eq, Ord, Show, Data, Typeable)
-- | 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 (@wire@ in Verilog) has a continuously assigned value. The net can
-- be declared and assigned at the same time (@Just Expr@), or separately
-- (@Nothing@) in a @NetAssign@.
= NetDecl Ident (Maybe Range) (Maybe Expr)
| NetAssign Ident Expr
-- | A mem (@reg@ 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, @MemDecl x (0, 31) (7, 0)@ corresponds to the following in Verilog:
-- @reg [7:0] x [0:31]@
| MemDecl Ident (Maybe Range) (Maybe Range) (Maybe [Expr])
-- | These are permanent assignments to memory locations,
-- of the form mem[addr] = val
| MemAssign Ident Expr Expr
-- | 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 -- name of the module
Ident -- name of the instance
[(Ident, Expr)] -- parameter assignments
[(Ident, Expr)] -- input port connections
[(Ident, Expr)] -- output port connections
-- declare an external module entity
-- TODO: ExternDecl ExternLang
-- | A sequential process with clock and (optional) asynchronous reset.
| ProcessDecl Event (Maybe (Event, Stmt)) Stmt
-- | A statement that executes once at the beginning of simulation.
-- Equivalent to Verilog \"initial\" statement.
| InitProcessDecl Stmt
-- | A basic comment (typically is placed above a decl of interest).
-- Newlines are allowed, and generate new single line comments.
| CommentDecl String
deriving (Eq, Ord, Show, Data, Typeable)
-- | A 'Range' tells us the type of a bit vector. It can count up or down.
data Range
= Range ConstExpr ConstExpr
deriving (Eq, Ord, Show, Data, Typeable)
-- | 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
deriving (Eq, Ord, Show, Data, Typeable)
-- | An event can be triggered by the rising edge ('PosEdge') or falling edge
-- ('NegEdge') of a signal.
data Edge
= PosEdge
| NegEdge
deriving (Eq, Ord, Show, Data, Typeable)
-- | 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
= ExprLit (Maybe Size) ExprLit -- ^ a sized or unsized literal
| ExprVar Ident -- ^ a variable ference
| ExprString String -- ^ a quoted string (useful for parameters)
| ExprIndex Ident Expr -- ^ @x[e]@
| ExprSlice Ident Expr Expr -- ^ @x[e1 : e2]@
| ExprSliceOff Ident Expr Int -- ^ @x[e : e+i]@, where @i@ can be negative
| ExprCase Expr [([ConstExpr], Expr)] (Maybe Expr)
-- ^ case expression. supports multiple matches
-- per result value, and an optional default value
| ExprConcat [Expr] -- ^ concatenation
| ExprCond Expr Expr Expr -- ^ conditional expression
| ExprUnary UnaryOp Expr -- ^ application of a unary operator
| ExprBinary BinaryOp Expr Expr -- ^ application of a binary operator
| ExprFunCall Ident [Expr] -- ^ a function application
deriving (Eq, Ord, Show, Data, Typeable)
data ExprLit
= ExprNum Integer -- ^ a number
| ExprBit Bit -- ^ a single bit. in vhdl, bits are different than 1-bit bitvectors
| ExprBitVector [Bit]
deriving (Eq, Ord, Show, Data, Typeable)
data Bit
= T | F | U | Z
deriving (Eq, Ord, Show, Data, Typeable)
-- | Behavioral sequential statement
data Stmt
= Assign LValue Expr -- ^ non-blocking assignment
| If Expr Stmt (Maybe Stmt) -- ^ @if@ statement
| Case Expr [([Expr], Stmt)] (Maybe Stmt)
-- ^ case statement, with optional default case
| Seq [Stmt] -- ^ multiple statements in sequence
| FunCallStmt Ident [Expr] -- ^ a function call that can appear as a statement,
-- useful for calling Verilog tasks (e.g. $readmem).
deriving (Eq, Ord, Show, Data, Typeable)
-- | An 'LValue' 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 'Expr'.
type LValue = Expr
-- | Unary operators
--
-- 'LNeg' is logical negation, 'Neg' is bitwise negation. 'UAnd', 'UNand',
-- 'UOr', 'UNor', 'UXor', and 'UXnor' are sometimes called \"reduction
-- operators\".
data UnaryOp
= UPlus | UMinus | LNeg | Neg | UAnd | UNand | UOr | UNor | UXor | UXnor
deriving (Eq, Ord, Show, Data, Typeable)
-- | Binary operators.
--
-- These operators include almost all VHDL and Verilog operators.
--
-- * precedence and pretty-printing are language specific, and defined elsewhere.
--
-- * exponentation operators were introduced in Verilog-2001.
--
-- * some operators are not prefix/infix, such as verilog concatenation and the
-- conditional (@x ? y : z@) operator. those operators are defined in
-- 'Expr'.
--
-- * VHDL has both \"logical\" and \"barithmetic\" shift operators, which we
-- don't yet distinguish between here.
--
-- * VHDL has both a @mod@ and a @rem@ operator, but so far we only define
-- 'Modulo'.
--
-- * VHDL has a concat operator (@&@) that isn't yet supported here. Use
-- 'ExprConcat' instead.
--
-- * VHDL has an @abs@ operator that isn't yet supported here.
data BinaryOp
= Pow | Plus | Minus | Times | Divide | Modulo -- arithmetic
| Equals | NotEquals -- logical equality
| CEquals | CNotEquals -- case equality
| LAnd | LOr -- logical and/or
| LessThan | LessEqual | GreaterThan | GreaterEqual -- relational
| And | Nand | Or | Nor | Xor | Xnor -- bitwise
| ShiftLeft | ShiftRight | RotateLeft | RotateRight -- shift/rotate
| ShiftLeftArith | ShiftRightArith -- arithmetical shift
deriving (Eq, Ord, Show, Data, Typeable)
-- -----------------------------------------------------------------------------
-- GENERATED START
instance Binary Module where
put (Module x1 x2 x3 x4 x5)
= do put x1
put x2
put x3
put x4
put x5
get
= do x1 <- get
x2 <- get
x3 <- get
x4 <- get
x5 <- get
return (Module x1 x2 x3 x4 x5)
instance Binary Decl where
put x
= case x of
NetDecl x1 x2 x3 -> do putWord8 0
put x1
put x2
put x3
NetAssign x1 x2 -> do putWord8 1
put x1
put x2
MemDecl x1 x2 x3 x4 -> do putWord8 2
put x1
put x2
put x3
put x4
MemAssign x1 x2 x3 -> do putWord8 3
put x1
put x2
put x3
InstDecl x1 x2 x3 x4 x5 -> do putWord8 4
put x1
put x2
put x3
put x4
put x5
ProcessDecl x1 x2 x3 -> do putWord8 5
put x1
put x2
put x3
InitProcessDecl x1 -> do putWord8 6
put x1
CommentDecl x1 -> do putWord8 7
put x1
get
= do i <- getWord8
case i of
0 -> do x1 <- get
x2 <- get
x3 <- get
return (NetDecl x1 x2 x3)
1 -> do x1 <- get
x2 <- get
return (NetAssign x1 x2)
2 -> do x1 <- get
x2 <- get
x3 <- get
x4 <- get
return (MemDecl x1 x2 x3 x4)
3 -> do x1 <- get
x2 <- get
x3 <- get
return (MemAssign x1 x2 x3)
4 -> do x1 <- get
x2 <- get
x3 <- get
x4 <- get
x5 <- get
return (InstDecl x1 x2 x3 x4 x5)
5 -> do x1 <- get
x2 <- get
x3 <- get
return (ProcessDecl x1 x2 x3)
6 -> do x1 <- get
return (InitProcessDecl x1)
7 -> do x1 <- get
return (CommentDecl x1)
_ -> error "Corrupted binary data for Decl"
instance Binary Range where
put (Range x1 x2)
= do put x1
put x2
get
= do x1 <- get
x2 <- get
return (Range x1 x2)
instance Binary Event where
put (Event x1 x2)
= do put x1
put x2
get
= do x1 <- get
x2 <- get
return (Event x1 x2)
instance Binary Edge where
put x
= case x of
PosEdge -> putWord8 0
NegEdge -> putWord8 1
get
= do i <- getWord8
case i of
0 -> return PosEdge
1 -> return NegEdge
_ -> error "Corrupted binary data for Edge"
instance Binary Expr where
put x
= case x of
ExprLit x1 x2 -> do putWord8 0
put x1
put x2
ExprVar x1 -> do putWord8 1
put x1
ExprString x1 -> do putWord8 2
put x1
ExprIndex x1 x2 -> do putWord8 3
put x1
put x2
ExprSlice x1 x2 x3 -> do putWord8 4
put x1
put x2
put x3
ExprSliceOff x1 x2 x3 -> do putWord8 5
put x1
put x2
put x3
ExprCase x1 x2 x3 -> do putWord8 6
put x1
put x2
put x3
ExprConcat x1 -> do putWord8 7
put x1
ExprCond x1 x2 x3 -> do putWord8 8
put x1
put x2
put x3
ExprUnary x1 x2 -> do putWord8 9
put x1
put x2
ExprBinary x1 x2 x3 -> do putWord8 10
put x1
put x2
put x3
ExprFunCall x1 x2 -> do putWord8 11
put x1
put x2
get
= do i <- getWord8
case i of
0 -> do x1 <- get
x2 <- get
return (ExprLit x1 x2)
1 -> do x1 <- get
return (ExprVar x1)
2 -> do x1 <- get
return (ExprString x1)
3 -> do x1 <- get
x2 <- get
return (ExprIndex x1 x2)
4 -> do x1 <- get
x2 <- get
x3 <- get
return (ExprSlice x1 x2 x3)
5 -> do x1 <- get
x2 <- get
x3 <- get
return (ExprSliceOff x1 x2 x3)
6 -> do x1 <- get
x2 <- get
x3 <- get
return (ExprCase x1 x2 x3)
7 -> do x1 <- get
return (ExprConcat x1)
8 -> do x1 <- get
x2 <- get
x3 <- get
return (ExprCond x1 x2 x3)
9 -> do x1 <- get
x2 <- get
return (ExprUnary x1 x2)
10 -> do x1 <- get
x2 <- get
x3 <- get
return (ExprBinary x1 x2 x3)
11 -> do x1 <- get
x2 <- get
return (ExprFunCall x1 x2)
_ -> error "Corrupted binary data for Expr"
instance Binary ExprLit where
put x
= case x of
ExprNum x1 -> do putWord8 0
put x1
ExprBit x1 -> do putWord8 1
put x1
ExprBitVector x1 -> do putWord8 2
put x1
get
= do i <- getWord8
case i of
0 -> do x1 <- get
return (ExprNum x1)
1 -> do x1 <- get
return (ExprBit x1)
2 -> do x1 <- get
return (ExprBitVector x1)
_ -> error "Corrupted binary data for ExprLit"
instance Binary Bit where
put x
= case x of
T -> putWord8 0
F -> putWord8 1
U -> putWord8 2
Z -> putWord8 3
get
= do i <- getWord8
case i of
0 -> return T
1 -> return F
2 -> return U
3 -> return Z
_ -> error "Corrupted binary data for Bit"
instance Binary Stmt where
put x
= case x of
Assign x1 x2 -> do putWord8 0
put x1
put x2
If x1 x2 x3 -> do putWord8 1
put x1
put x2
put x3
Case x1 x2 x3 -> do putWord8 2
put x1
put x2
put x3
Seq x1 -> do putWord8 3
put x1
FunCallStmt x1 x2 -> do putWord8 4
put x1
put x2
get
= do i <- getWord8
case i of
0 -> do x1 <- get
x2 <- get
return (Assign x1 x2)
1 -> do x1 <- get
x2 <- get
x3 <- get
return (If x1 x2 x3)
2 -> do x1 <- get
x2 <- get
x3 <- get
return (Case x1 x2 x3)
3 -> do x1 <- get
return (Seq x1)
4 -> do x1 <- get
x2 <- get
return (FunCallStmt x1 x2)
_ -> error "Corrupted binary data for Stmt"
instance Binary UnaryOp where
put x
= case x of
UPlus -> putWord8 0
UMinus -> putWord8 1
LNeg -> putWord8 2
Neg -> putWord8 3
UAnd -> putWord8 4
UNand -> putWord8 5
UOr -> putWord8 6
UNor -> putWord8 7
UXor -> putWord8 8
UXnor -> putWord8 9
get
= do i <- getWord8
case i of
0 -> return UPlus
1 -> return UMinus
2 -> return LNeg
3 -> return Neg
4 -> return UAnd
5 -> return UNand
6 -> return UOr
7 -> return UNor
8 -> return UXor
9 -> return UXnor
_ -> error "Corrupted binary data for UnaryOp"
instance Binary BinaryOp where
put x
= case x of
Pow -> putWord8 0
Plus -> putWord8 1
Minus -> putWord8 2
Times -> putWord8 3
Divide -> putWord8 4
Modulo -> putWord8 5
Equals -> putWord8 6
NotEquals -> putWord8 7
CEquals -> putWord8 8
CNotEquals -> putWord8 9
LAnd -> putWord8 10
LOr -> putWord8 11
LessThan -> putWord8 12
LessEqual -> putWord8 13
GreaterThan -> putWord8 14
GreaterEqual -> putWord8 15
And -> putWord8 16
Nand -> putWord8 17
Or -> putWord8 18
Nor -> putWord8 19
Xor -> putWord8 20
Xnor -> putWord8 21
ShiftLeft -> putWord8 22
ShiftRight -> putWord8 23
RotateLeft -> putWord8 24
RotateRight -> putWord8 25
ShiftLeftArith -> putWord8 26
ShiftRightArith -> putWord8 27
get
= do i <- getWord8
case i of
0 -> return Pow
1 -> return Plus
2 -> return Minus
3 -> return Times
4 -> return Divide
5 -> return Modulo
6 -> return Equals
7 -> return NotEquals
8 -> return CEquals
9 -> return CNotEquals
10 -> return LAnd
11 -> return LOr
12 -> return LessThan
13 -> return LessEqual
14 -> return GreaterThan
15 -> return GreaterEqual
16 -> return And
17 -> return Nand
18 -> return Or
19 -> return Nor
20 -> return Xor
21 -> return Xnor
22 -> return ShiftLeft
23 -> return ShiftRight
24 -> return RotateLeft
25 -> return RotateRight
26 -> return ShiftLeftArith
27 -> return ShiftRightArith
_ -> error "Corrupted binary data for BinaryOp"
-- GENERATED STOP