Commit 1d79c279 by Zachary Snow

first half of interface conversion

parent 64a2610b
...@@ -14,6 +14,7 @@ import qualified Convert.AsgnOp ...@@ -14,6 +14,7 @@ import qualified Convert.AsgnOp
import qualified Convert.CaseKW import qualified Convert.CaseKW
import qualified Convert.Enum import qualified Convert.Enum
import qualified Convert.FuncRet import qualified Convert.FuncRet
import qualified Convert.Interface
import qualified Convert.Logic import qualified Convert.Logic
import qualified Convert.PackedArray import qualified Convert.PackedArray
import qualified Convert.Return import qualified Convert.Return
...@@ -28,6 +29,7 @@ type Phase = AST -> AST ...@@ -28,6 +29,7 @@ type Phase = AST -> AST
phases :: Target -> [Phase] phases :: Target -> [Phase]
phases YOSYS = phases YOSYS =
[ Convert.AsgnOp.convert [ Convert.AsgnOp.convert
, Convert.Interface.convert
, Convert.FuncRet.convert , Convert.FuncRet.convert
, Convert.Enum.convert , Convert.Enum.convert
, Convert.PackedArray.convert , Convert.PackedArray.convert
......
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- Conversion for interfaces
-}
module Convert.Interface (convert) where
import Data.Maybe (isJust)
import Control.Monad.Writer
import qualified Data.Map.Strict as Map
import Convert.Traverse
import Language.SystemVerilog.AST
type Instances = Map.Map Identifier Identifier
type Interface = ([Identifier], [ModuleItem])
type Interfaces = Map.Map Identifier Interface
type Modports = Map.Map Identifier [ModportDecl]
convert :: AST -> AST
convert descriptions =
filter (not . isInterface) $
traverseDescriptions (convertDescription interfaces) $
descriptions
where
interfaces = execWriter $ collectDescriptionsM collectDesc descriptions
collectDesc :: Description -> Writer Interfaces ()
collectDesc (Part Interface name ports items) =
tell $ Map.singleton name (ports, items)
collectDesc _ = return ()
isInterface :: Description -> Bool
isInterface (Part Interface _ _ _) = True
isInterface _ = False
-- TODO FIXME XXX: We should probably extract out/flatten the needless generate
-- blocks we make during covnersion...
convertDescription :: Interfaces -> Description -> Description
convertDescription interfaces (orig @ (Part Module name _ _)) =
Part Module name ports' items'
where
Part Module _ ports items = traverseModuleItems mapInstance orig
ports' = ports
items' = items
-- collect the interface type of all interface instances in this module
instances = execWriter $ collectModuleItemsM collectInstance orig
collectInstance :: ModuleItem -> Writer Instances ()
collectInstance (Instance part _ ident _) =
if Map.member part interfaces
then tell $ Map.singleton ident part
else return ()
collectInstance _ = return ()
-- TODO: We don't yet handle interfaces with parameter bindings.
mapInstance :: ModuleItem -> ModuleItem
mapInstance (Instance part params ident (Just instancePorts)) =
case Map.lookup part interfaces of
Just interface ->
Generate $ map GenModuleItem $
inlineInterface interface (ident, expandedPorts)
Nothing -> Instance part params ident (Just expandedPorts)
where expandedPorts = concatMap expandPortBinding instancePorts
mapInstance other = other
expandPortBinding :: PortBinding -> [PortBinding]
expandPortBinding (origBinding @ (portName, Just (Access (Ident instanceName) modportName))) =
case Map.lookup instanceName instances of
Nothing -> [origBinding]
Just interfaceName ->
map mapper modportDecls
where
modportDecls = lookupModport instanceName interfaceName modportName
mapper (_, x, me) = (portName ++ "_" ++ x, me)
expandPortBinding other = [other]
lookupModport :: Identifier -> Identifier -> Identifier -> [ModportDecl]
lookupModport instanceName interfaceName = (Map.!) modportMap
where
interfaceItems =
map (prefixModuleItems $ instanceName ++ "_") $
snd $ interfaces Map.! interfaceName
modportMap = execWriter $
mapM (collectNestedModuleItemsM collectModport) $
interfaceItems
collectModport :: ModuleItem -> Writer Modports ()
collectModport (Modport x l) = tell $ Map.singleton x l
collectModport _ = return ()
convertDescription _ other = other
-- add a prefix to all standard identifiers in a module item
prefixModuleItems :: Identifier -> ModuleItem -> ModuleItem
prefixModuleItems prefix =
traverseDecls prefixDecl .
traverseExprs prefixExpr .
traverseLHSs prefixLHS
where
prefixDecl :: Decl -> Decl
prefixDecl (Variable d t x a me) = Variable d t (prefix ++ x) a me
prefixDecl (Parameter t x e) = Parameter t (prefix ++ x) e
prefixDecl (Localparam t x e) = Localparam t (prefix ++ x) e
prefixExpr :: Expr -> Expr
prefixExpr (Ident x) = Ident (prefix ++ x)
prefixExpr other = other
prefixLHS :: LHS -> LHS
prefixLHS (LHSIdent x) = LHSIdent (prefix ++ x)
prefixLHS other = other
-- convert an interface instantiation into a series of equivalent module items
inlineInterface :: Interface -> (Identifier, [PortBinding]) -> [ModuleItem]
inlineInterface (ports, items) (instanceName, instancePorts) =
(:) (Comment $ "expanded instance: " ++ instanceName) $
(++) portBindings $
map (traverseNestedModuleItems removeModport) $
map (traverseNestedModuleItems removeMIDeclDir) $
map (prefixModuleItems prefix) $
items
where
prefix = instanceName ++ "_"
origInstancePortNames = map fst instancePorts
instancePortExprs = map snd instancePorts
instancePortNames =
map (prefix ++) $
if all ("" ==) origInstancePortNames
then ports
else origInstancePortNames
portBindings =
map (\(ident, Just expr) -> Assign (LHSIdent ident) expr) $
filter (isJust . snd) $
zip instancePortNames instancePortExprs
removeMIDeclDir :: ModuleItem -> ModuleItem
removeMIDeclDir (MIDecl (Variable _ t x a me)) =
MIDecl $ Variable Local t x a me
removeMIDeclDir other = other
removeModport :: ModuleItem -> ModuleItem
removeModport (Modport x _) = Comment $ "removed modport " ++ x
removeModport other = other
...@@ -18,7 +18,7 @@ convert descriptions = ...@@ -18,7 +18,7 @@ convert descriptions =
where where
modulePorts = execWriter $ collectDescriptionsM getPorts descriptions modulePorts = execWriter $ collectDescriptionsM getPorts descriptions
getPorts :: Description -> Writer (Map.Map Identifier [Identifier]) () getPorts :: Description -> Writer (Map.Map Identifier [Identifier]) ()
getPorts (Part Module name ports _) = tell $ Map.singleton name ports getPorts (Part _ name ports _) = tell $ Map.singleton name ports
getPorts _ = return () getPorts _ = return ()
mapInstance :: ModuleItem -> ModuleItem mapInstance :: ModuleItem -> ModuleItem
......
...@@ -39,6 +39,9 @@ module Convert.Traverse ...@@ -39,6 +39,9 @@ module Convert.Traverse
, traverseAsgnsM , traverseAsgnsM
, traverseAsgns , traverseAsgns
, collectAsgnsM , collectAsgnsM
, traverseNestedModuleItemsM
, traverseNestedModuleItems
, collectNestedModuleItemsM
, traverseNestedStmts , traverseNestedStmts
) where ) where
...@@ -284,10 +287,16 @@ traverseExprsM mapper = moduleItemMapper ...@@ -284,10 +287,16 @@ traverseExprsM mapper = moduleItemMapper
else do else do
l <- mapM portBindingMapper (fromJust ml) l <- mapM portBindingMapper (fromJust ml)
return $ Instance m params x (Just l) return $ Instance m params x (Just l)
moduleItemMapper (Modport x l) =
mapM modportDeclMapper l >>= return . Modport x
moduleItemMapper (Comment x) = return $ Comment x moduleItemMapper (Comment x) = return $ Comment x
moduleItemMapper (Genvar x) = return $ Genvar x moduleItemMapper (Genvar x) = return $ Genvar x
moduleItemMapper (Generate x) = return $ Generate x moduleItemMapper (Generate x) = return $ Generate x
moduleItemMapper (Modport x l) = return $ Modport x l
modportDeclMapper (dir, ident, Just e) = do
e' <- exprMapper e
return (dir, ident, Just e')
modportDeclMapper other = return other
traverseExprs :: Mapper Expr -> Mapper ModuleItem traverseExprs :: Mapper Expr -> Mapper ModuleItem
traverseExprs = unmonad traverseExprsM traverseExprs = unmonad traverseExprsM
...@@ -444,5 +453,16 @@ traverseAsgns = unmonad traverseAsgnsM ...@@ -444,5 +453,16 @@ traverseAsgns = unmonad traverseAsgnsM
collectAsgnsM :: Monad m => CollectorM m (LHS, Expr) -> CollectorM m ModuleItem collectAsgnsM :: Monad m => CollectorM m (LHS, Expr) -> CollectorM m ModuleItem
collectAsgnsM = collectify traverseAsgnsM collectAsgnsM = collectify traverseAsgnsM
traverseNestedModuleItemsM :: Monad m => MapperM m ModuleItem -> MapperM m ModuleItem
traverseNestedModuleItemsM mapper item = do
Part Module "DNE" [] [item'] <-
traverseModuleItemsM mapper (Part Module "DNE" [] [item])
return item'
traverseNestedModuleItems :: Mapper ModuleItem -> Mapper ModuleItem
traverseNestedModuleItems = unmonad traverseNestedModuleItemsM
collectNestedModuleItemsM :: Monad m => CollectorM m ModuleItem -> CollectorM m ModuleItem
collectNestedModuleItemsM = collectify traverseNestedModuleItemsM
traverseNestedStmts :: Mapper Stmt -> Mapper Stmt traverseNestedStmts :: Mapper Stmt -> Mapper Stmt
traverseNestedStmts = unmonad traverseNestedStmtsM traverseNestedStmts = unmonad traverseNestedStmtsM
...@@ -45,6 +45,7 @@ executable sv2v ...@@ -45,6 +45,7 @@ executable sv2v
Convert.CaseKW Convert.CaseKW
Convert.Enum Convert.Enum
Convert.FuncRet Convert.FuncRet
Convert.Interface
Convert.Logic Convert.Logic
Convert.PackedArray Convert.PackedArray
Convert.Return Convert.Return
......
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