Commit 4bebb85c by Zachary Snow

refactor interface conversion

parent aca24ebe
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
module Convert.Interface (convert) where module Convert.Interface (convert) where
import Data.Maybe (fromJust, mapMaybe) import Data.Maybe (mapMaybe)
import Control.Monad.Writer import Control.Monad.Writer
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import qualified Data.Set as Set import qualified Data.Set as Set
...@@ -14,11 +14,12 @@ import qualified Data.Set as Set ...@@ -14,11 +14,12 @@ import qualified Data.Set as Set
import Convert.Traverse import Convert.Traverse
import Language.SystemVerilog.AST import Language.SystemVerilog.AST
type Instances = Map.Map Identifier Identifier
type Interface = ([Identifier], [ModuleItem]) type Interface = ([Identifier], [ModuleItem])
type Interfaces = Map.Map Identifier Interface type Interfaces = Map.Map Identifier Interface
type Modports = Map.Map Identifier (Identifier, [ModportDecl]) type Module = ([Identifier], [(Identifier, Type)])
type Modules = Map.Map Identifier ([Identifier], [(Identifier, Type)]) type Modules = Map.Map Identifier Module
type Instances = Map.Map Identifier Identifier
type Modports = Map.Map Identifier (Identifier, Identifier)
convert :: [AST] -> [AST] convert :: [AST] -> [AST]
convert = convert =
...@@ -80,54 +81,54 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po ...@@ -80,54 +81,54 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
-- collect the interface type of all interface instances in this module -- collect the interface type of all interface instances in this module
(instances, modports) = execWriter $ mapM (instances, modports) = execWriter $ mapM
(collectNestedModuleItemsM collectInterface) items (collectNestedModuleItemsM collectInstanceM) items
collectInterface :: ModuleItem -> Writer (Instances, Modports) () collectInstanceM :: ModuleItem -> Writer (Instances, Modports) ()
collectInterface (MIPackageItem (Decl (Variable _ t ident _ _))) = collectInstanceM (MIPackageItem (Decl (Variable _ t ident _ _))) =
case t of case t of
InterfaceT interfaceName (Just modportName) [] -> InterfaceT interfaceName (Just modportName) [] ->
if Map.member interfaceName interfaces if Map.member interfaceName interfaces
then tell (Map.empty, Map.singleton ident (interfaceName, modportDecls)) then writeModport interfaceName modportName
else return () else return ()
where Just modportDecls = lookupModport interfaceName modportName
Alias Nothing interfaceName [] -> Alias Nothing interfaceName [] ->
case impliedModport interfaceName of if Map.member interfaceName interfaces
Just modportDecls -> then writeModport interfaceName ""
tell (Map.empty, Map.singleton ident modport) else return ()
where modport = (interfaceName, modportDecls)
Nothing -> return ()
_ -> return () _ -> return ()
collectInterface (Instance part _ ident [] _) = where
writeModport :: Identifier -> Identifier ->
Writer (Instances, Modports) ()
writeModport interfaceName modportName =
tell (Map.empty, Map.singleton ident modport)
where modport = (interfaceName, modportName)
collectInstanceM (Instance part _ ident [] _) =
if Map.member part interfaces if Map.member part interfaces
then tell (Map.singleton ident part, Map.empty) then tell (Map.singleton ident part, Map.empty)
else return () else return ()
collectInterface _ = return () collectInstanceM _ = return ()
mapInterface :: ModuleItem -> ModuleItem mapInterface :: ModuleItem -> ModuleItem
mapInterface (orig @ (MIPackageItem (Decl (Variable _ t ident _ _)))) = mapInterface (orig @ (MIPackageItem (Decl (Variable _ _ ident _ _)))) =
-- expand instantiation of a modport -- expand instantiation of a modport
case Map.lookup ident modports of if Map.member ident modports
Just (_, modportDecls) -> Generate $ map GenModuleItem $ then Generate $ map GenModuleItem $
filter shouldKeep interfaceItems ++ map makePortDecl filter shouldKeep interfaceItems ++ map makePortDecl
(prefixModportDecls ident modportDecls) modportDecls
Nothing -> orig else orig
where where
interfaceName = case t of Just (interfaceName, modportName) = Map.lookup ident modports
InterfaceT x (Just _) [] -> x
Alias Nothing x [] -> x
_ -> error $ "unexpected modport type " ++ show t
interfaceItems = prefixInterface ident $ interfaceItems = prefixInterface ident $
case Map.lookup interfaceName interfaces of snd $ lookupInterface interfaceName
Just res -> snd res modportDecls = lookupModport interfaceItems modportName
Nothing -> error $ "could not find interface " ++ show interfaceName
shouldKeep (MIPackageItem (Decl Param{})) = True shouldKeep (MIPackageItem (Decl Param{})) = True
shouldKeep (MIPackageItem Task{}) = True shouldKeep (MIPackageItem Task{}) = True
shouldKeep (MIPackageItem Function{}) = True shouldKeep (MIPackageItem Function{}) = True
shouldKeep _ = False shouldKeep _ = False
makePortDecl :: ModportDecl -> ModuleItem makePortDecl :: ModportDecl -> ModuleItem
makePortDecl (dir, port, typ, _) = makePortDecl (dir, port, typ, _) =
MIPackageItem $ Decl $ MIPackageItem $ Decl $ Variable dir typ port' [] Nil
Variable dir mpt (ident ++ "_" ++ port) mprs Nil where port' = if null modportName
where (mpt, mprs) = (typ, []) then port
else ident ++ '_' : port
mapInterface (Instance part params ident [] instancePorts) = mapInterface (Instance part params ident [] instancePorts) =
-- expand modport port bindings -- expand modport port bindings
case Map.lookup part interfaces of case Map.lookup part interfaces of
...@@ -179,13 +180,14 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po ...@@ -179,13 +180,14 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
++ show binding ++ " in module " ++ show moduleName ++ show binding ++ " in module " ++ show moduleName
expandPortBinding _ (origBinding @ (portName, Dot (Ident instanceName) modportName)) _ = expandPortBinding _ (origBinding @ (portName, Dot (Ident instanceName) modportName)) _ =
-- expand instance modport bound to a modport -- expand instance modport bound to a modport
if Map.member instanceName instances && modportDecls /= Nothing if Map.member instanceName instances
then expandPortBinding' interfaceName portName instanceName then expandPortBinding' interfaceName portName instanceName
(fromJust modportDecls) modportDecls
else ([], [origBinding]) else ([], [origBinding])
where where
interfaceName = instances Map.! instanceName interfaceName = instances Map.! instanceName
modportDecls = lookupModport interfaceName modportName interfaceItems = snd $ lookupInterface interfaceName
modportDecls = lookupModport interfaceItems modportName
expandPortBinding moduleName (origBinding @ (portName, Ident ident)) _ = expandPortBinding moduleName (origBinding @ (portName, Ident ident)) _ =
case (instances Map.!? ident, modports Map.!? ident) of case (instances Map.!? ident, modports Map.!? ident) of
(Nothing, Nothing) -> ([], [origBinding]) (Nothing, Nothing) -> ([], [origBinding])
...@@ -193,11 +195,9 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po ...@@ -193,11 +195,9 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
-- given entire interface, but just bound to a modport -- given entire interface, but just bound to a modport
if Map.notMember moduleName modules then if Map.notMember moduleName modules then
error $ "could not find module " ++ show moduleName error $ "could not find module " ++ show moduleName
else if modportDecls == Nothing then
([], [origBinding])
else else
expandPortBinding' interfaceName portName ident expandPortBinding' interfaceName portName ident
(fromJust modportDecls) modportDecls
where where
Just (_, decls) = Map.lookup moduleName modules Just (_, decls) = Map.lookup moduleName modules
portType = portType =
...@@ -206,18 +206,22 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po ...@@ -206,18 +206,22 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
++ show portName ++ " in module " ++ show portName ++ " in module "
++ show moduleName ++ show moduleName
Just t -> t Just t -> t
modportDecls = interfaceItems = snd $ lookupInterface interfaceName
case portType of modportDecls = lookupModport interfaceItems modportName
InterfaceT _ (Just modportName) [] -> modportName = case portType of
lookupModport interfaceName modportName InterfaceT _ (Just x) [] -> x
Alias Nothing _ [] -> Alias Nothing _ [] -> ""
impliedModport interfaceName _ -> error $ "can't deduce modport for interface "
_ -> Nothing ++ interfaceName ++ " bound to port "
(_, Just (interfaceName, modportDecls)) -> ++ portName ++ " of module " ++ moduleName
(_, Just (interfaceName, modportName)) ->
-- modport directly bound to a modport -- modport directly bound to a modport
expandPortBinding' interfaceName portName ident expandPortBinding' interfaceName portName ident
(map redirect modportDecls) (map redirect modportDecls)
where redirect (d, x, t, _) = (d, x, t, Ident x) where
interfaceItems = snd $ lookupInterface interfaceName
modportDecls = lookupModport interfaceItems modportName
redirect (d, x, t, _) = (d, x, t, Ident x)
expandPortBinding _ other _ = ([], [other]) expandPortBinding _ other _ = ([], [other])
expandPortBinding' :: Identifier -> Identifier -> Identifier -> expandPortBinding' :: Identifier -> Identifier -> Identifier ->
...@@ -226,7 +230,7 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po ...@@ -226,7 +230,7 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
(paramBindings, portBindings) (paramBindings, portBindings)
where where
paramBindings = map toParamBinding interfaceParamNames paramBindings = map toParamBinding interfaceParamNames
interfaceItems = snd $ interfaces Map.! interfaceName interfaceItems = snd $ lookupInterface interfaceName
interfaceParamNames = map fst $ parameters interfaceItems interfaceParamNames = map fst $ parameters interfaceItems
toParamBinding x = (portName ++ '_' : x, Right $ Ident $ instanceName ++ '_' : x) toParamBinding x = (portName ++ '_' : x, Right $ Ident $ instanceName ++ '_' : x)
portBindings = map toPortBinding modportDecls portBindings = map toPortBinding modportDecls
...@@ -238,13 +242,19 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po ...@@ -238,13 +242,19 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
prefixExpr (Ident x) = Ident (instanceName ++ '_' : x) prefixExpr (Ident x) = Ident (instanceName ++ '_' : x)
prefixExpr other = other prefixExpr other = other
lookupModport :: Identifier -> Identifier -> Maybe [ModportDecl] lookupInterface :: Identifier -> Interface
lookupModport interfaceName = lookupInterface interfaceName =
if Map.member interfaceName interfaces case Map.lookup interfaceName interfaces of
then (Map.!?) modportMap Just res -> res
else error $ "could not find interface " ++ show interfaceName Nothing -> error $ "could not find interface " ++ show interfaceName
lookupModport :: [ModuleItem] -> Identifier -> [ModportDecl]
lookupModport interfaceItems "" = impliedModport interfaceItems
lookupModport interfaceItems modportName =
case Map.lookup modportName modportMap of
Just modportDecls -> modportDecls
Nothing -> error $ "could not find modport " ++ show modportName
where where
interfaceItems = snd $ interfaces Map.! interfaceName
modportMap = execWriter $ modportMap = execWriter $
mapM (collectNestedModuleItemsM collectModport) $ mapM (collectNestedModuleItemsM collectModport) $
interfaceItems interfaceItems
...@@ -252,16 +262,10 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po ...@@ -252,16 +262,10 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
collectModport (Modport ident l) = tell $ Map.singleton ident l collectModport (Modport ident l) = tell $ Map.singleton ident l
collectModport _ = return () collectModport _ = return ()
impliedModport :: Identifier -> Maybe [ModportDecl] impliedModport :: [ModuleItem] -> [ModportDecl]
impliedModport interfaceName = impliedModport =
if Map.member interfaceName interfaces execWriter . mapM (collectNestedModuleItemsM collectModportDecls)
then Just modport
else Nothing
where where
interfaceItems = snd $ interfaces Map.! interfaceName
modport = execWriter $
mapM (collectNestedModuleItemsM collectModportDecls) $
interfaceItems
collectModportDecls :: ModuleItem -> Writer [ModportDecl] () collectModportDecls :: ModuleItem -> Writer [ModportDecl] ()
collectModportDecls (MIPackageItem (Decl (Variable d t x _ _))) = collectModportDecls (MIPackageItem (Decl (Variable d t x _ _))) =
tell [(d', x, t, Ident x)] tell [(d', x, t, Ident x)]
...@@ -284,8 +288,12 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po ...@@ -284,8 +288,12 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
convertPort ident = convertPort ident =
case Map.lookup ident modports of case Map.lookup ident modports of
Nothing -> [ident] Nothing -> [ident]
Just (_, decls) -> map (\(_, x, _, _) -> Just (interfaceName, modportName) ->
ident ++ "_" ++ x) decls map (\(_, x, _, _) ->
ident ++ "_" ++ x) modportDecls
where
interfaceItems = snd $ lookupInterface interfaceName
modportDecls = lookupModport interfaceItems modportName
convertDescription _ _ other = other convertDescription _ _ other = other
...@@ -341,24 +349,6 @@ collectIdentsM item = collectDeclsM collectDecl item ...@@ -341,24 +349,6 @@ collectIdentsM item = collectDeclsM collectDecl item
collectDecl (ParamType _ x _) = tell $ Set.singleton x collectDecl (ParamType _ x _) = tell $ Set.singleton x
collectDecl (CommentDecl _) = return () collectDecl (CommentDecl _) = return ()
-- add a prefix to the expressions in a modport definition
prefixModportDecls :: Identifier -> [ModportDecl] -> [ModportDecl]
prefixModportDecls name modportDecls =
map mapper modportDecls
where
mapper :: ModportDecl -> ModportDecl
mapper (d, x, t, e) = (d, x, t', e')
where
exprMapper = traverseNestedExprs prefixExpr
t' = traverseNestedTypes (traverseTypeExprs exprMapper) t
e' = exprMapper e
prefix :: Identifier -> Identifier
prefix = (++) $ name ++ "_"
prefixExpr :: Expr -> Expr
prefixExpr (Ident ('$' : x)) = Ident $ '$' : x
prefixExpr (Ident x) = Ident (prefix x)
prefixExpr other = other
-- convert an interface instantiation into a series of equivalent module items -- convert an interface instantiation into a series of equivalent module items
inlineInterface :: Interface -> (Identifier, [ParamBinding], [PortBinding]) -> [ModuleItem] inlineInterface :: Interface -> (Identifier, [ParamBinding], [PortBinding]) -> [ModuleItem]
inlineInterface (ports, items) (instanceName, instanceParams, instancePorts) = inlineInterface (ports, items) (instanceName, instanceParams, instancePorts) =
......
...@@ -52,8 +52,7 @@ convert = ...@@ -52,8 +52,7 @@ convert =
lookupDir portName = lookupDir portName =
case lookup portName dirs of case lookup portName dirs of
Just dir -> dir Just dir -> dir
Nothing -> error $ "Could not find dir for port " ++ Nothing -> Inout
portName ++ " in module " ++ name
collectPortsM _ = return () collectPortsM _ = return ()
collectDeclDirsM :: ModuleItem -> Writer [(Identifier, Direction)] () collectDeclDirsM :: ModuleItem -> Writer [(Identifier, Direction)] ()
collectDeclDirsM (MIPackageItem (Decl (Variable dir t ident _ _))) = collectDeclDirsM (MIPackageItem (Decl (Variable dir t ident _ _))) =
......
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