Commit 8e1693d3 by Zachary Snow

yosys-compatible unbased unsized binding conversion

parent 21ebbb5a
{-# LANGUAGE PatternSynonyms #-} {-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE TupleSections #-}
{- sv2v {- sv2v
- Author: Zachary Snow <zach@zachjs.com> - Author: Zachary Snow <zach@zachjs.com>
- -
...@@ -6,116 +7,133 @@ ...@@ -6,116 +7,133 @@
- -
- The literals are given a binary base, a size of 1, and are made signed to - The literals are given a binary base, a size of 1, and are made signed to
- allow sign extension. For context-determined expressions, the converted - allow sign extension. For context-determined expressions, the converted
- literals are explicitly cast to the appropriate context-determined size. - literals are repeated to match the context-determined size.
- -
- As a special case, unbased, unsized literals which take on the size of a - As a special case, unbased, unsized literals which take on the size of a
- module port binding are replaced with a hierarchical reference to an - module's port are replaced as above, but with the size of the port being
- appropriately sized constant which is injected into the instantiated module's - determined based on the parameter bindings of the instance and the definition
- definition. This allows these literals to be used for parameterized ports - of the instantiated module.
- without further complicating other conversions, as hierarchical references
- are not allowed within constant expressions.
-} -}
module Convert.UnbasedUnsized (convert) where module Convert.UnbasedUnsized (convert) where
import Control.Monad.Writer import Control.Monad.Writer
import Data.Maybe (catMaybes)
import qualified Data.Map.Strict as Map
import Convert.ExprUtils
import Convert.Traverse import Convert.Traverse
import Language.SystemVerilog.AST import Language.SystemVerilog.AST
type Part = ([Identifier], [ModuleItem])
type Parts = Map.Map Identifier Part
data ExprContext data ExprContext
= SelfDetermined = SelfDetermined
| ContextDetermined Expr | ContextDetermined Expr
deriving (Eq, Show) deriving (Eq, Show)
type Port = Either Identifier Int
data Bind = Bind
{ bModule :: Identifier
, bBit :: Char
, bPort :: Port
} deriving (Eq, Show)
type Binds = [Bind]
convert :: [AST] -> [AST] convert :: [AST] -> [AST]
convert files = convert files =
map (traverseDescriptions $ convertDescription binds) files' map (traverseDescriptions convertDescription) files
where where
(files', binds) = runWriter $ parts = execWriter $ mapM (collectDescriptionsM collectPartsM) files
mapM (mapM $ traverseModuleItemsM convertModuleItemM) files convertDescription = traverseModuleItems $ convertModuleItem parts
convertDescription :: Binds -> Description -> Description collectPartsM :: Description -> Writer Parts ()
convertDescription [] other = other collectPartsM (Part _ _ _ _ name ports items) =
convertDescription binds (Part attrs extern kw lifetime name ports items) = tell $ Map.singleton name (ports, items)
Part attrs extern kw lifetime name ports items' collectPartsM _ = return ()
convertModuleItem :: Parts -> ModuleItem -> ModuleItem
convertModuleItem parts (Instance moduleName params instanceName [] bindings) =
convertModuleItem' $ Instance moduleName params instanceName [] bindings'
where where
binds' = filter ((== name) . bModule) binds bindings' = zipWith convertBinding bindings [0..]
items' = removeDupes [] $ items ++ map (bindItem ports) binds' (portNames, moduleItems) =
removeDupes :: [Identifier] -> [ModuleItem] -> [ModuleItem] case Map.lookup moduleName parts of
removeDupes _ [] = [] Nothing -> error $ "could not find module: " ++ moduleName
removeDupes existing (item @ (MIPackageItem (Decl decl)) : is) = Just partInfo -> partInfo
case decl of tag = Ident "~~uub~~"
Param Localparam _ x _ -> convertBinding :: PortBinding -> Int -> PortBinding
if elem x existing convertBinding (portName, expr) idx =
then removeDupes existing is (portName, ) $
else item : removeDupes (x : existing) is traverseNestedExprs (replaceBindingExpr portName idx) $
_ -> item : removeDupes existing is convertExpr (ContextDetermined tag) expr
removeDupes existing (item : is) = replaceBindingExpr :: Identifier -> Int -> Expr -> Expr
item : removeDupes existing is replaceBindingExpr portName idx (orig @ (Repeat _ [ConvertedUU a b])) =
convertDescription _ other = other if orig == sizedLiteralFor tag ch
then Repeat portSize [ConvertedUU a b]
bindName :: Bind -> Identifier else orig
bindName (Bind _ ch (Left x)) = "sv2v_uub_" ++ ch : '_' : x
bindName (Bind m ch (Right i)) =
bindName $ Bind m ch (Left $ show i)
bindItem :: [Identifier] -> Bind -> ModuleItem
bindItem ports bind =
MIPackageItem $ Decl $ Param Localparam typ name expr
where where
portName = lookupPort ports (bPort bind) ch = charForBit a b
size = DimsFn FnBits $ Right $ Ident portName portName' =
rng = (BinOp Sub size (RawNum 1), RawNum 0) if null portName
typ = Implicit Unspecified [rng] then lookupBindingName portNames idx
name = bindName bind else portName
expr = literalFor $ bBit bind portSize = determinePortSize portName' params moduleItems
replaceBindingExpr _ _ other = other
lookupPort :: [Identifier] -> Port -> Identifier convertModuleItem _ other = convertModuleItem' other
lookupPort _ (Left x) = x
lookupPort ports (Right i) = determinePortSize :: Identifier -> [ParamBinding] -> [ModuleItem] -> Expr
if i < length ports determinePortSize portName instanceParams moduleItems =
then ports !! i step initialMapping moduleItems
else error $ "out of bounds bort binding " ++ show (ports, i)
convertModuleItemM :: ModuleItem -> Writer Binds ModuleItem
convertModuleItemM (Instance moduleName params instanceName [] bindings) = do
bindings' <- mapM (uncurry convertBinding) $ zip bindings [0..]
let item = Instance moduleName params instanceName [] bindings'
return $ convertModuleItem item
where where
tag = Ident ":uub:" moduleParams = parameterNames moduleItems
convertBinding :: PortBinding -> Int -> Writer Binds PortBinding initialMapping = catMaybes $
convertBinding (portName, expr) idx = do zipWith createParamReplacement instanceParams [0..]
let port = if null portName then Right idx else Left portName createParamReplacement
let expr' = convertExpr (ContextDetermined tag) expr :: ParamBinding -> Int -> Maybe (Identifier, Expr)
expr'' <- traverseNestedExprsM (replaceBindingExpr port) expr' createParamReplacement ("", b) idx =
return (portName, expr'') createParamReplacement (paramName, b) idx
replaceBindingExpr :: Port -> Expr -> Writer Binds Expr where paramName = lookupBindingName moduleParams idx
replaceBindingExpr port (orig @ (Repeat _ [ConvertedUU a b])) = do createParamReplacement (_, Left _) _ = Nothing
let ch = charForBit a b createParamReplacement (paramName, Right expr) _ =
if orig == sizedLiteralFor tag ch Just (paramName, tagExpr expr)
then do
let bind = Bind moduleName ch port step :: [(Identifier, Expr)] -> [ModuleItem] -> Expr
tell [bind] step mapping (MIPackageItem (Decl (Param _ _ x e)) : rest) =
let expr = Dot (Ident instanceName) (bindName bind) step (mapping ++ [(x, e)]) rest
return expr step mapping (MIPackageItem (Decl (Variable _ t x a _)) : rest) =
else return orig if x == portName
replaceBindingExpr _ other = return other then substituteExpr mapping size
convertModuleItemM other = return $ convertModuleItem other else step mapping rest
where size = BinOp Mul (dimensionsSize a) (DimsFn FnBits $ Left t)
convertModuleItem :: ModuleItem -> ModuleItem step mapping (_ : rest) = step mapping rest
convertModuleItem = step _ [] = error $ "could not find size of port " ++ portName
substituteExpr :: [(Identifier, Expr)] -> Expr -> Expr
substituteExpr _ (Ident (':' : x)) =
Ident x
substituteExpr mapping (Ident x) =
case lookup x mapping of
Nothing -> Ident x
Just expr -> substituteExpr mapping expr
substituteExpr mapping expr =
traverseSinglyNestedExprs (substituteExpr mapping) expr
tagExpr :: Expr -> Expr
tagExpr (Ident x) = Ident (':' : x)
tagExpr expr = traverseSinglyNestedExprs tagExpr expr
-- given a list of module items, produces the parameter names in order
parameterNames :: [ModuleItem] -> [Identifier]
parameterNames =
execWriter . mapM (collectNestedModuleItemsM $ collectDeclsM collectDeclM)
where
collectDeclM :: Decl -> Writer [Identifier] ()
collectDeclM (Param Parameter _ x _) = tell [x]
collectDeclM (ParamType Parameter x _) = tell [x]
collectDeclM _ = return ()
lookupBindingName :: [Identifier] -> Int -> Identifier
lookupBindingName names idx =
if idx < length names
then names !! idx
else error $ "out of bounds binding " ++ show (names, idx)
convertModuleItem' :: ModuleItem -> ModuleItem
convertModuleItem' =
traverseExprs (convertExpr SelfDetermined) . traverseExprs (convertExpr SelfDetermined) .
traverseTypes (traverseNestedTypes convertType) . traverseTypes (traverseNestedTypes convertType) .
traverseAsgns convertAsgn traverseAsgns convertAsgn
......
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