Commit eae46b7a by Zachary Snow

improved interface modport type checking

parent 68fa8290
...@@ -24,7 +24,7 @@ data PartInfo = PartInfo ...@@ -24,7 +24,7 @@ data PartInfo = PartInfo
} }
type PartInfos = Map.Map Identifier PartInfo type PartInfos = Map.Map Identifier PartInfo
type ModportInstances = [(Identifier, Identifier)] type ModportInstances = [(Identifier, (Identifier, Identifier))]
type ModportBinding = (Identifier, (Substitutions, Expr)) type ModportBinding = (Identifier, (Substitutions, Expr))
type Substitutions = [(Expr, Expr)] type Substitutions = [(Expr, Expr)]
...@@ -197,19 +197,41 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -197,19 +197,41 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
else if bindingIsBundle && not portIsBundle then else if bindingIsBundle && not portIsBundle then
-- given entire interface, but just bound to a modport -- given entire interface, but just bound to a modport
foundModport $ Dot expr modportName foundModport $ Dot expr modportName
else if modportInstance /= Nothing then
error $ "could not resolve modport binding " ++ show expr
++ " for port " ++ portName ++ " of type "
++ showModportType interfaceName modportName
else else
Nothing Nothing
where where
bindingIsModport = lookupIntfElem modports expr /= Nothing bindingIsModport = lookupIntfElem modports expr /= Nothing
bindingIsBundle = lookupIntfElem modports (Dot expr "") /= Nothing bindingIsBundle = lookupIntfElem modports (Dot expr "") /= Nothing
portIsBundle = null modportName portIsBundle = null modportName
modportName = case lookup portName modportInstances of modportInstance = lookup portName modportInstances
(interfaceName, modportName) =
case modportInstance of
Just x -> x Just x -> x
Nothing -> error $ "can't deduce modport for interface " Nothing -> error $ "can't deduce modport for interface "
++ show expr ++ " bound to port " ++ portName ++ show expr ++ " bound to port " ++ portName
foundModport modportE = foundModport modportE =
Just (findInstance modportE, qualifyModport modportE) if (null interfaceName || bInterfaceName == interfaceName)
&& (null modportName || bModportName == modportName)
then Just (instanceE, qualifyModport modportE)
else error msg
where
bModportName =
case modportE of
Dot _ x -> x
_ -> ""
instanceE = findInstance modportE
Just (_, _, InterfaceTypeVal bInterfaceName) =
lookupIntfElem modports $ InterfaceTypeKey
(findInstance modportE)
msg = "port " ++ portName ++ " has type "
++ showModportType interfaceName modportName
++ ", but the binding " ++ show expr ++ " has type "
++ showModportType bInterfaceName bModportName
findInstance :: Expr -> Expr findInstance :: Expr -> Expr
findInstance e = findInstance e =
...@@ -221,11 +243,19 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -221,11 +243,19 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
Just (accesses, _, _) -> accessesToExpr $ init accesses Just (accesses, _, _) -> accessesToExpr $ init accesses
qualifyModport :: Expr -> Expr qualifyModport :: Expr -> Expr
qualifyModport e = qualifyModport e =
accessesToExpr $
case lookupIntfElem modports e of case lookupIntfElem modports e of
Just (accesses, _, _) -> accessesToExpr accesses Just (accesses, _, _) -> accesses
Nothing -> accessesToExpr $ init accesses Nothing ->
where Just (accesses, _, _) = case lookupIntfElem modports (Dot e "") of
lookupIntfElem modports (Dot e "") Just (accesses, _, _) -> init accesses
Nothing ->
error $ "could not find modport " ++ show e
showModportType :: Identifier -> Identifier -> String
showModportType "" "" = "generic interface"
showModportType intf "" = intf
showModportType intf modp = intf ++ '.' : modp
-- expand a modport binding into a series of expression substitutions -- expand a modport binding into a series of expression substitutions
genSubstitutions :: Scopes [ModportDecl] -> Expr -> Expr -> Expr genSubstitutions :: Scopes [ModportDecl] -> Expr -> Expr -> Expr
...@@ -271,15 +301,15 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -271,15 +301,15 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
Just info = maybeInfo Just info = maybeInfo
collectDecl _ = return () collectDecl _ = return ()
extractModportInfo :: Type -> Maybe Identifier extractModportInfo :: Type -> Maybe (Identifier, Identifier)
extractModportInfo (InterfaceT "" "" []) = Just "" extractModportInfo (InterfaceT "" "" []) = Just ("", "")
extractModportInfo (InterfaceT interfaceName modportName []) = extractModportInfo (InterfaceT interfaceName modportName []) =
if isInterface interfaceName if isInterface interfaceName
then Just modportName then Just (interfaceName, modportName)
else Nothing else Nothing
extractModportInfo (Alias interfaceName []) = extractModportInfo (Alias interfaceName []) =
if isInterface interfaceName if isInterface interfaceName
then Just "" then Just (interfaceName, "")
else Nothing else Nothing
extractModportInfo _ = Nothing extractModportInfo _ = Nothing
...@@ -318,7 +348,7 @@ inlineInstance global ranges modportBindings items partName ...@@ -318,7 +348,7 @@ inlineInstance global ranges modportBindings items partName
traverseDeclM traverseModuleItemM traverseGenItemM traverseStmtM "" traverseDeclM traverseModuleItemM traverseGenItemM traverseStmtM ""
$ map (traverseNestedModuleItems rewriteItem) $ $ map (traverseNestedModuleItems rewriteItem) $
if null modportBindings if null modportBindings
then items ++ [dimensionModport, bundleModport] then items ++ [typeModport, dimensionModport, bundleModport]
else items else items
key = shortHash (partName, instanceName) key = shortHash (partName, instanceName)
...@@ -328,6 +358,7 @@ inlineInstance global ranges modportBindings items partName ...@@ -328,6 +358,7 @@ inlineInstance global ranges modportBindings items partName
dimensionModport = if not isArray dimensionModport = if not isArray
then MIPackageItem $ Decl $ CommentDecl "not an instance array" then MIPackageItem $ Decl $ CommentDecl "not an instance array"
else InstArrEncoded arrayLeft arrayRight else InstArrEncoded arrayLeft arrayRight
typeModport = InterfaceTypeEncoded partName
inlineKind = inlineKind =
if null modportBindings if null modportBindings
...@@ -613,6 +644,16 @@ pattern InstArrEncoded l r = Modport InstArrName (InstArrVal l r) ...@@ -613,6 +644,16 @@ pattern InstArrEncoded l r = Modport InstArrName (InstArrVal l r)
pattern DeclVal :: [ModportDecl] pattern DeclVal :: [ModportDecl]
pattern DeclVal = [(Local, "~decl~", Nil)] pattern DeclVal = [(Local, "~decl~", Nil)]
-- encoding for the interface type of an interface instantiation
pattern InterfaceTypeName :: Identifier
pattern InterfaceTypeName = "~interface_type~"
pattern InterfaceTypeVal :: Identifier -> [ModportDecl]
pattern InterfaceTypeVal x = [(Local, "~interface~type~", Ident x)]
pattern InterfaceTypeKey :: Expr -> Expr
pattern InterfaceTypeKey e = Dot e InterfaceTypeName
pattern InterfaceTypeEncoded :: Identifier -> ModuleItem
pattern InterfaceTypeEncoded x = Modport InterfaceTypeName (InterfaceTypeVal x)
-- determines the lower bound for the given slice -- determines the lower bound for the given slice
sliceLo :: PartSelectMode -> Range -> Expr sliceLo :: PartSelectMode -> Range -> Expr
sliceLo NonIndexed (l, r) = endianCondExpr (l, r) r l sliceLo NonIndexed (l, r) = endianCondExpr (l, r) r l
......
interface Interface1;
logic x;
modport ModportA (input x);
modport ModportB (output x);
endinterface
interface Interface2;
logic x;
modport ModportA (input x);
modport ModportB (output x);
endinterface
// pattern: port intf has type Interface1, but the binding intf2 has type Interface2
`include "interface_mismatch.svh"
module Module(intf);
Interface1 intf;
endmodule
module top;
Interface2 intf2();
Module m(intf2);
endmodule
// pattern: port intf has type Interface1, but the binding intf2\.ModportA has type Interface2\.ModportA
`include "interface_mismatch.svh"
module Module(intf);
Interface1 intf;
endmodule
module top;
Interface2 intf2();
Module m(intf2.ModportA);
endmodule
// pattern: port intf has type Interface1\.ModportB, but the binding intf1\.ModportA has type Interface1\.ModportA
`include "interface_mismatch.svh"
module Module(intf);
Interface1.ModportB intf;
endmodule
module top;
Interface1 intf1();
Module m(intf1.ModportA);
endmodule
// pattern: could not resolve modport binding intf1\.ModportC for port intf of type Interface1\.ModportB
`include "interface_mismatch.svh"
module Module(intf);
Interface1.ModportB intf;
endmodule
module top;
Interface1 intf1();
Module m(intf1.ModportC);
endmodule
// pattern: could not resolve modport binding intf1\.ModportC for port intf of type Interface1\.ModportC
`include "interface_mismatch.svh"
module Module(intf);
Interface1.ModportC intf;
endmodule
module top;
Interface1 intf1();
Module m(intf1.ModportC);
endmodule
// pattern: could not find modport intf1\.ModportC
`include "interface_mismatch.svh"
module Module(intf);
Interface1.ModportC intf;
endmodule
module top;
Interface1 intf1();
Module m(intf1);
endmodule
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