Commit b0eedfe3 by Zachary Snow

$bits conversion handles basic expressions

parent 73f83112
......@@ -6,25 +6,77 @@
module Convert.Bits (convert) where
import Control.Monad.State
import qualified Data.Map.Strict as Map
import Convert.Traverse
import Language.SystemVerilog.AST
type Info = Map.Map Identifier (Type, [Range])
convert :: AST -> AST
convert =
traverseDescriptions $
traverseModuleItems $
traverseExprs $
traverseNestedExprs $
convertExpr
convertExpr :: Expr -> Expr
convertExpr (Bits (Left (IntegerVector _ _ rs))) = size rs
convertExpr (Bits (Left (Implicit _ rs))) = size rs
convertExpr other = other
size :: [Range] -> Expr
size ranges =
simplify $
foldl (BinOp Mul) (Number "1") $
map rangeSize $
ranges
convert = traverseDescriptions convertDescription
convertDescription :: Description -> Description
convertDescription =
scopedConversion traverseDeclM traverseModuleItemM traverseStmtM Map.empty
-- collects and converts multi-dimensional packed-array declarations
traverseDeclM :: Decl -> State Info Decl
traverseDeclM (origDecl @ (Variable _ t ident a _)) = do
modify $ Map.insert ident (t, a)
return origDecl
traverseDeclM other = return other
traverseModuleItemM :: ModuleItem -> State Info ModuleItem
traverseModuleItemM item = traverseExprsM traverseExprM item
traverseStmtM :: Stmt -> State Info Stmt
traverseStmtM stmt = traverseStmtExprsM traverseExprM stmt
traverseExprM :: Expr -> State Info Expr
traverseExprM = traverseNestedExprsM $ stately convertExpr
convertExpr :: Info -> Expr -> Expr
convertExpr _ (Bits (Left t)) =
case t of
IntegerVector _ _ rs -> dimensionsSize rs
Implicit _ rs -> dimensionsSize rs
Net _ rs -> dimensionsSize rs
_ -> Bits $ Left t
convertExpr info (Bits (Right e)) =
case e of
Ident x ->
case Map.lookup x info of
Nothing -> Bits $ Right e
Just (t, rs) -> simplify $ BinOp Mul
(dimensionsSize rs)
(convertExpr info $ Bits $ Left t)
Concat exprs ->
foldl (BinOp Add) (Number "0") $
map (convertExpr info) $
map (Bits . Right) $
exprs
Range expr mode range ->
simplify $ BinOp Mul size
(convertExpr info $ Bits $ Right $ Bit expr (Number "0"))
where
size = case mode of
NonIndexed -> rangeSize range
IndexedPlus -> snd range
IndexedMinus -> snd range
Bit (Ident x) idx ->
case Map.lookup x info of
Nothing -> Bits $ Right $ Bit (Ident x) idx
Just (t, rs) ->
convertExpr info $ Bits $ Left t'
where t' = popRange t rs
_ -> Bits $ Right e
convertExpr _ other = other
popRange :: Type -> [Range] -> Type
popRange t rs =
tf $ tail rsCombined
where
(tf, trs) = typeRanges t
rsCombined = rs ++ trs
......@@ -35,19 +35,9 @@ convert :: AST -> AST
convert = traverseDescriptions convertDescription
convertDescription :: Description -> Description
convertDescription (description @ (Part _ _ _ _ _ _)) =
evalState
(initialTraverse description >>= scopedTraverse)
convertDescription =
scopedConversion traverseDeclM traverseModuleItemM traverseStmtM
(Info Map.empty)
where
initialTraverse = traverseModuleItemsM traverseMIDecl
scopedTraverse = traverseModuleItemsM $
traverseScopesM traverseDeclM traverseModuleItemM traverseStmtM
traverseMIDecl :: ModuleItem -> State Info ModuleItem
traverseMIDecl (MIDecl decl) =
traverseDeclM decl >>= return . MIDecl
traverseMIDecl other = return other
convertDescription description = description
-- collects and converts multi-dimensional packed-array declarations
traverseDeclM :: Decl -> State Info Decl
......
......@@ -217,11 +217,8 @@ convertAsgn structs types (lhs, expr) =
Pattern [(Just "default", e)]
else if null rs then
expanded
else if length rs == 1 then
Repeat (rangeSize $ head rs) [expanded]
else
error $ "default pattern for multi-dimensional struct array "
++ show structTf ++ " is not allowed"
Repeat (dimensionsSize rs) [expanded]
where
structTf = Struct (Packed sg) fields
expanded = convertExpr (structTf []) $ Pattern $
......
......@@ -71,6 +71,7 @@ module Convert.Traverse
, traverseNestedLHSs
, collectNestedLHSsM
, traverseScopesM
, scopedConversion
, stately
) where
......@@ -929,6 +930,26 @@ traverseScopesM declMapper moduleItemMapper stmtMapper =
else error $ "illegal scope state modification: "
++ show (prevState, item, currState, item')
-- applies the given decl conversion across the description, and then performs a
-- scoped traversal for each ModuleItem in the description
scopedConversion
:: (Eq s, Show s)
=> MapperM (State s) Decl
-> MapperM (State s) ModuleItem
-> MapperM (State s) Stmt
-> s
-> Description
-> Description
scopedConversion traverseDeclM traverseModuleItemM traverseStmtM s description =
evalState (initialTraverse description >>= scopedTraverse) s
where
initialTraverse = traverseModuleItemsM traverseMIDecl
scopedTraverse = traverseModuleItemsM $
traverseScopesM traverseDeclM traverseModuleItemM traverseStmtM
traverseMIDecl (MIDecl decl) =
traverseDeclM decl >>= return . MIDecl
traverseMIDecl other = return other
-- convert a basic mapper with an initial argument to a stateful mapper
stately :: (Eq s, Show s) => (s -> Mapper a) -> MapperM (State s) a
stately mapper thing = do
......
......@@ -17,6 +17,7 @@ module Language.SystemVerilog.AST.Expr
, endianCondExpr
, endianCondRange
, sizedExpr
, dimensionsSize
) where
import Data.List (intercalate)
......@@ -209,3 +210,10 @@ sizedExpr x r (Number n) =
else size ++ n
Just num -> size ++ "'d" ++ show num
sizedExpr _ _ e = e
dimensionsSize :: [Range] -> Expr
dimensionsSize ranges =
simplify $
foldl (BinOp Mul) (Number "1") $
map rangeSize $
ranges
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment