Commit 8ae925d9 by Zachary Snow

support modports depending on other interface data declarations

parent 369af001
...@@ -91,24 +91,27 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po ...@@ -91,24 +91,27 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
mapInterface (orig @ (MIPackageItem (Decl (Variable _ t ident _ _)))) = mapInterface (orig @ (MIPackageItem (Decl (Variable _ t ident _ _)))) =
-- expand instantiation of a modport -- expand instantiation of a modport
case Map.lookup ident modports of case Map.lookup ident modports of
Just (_, modportDecls) -> Generate $ Just (_, modportDecls) -> Generate $ map GenModuleItem $
map (GenModuleItem . MIPackageItem . Decl) filter shouldKeep interfaceItems ++ map makePortDecl modportDecls
(parameterDecls ++ map mapper modportDecls)
Nothing -> orig Nothing -> orig
where where
interfaceName = case t of interfaceName = case t of
InterfaceT x (Just _) [] -> x InterfaceT x (Just _) [] -> x
Alias Nothing x [] -> x Alias Nothing x [] -> x
_ -> error $ "unexpected modport type " ++ show t _ -> error $ "unexpected modport type " ++ show t
interfaceItems = interfaceItems = prefixInterface ident $
case Map.lookup interfaceName interfaces of case Map.lookup interfaceName interfaces of
Just res -> snd res Just res -> snd res
Nothing -> error $ "could not find interface " ++ show interfaceName Nothing -> error $ "could not find interface " ++ show interfaceName
parameterDecls = map snd $ parameters interfaceItems shouldKeep (MIPackageItem (Decl Param{})) = True
mapper :: ModportDecl -> Decl shouldKeep (MIPackageItem Task{}) = True
mapper (dir, port, expr) = shouldKeep (MIPackageItem Function{}) = True
shouldKeep _ = False
makePortDecl :: ModportDecl -> ModuleItem
makePortDecl (dir, port, expr) =
MIPackageItem $ Decl $
Variable dir mpt (ident ++ "_" ++ port) mprs Nil Variable dir mpt (ident ++ "_" ++ port) mprs Nil
where (mpt, mprs) = lookupType interfaceItems expr where (mpt, mprs) = lookupType interfaceItems ident expr
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
...@@ -149,6 +152,15 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po ...@@ -149,6 +152,15 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
declVarIdent _ = "" declVarIdent _ = ""
expandPortBinding :: Identifier -> PortBinding -> Int -> ([ParamBinding], [PortBinding]) expandPortBinding :: Identifier -> PortBinding -> Int -> ([ParamBinding], [PortBinding])
expandPortBinding moduleName ("", binding) idx =
case Map.lookup moduleName modules of
Nothing -> error $ "could not find module: " ++ moduleName
Just (_, decls) ->
if idx < length decls
then expandPortBinding moduleName
(fst $ decls !! idx, binding) idx
else error $ "could not infer port for "
++ 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 && modportDecls /= Nothing
...@@ -158,7 +170,7 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po ...@@ -158,7 +170,7 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
where where
interfaceName = instances Map.! instanceName interfaceName = instances Map.! instanceName
modportDecls = lookupModport interfaceName modportName modportDecls = lookupModport interfaceName modportName
expandPortBinding moduleName (origBinding @ (portName, Ident ident)) idx = 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])
(Just interfaceName, _) -> (Just interfaceName, _) ->
...@@ -173,13 +185,7 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po ...@@ -173,13 +185,7 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
where where
Just (_, decls) = Map.lookup moduleName modules Just (_, decls) = Map.lookup moduleName modules
portType = portType =
if null portName case lookup portName decls of
then if idx < length decls
then snd $ decls !! idx
else error $ "could not infer port "
++ show origBinding ++ " in module "
++ show moduleName
else case lookup portName decls of
Nothing -> error $ "could not find port " Nothing -> error $ "could not find port "
++ show portName ++ " in module " ++ show portName ++ " in module "
++ show moduleName ++ show moduleName
...@@ -206,11 +212,11 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po ...@@ -206,11 +212,11 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
paramBindings = map toParamBinding interfaceParamNames paramBindings = map toParamBinding interfaceParamNames
interfaceItems = snd $ interfaces Map.! interfaceName interfaceItems = snd $ interfaces Map.! interfaceName
interfaceParamNames = map fst $ parameters interfaceItems interfaceParamNames = map fst $ parameters interfaceItems
toParamBinding x = (x, Right $ Ident $ instanceName ++ '_' : x) toParamBinding x = (portName ++ '_' : x, Right $ Ident $ instanceName ++ '_' : x)
portBindings = map toPortBinding modportDecls portBindings = map toPortBinding modportDecls
toPortBinding (_, x, e) = (x', e') toPortBinding (_, x, e) = (x', e')
where where
x' = if null portName then "" else portName ++ '_' : x x' = portName ++ '_' : x
e' = traverseNestedExprs prefixExpr e e' = traverseNestedExprs prefixExpr e
prefixExpr :: Expr -> Expr prefixExpr :: Expr -> Expr
prefixExpr (Ident x) = Ident (instanceName ++ '_' : x) prefixExpr (Ident x) = Ident (instanceName ++ '_' : x)
...@@ -318,17 +324,17 @@ collectIdentsM item = collectDeclsM collectDecl item ...@@ -318,17 +324,17 @@ 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 ()
lookupType :: [ModuleItem] -> Expr -> (Type, [Range]) lookupType :: [ModuleItem] -> Identifier -> Expr -> (Type, [Range])
lookupType items (Ident ident) = lookupType items prefix (Ident ident) =
case mapMaybe findType items of case mapMaybe findType items of
[] -> error $ "unable to locate type of " ++ ident [] -> error $ "unable to locate type of " ++ ident
ts -> head ts ts -> head ts
where where
findType :: ModuleItem -> Maybe (Type, [Range]) findType :: ModuleItem -> Maybe (Type, [Range])
findType (MIPackageItem (Decl (Variable _ t x rs _))) = findType (MIPackageItem (Decl (Variable _ t x rs _))) =
if x == ident then Just (t, rs) else Nothing if x == prefix ++ "_" ++ ident then Just (t, rs) else Nothing
findType _ = Nothing findType _ = Nothing
lookupType _ expr = lookupType _ _ expr =
-- TODO: Add support for non-Ident modport expressions. -- TODO: Add support for non-Ident modport expressions.
error $ "interface conversion does not support modport expressions that " error $ "interface conversion does not support modport expressions that "
++ " are not identifiers: " ++ show expr ++ " are not identifiers: " ++ show expr
...@@ -345,17 +351,9 @@ inlineInterface (ports, items) (instanceName, instanceParams, instancePorts) = ...@@ -345,17 +351,9 @@ inlineInterface (ports, items) (instanceName, instanceParams, instancePorts) =
comment = MIPackageItem $ Decl $ CommentDecl $ comment = MIPackageItem $ Decl $ CommentDecl $
"expanded instance: " ++ instanceName "expanded instance: " ++ instanceName
prefix = instanceName ++ "_" prefix = instanceName ++ "_"
idents = execWriter $
mapM (collectNestedModuleItemsM collectIdentsM) items
prefixIfNecessary :: Identifier -> Identifier
prefixIfNecessary x =
if Set.member x idents
then prefix ++ x
else x
itemsPrefixed = itemsPrefixed =
map (traverseNestedModuleItems $ prefixModuleItems prefixIfNecessary) $
map (traverseDecls overrideParam) $ map (traverseDecls overrideParam) $
items prefixInterface instanceName items
origInstancePortNames = map fst instancePorts origInstancePortNames = map fst instancePorts
instancePortExprs = map snd instancePorts instancePortExprs = map snd instancePorts
instancePortNames = instancePortNames =
...@@ -377,7 +375,7 @@ inlineInterface (ports, items) (instanceName, instanceParams, instancePorts) = ...@@ -377,7 +375,7 @@ inlineInterface (ports, items) (instanceName, instanceParams, instancePorts) =
removeModport other = other removeModport other = other
interfaceParamNames = map fst $ parameters items interfaceParamNames = map fst $ parameters items
instanceParamMap = instanceParamMap = Map.mapKeys (prefix ++) $
Map.fromList $ resolveParams interfaceParamNames instanceParams Map.fromList $ resolveParams interfaceParamNames instanceParams
overrideParam :: Decl -> Decl overrideParam :: Decl -> Decl
overrideParam (Param Parameter t x e) = overrideParam (Param Parameter t x e) =
...@@ -419,6 +417,22 @@ inlineInterface (ports, items) (instanceName, instanceParams, instancePorts) = ...@@ -419,6 +417,22 @@ inlineInterface (ports, items) (instanceName, instanceParams, instancePorts) =
Nothing -> error $ "trying to bind an interface output to " ++ Nothing -> error $ "trying to bind an interface output to " ++
show expr ++ " but that can't be an LHS" show expr ++ " but that can't be an LHS"
-- convert an interface instantiation into a series of equivalent module items
prefixInterface :: Identifier -> [ModuleItem] -> [ModuleItem]
prefixInterface instanceName items =
map prefixItem items
where
prefix = instanceName ++ "_"
idents = execWriter $
mapM (collectNestedModuleItemsM collectIdentsM) items
prefixIfNecessary :: Identifier -> Identifier
prefixIfNecessary x =
if Set.member x idents
then prefix ++ x
else x
prefixItem = traverseNestedModuleItems $
prefixModuleItems prefixIfNecessary
-- give a set of param bindings explicit names -- give a set of param bindings explicit names
resolveParams :: [Identifier] -> [ParamBinding] -> [ParamBinding] resolveParams :: [Identifier] -> [ParamBinding] -> [ParamBinding]
resolveParams available bindings = resolveParams available bindings =
......
interface I; interface I;
parameter WIDTH = 32; parameter WIDTH = 32;
logic [WIDTH-1:0] data = 0; function compute_offset;
return 1;
endfunction
localparam OFFSET = compute_offset();
logic [WIDTH-OFFSET:0] data = 0;
modport P(input data); modport P(input data);
endinterface endinterface
......
...@@ -2,7 +2,8 @@ module M(data); ...@@ -2,7 +2,8 @@ module M(data);
parameter A = 1; parameter A = 1;
parameter WIDTH = 32; parameter WIDTH = 32;
parameter B = 2; parameter B = 2;
input wire [WIDTH-1:0] data; localparam OFFSET = 1;
input wire [WIDTH-OFFSET:0] data;
initial begin initial begin
$display("A %b", A); $display("A %b", A);
$display("I.P %b", data); $display("I.P %b", data);
......
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