interface conversion supports positional port bindings

- also fixes an issue where system tasks were inadvertently prefixed
  during the interface conversion
This commit is contained in:
Zachary Snow 2020-02-09 13:42:45 -05:00
parent 7a00c36a70
commit 8a008c3024
3 changed files with 50 additions and 15 deletions

View File

@ -6,6 +6,7 @@
module Convert.Interface (convert) where module Convert.Interface (convert) where
import Data.List (lookup)
import Data.Maybe (fromJust, mapMaybe) import Data.Maybe (fromJust, mapMaybe)
import Control.Monad.Writer import Control.Monad.Writer
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
@ -18,7 +19,7 @@ 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 [ModportDecl] type Modports = Map.Map Identifier [ModportDecl]
type Modules = Map.Map (Identifier, Identifier) Type type Modules = Map.Map Identifier [(Identifier, Type)]
convert :: [AST] -> [AST] convert :: [AST] -> [AST]
convert = convert =
@ -32,11 +33,13 @@ convert =
collectDesc (orig @ (Part _ False kw _ name ports items)) = do collectDesc (orig @ (Part _ False kw _ name ports items)) = do
if kw == Interface if kw == Interface
then tell (Map.singleton name (ports, items), Map.empty) then tell (Map.singleton name (ports, items), Map.empty)
else collectModuleItemsM (collectDeclsM collectDecl) orig else tell (Map.empty, Map.singleton name decls)
where where
collectDecl :: Decl -> Writer (Interfaces, Modules) () decls = execWriter $
collectModuleItemsM (collectDeclsM collectDecl) orig
collectDecl :: Decl -> Writer [(Identifier, Type)] ()
collectDecl (Variable _ t ident _ _) = collectDecl (Variable _ t ident _ _) =
tell (Map.empty, Map.singleton (name, ident) t) tell [(ident, t)]
collectDecl _ = return () collectDecl _ = return ()
collectDesc _ = return () collectDesc _ = return ()
isInterface :: Description -> Bool isInterface :: Description -> Bool
@ -95,7 +98,7 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
Generate $ map GenModuleItem $ Generate $ map GenModuleItem $
inlineInterface interface (ident, params, expandedPorts) inlineInterface interface (ident, params, expandedPorts)
Nothing -> Instance part params ident Nothing expandedPorts Nothing -> Instance part params ident Nothing expandedPorts
where expandedPorts = concatMap (expandPortBinding part) instancePorts where expandedPorts = concatMap (uncurry $ expandPortBinding part) (zip instancePorts [0..])
mapInterface (orig @ (MIPackageItem (Function _ _ _ decls _))) = mapInterface (orig @ (MIPackageItem (Function _ _ _ decls _))) =
convertTF decls orig convertTF decls orig
mapInterface (orig @ (MIPackageItem (Task _ _ decls _))) = mapInterface (orig @ (MIPackageItem (Task _ _ decls _))) =
@ -114,8 +117,8 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
declVarIdent (Variable _ _ x _ _) = Just x declVarIdent (Variable _ _ x _ _) = Just x
declVarIdent _ = Nothing declVarIdent _ = Nothing
expandPortBinding :: Identifier -> PortBinding -> [PortBinding] expandPortBinding :: Identifier -> PortBinding -> Int -> [PortBinding]
expandPortBinding _ (origBinding @ (portName, Just (Dot (Ident instanceName) modportName))) = expandPortBinding _ (origBinding @ (portName, Just (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 && modportDecls /= Nothing
then map mapper $ fromJust modportDecls then map mapper $ fromJust modportDecls
@ -128,18 +131,27 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
prefixExpr :: Expr -> Expr prefixExpr :: Expr -> Expr
prefixExpr (Ident x) = Ident (instanceName ++ "_" ++ x) prefixExpr (Ident x) = Ident (instanceName ++ "_" ++ x)
prefixExpr other = other prefixExpr other = other
expandPortBinding moduleName (origBinding @ (portName, Just (Ident ident))) = expandPortBinding moduleName (origBinding @ (portName, Just (Ident ident))) idx =
case (instances Map.!? ident, modports Map.!? ident) of case (instances Map.!? ident, modports Map.!? ident) of
(Nothing, Nothing) -> [origBinding] (Nothing, Nothing) -> [origBinding]
(Just _, _) -> (Just _, _) ->
-- given entire interface, but just bound to a modport -- given entire interface, but just bound to a modport
expandPortBinding moduleName (portName, Just newExpr) expandPortBinding moduleName (portName', Just newExpr) idx
where where
InterfaceT _ (Just modportName) [] = (portName', InterfaceT _ (Just modportName) []) =
case Map.lookup (moduleName, portName) modules of case (portName, Map.lookup moduleName modules) of
Just t -> t ("", Just decls) ->
Nothing -> error $ "could not find port " if idx < length decls
++ show portName ++ " in module " then decls !! idx
else error $ "could not infer port "
++ show origBinding ++ " in module "
++ show moduleName
(_, Just decls) -> case lookup portName decls of
Nothing -> error $ "could not find port "
++ show portName ++ " in module "
++ show moduleName
Just t -> (portName, t)
(_, Nothing) -> error $ "could not find module "
++ show moduleName ++ show moduleName
newExpr = Dot (Ident ident) modportName newExpr = Dot (Ident ident) modportName
(_, Just decls) -> (_, Just decls) ->
@ -149,7 +161,7 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
mapper (_, x, _) = mapper (_, x, _) =
( portName ++ "_" ++ x ( portName ++ "_" ++ x
, Just $ Dot (Ident ident) x ) , Just $ Dot (Ident ident) x )
expandPortBinding _ other = [other] expandPortBinding _ other _ = [other]
lookupModport :: Identifier -> Identifier -> Maybe [ModportDecl] lookupModport :: Identifier -> Identifier -> Maybe [ModportDecl]
lookupModport interfaceName = lookupModport interfaceName =
@ -200,6 +212,7 @@ prefixModuleItems prefix =
prefixDecl (ParamType s x mt) = ParamType s (prefix ++ x) mt prefixDecl (ParamType s x mt) = ParamType s (prefix ++ x) mt
prefixDecl (CommentDecl c) = CommentDecl c prefixDecl (CommentDecl c) = CommentDecl c
prefixExpr :: Expr -> Expr prefixExpr :: Expr -> Expr
prefixExpr (Ident ('$' : x)) = Ident $ '$' : x
prefixExpr (Ident x) = Ident (prefix ++ x) prefixExpr (Ident x) = Ident (prefix ++ x)
prefixExpr other = other prefixExpr other = other
prefixLHS :: LHS -> LHS prefixLHS :: LHS -> LHS

View File

@ -0,0 +1,14 @@
interface Interface;
logic x;
modport Modport(
input x
);
initial $display("Interface", x);
endinterface
module Module(Interface.Modport foo);
initial $display("Module", foo.x);
endmodule
module top;
Interface i();
Module m(i);
endmodule

View File

@ -0,0 +1,8 @@
module Module(input wire x);
initial $display("Module", x);
endmodule
module top;
wire i_x;
initial $display("Interface", i_x);
Module m(.x(i_x));
endmodule