Commit d1d81eb8 by Zachary Snow

use scoped errors in interface conversion

parent 84edbae5
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
module Convert.Interface (convert) where module Convert.Interface (convert) where
import Data.List (intercalate, (\\))
import Data.Maybe (isJust, isNothing, mapMaybe) import Data.Maybe (isJust, isNothing, mapMaybe)
import Control.Monad.Writer.Strict import Control.Monad.Writer.Strict
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
...@@ -57,7 +58,7 @@ convertDescription :: PartInfos -> Description -> Description ...@@ -57,7 +58,7 @@ convertDescription :: PartInfos -> Description -> Description
convertDescription _ (Part _ _ Interface _ name _ _) = convertDescription _ (Part _ _ Interface _ name _ _) =
PackageItem $ Decl $ CommentDecl $ "removed interface: " ++ name PackageItem $ Decl $ CommentDecl $ "removed interface: " ++ name
convertDescription parts (Part attrs extern Module lifetime name ports items) = convertDescription parts (Part attrs extern Module lifetime name ports items) =
if null $ extractModportInstances $ PartInfo Module ports items then if null $ extractModportInstances name $ PartInfo Module ports items then
Part attrs extern Module lifetime name ports items' Part attrs extern Module lifetime name ports items'
else else
PackageItem $ Decl $ CommentDecl $ PackageItem $ Decl $ CommentDecl $
...@@ -99,12 +100,12 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -99,12 +100,12 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
else do else do
-- inline instantiation of a module -- inline instantiation of a module
let modportBindings = getModportBindings modports let modportBindings = getModportBindings modports
if length modportInstances /= length modportBindings let unconnected = map fst modportInstances \\
then map fst modportBindings
error $ "instance " ++ instanceName ++ " of " ++ part if not (null unconnected)
++ " has interface ports " then scopedErrorM $ "instance " ++ instanceName ++ " of "
++ showKeys modportInstances ++ ", but only " ++ part ++ " has unconnected interface ports: "
++ showKeys modportBindings ++ " are connected" ++ intercalate ", " unconnected
else scoper $ Generate $ map GenModuleItem $ else scoper $ Generate $ map GenModuleItem $
inlineInstance modports rs modportBindings partItems inlineInstance modports rs modportBindings partItems
part instanceName paramBindings portBindings part instanceName paramBindings portBindings
...@@ -115,12 +116,11 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -115,12 +116,11 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
Just partInfo = maybePartInfo Just partInfo = maybePartInfo
PartInfo partKind _ partItems = partInfo PartInfo partKind _ partItems = partInfo
modportInstances = extractModportInstances partInfo modportInstances = extractModportInstances part partInfo
getModportBindings modports = mapMaybe getModportBindings modports = mapMaybe
(inferModportBinding modports modportInstances) $ (inferModportBinding modports modportInstances) $
map (second $ addImpliedSlice modports) portBindings map (second $ addImpliedSlice modports) portBindings
second f = \(a, b) -> (a, f b) second f = \(a, b) -> (a, f b)
showKeys = show . map fst
traverseModuleItemM other = return other traverseModuleItemM other = return other
...@@ -195,8 +195,8 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -195,8 +195,8 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
-- 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 else if modportInstance /= Nothing then
error $ "could not resolve modport binding " ++ show expr scopedError modports $ "could not resolve modport binding "
++ " for port " ++ portName ++ " of type " ++ show expr ++ " for port " ++ portName ++ " of type "
++ showModportType interfaceName modportName ++ showModportType interfaceName modportName
else else
Nothing Nothing
...@@ -208,14 +208,15 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -208,14 +208,15 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
(interfaceName, modportName) = (interfaceName, modportName) =
case modportInstance of case modportInstance of
Just x -> x Just x -> x
Nothing -> error $ "can't deduce modport for interface " Nothing -> scopedError modports $
++ show expr ++ " bound to port " ++ portName "can't deduce modport for interface " ++ show expr
++ " bound to port " ++ portName
foundModport modportE = foundModport modportE =
if (null interfaceName || bInterfaceName == interfaceName) if (null interfaceName || bInterfaceName == interfaceName)
&& (null modportName || bModportName == modportName) && (null modportName || bModportName == modportName)
then Just (instanceE, qualifyModport modportE) then Just (instanceE, qualifyModport modportE)
else error msg else scopedError modports msg
where where
bModportName = bModportName =
case modportE of case modportE of
...@@ -246,8 +247,8 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -246,8 +247,8 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
Nothing -> Nothing ->
case lookupIntfElem modports (Dot e "") of case lookupIntfElem modports (Dot e "") of
Just (accesses, _, _) -> init accesses Just (accesses, _, _) -> init accesses
Nothing -> Nothing -> scopedError modports $
error $ "could not find modport " ++ show e "could not find modport " ++ show e
showModportType :: Identifier -> Identifier -> String showModportType :: Identifier -> Identifier -> String
showModportType "" "" = "generic interface" showModportType "" "" = "generic interface"
...@@ -271,23 +272,26 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -271,23 +272,26 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
e' = replaceInExpr replacements e e' = replaceInExpr replacements e
-- association list of modport instances in the given module body -- association list of modport instances in the given module body
extractModportInstances :: PartInfo -> ModportInstances extractModportInstances :: Identifier -> PartInfo -> ModportInstances
extractModportInstances partInfo = extractModportInstances part partInfo =
execWriter $ mapM (collectDeclsM collectDecl) (pItems partInfo) execWriter $ runScoperT $ scopeModuleItems collector part decls
where where
collectDecl :: Decl -> Writer ModportInstances () collector = scopeModuleItem checkDecl return return return
collectDecl (Variable _ t x _ _) = decls = filter isDecl $ pItems partInfo
checkDecl :: Decl -> ScoperT () (Writer ModportInstances) Decl
checkDecl decl@(Variable _ t x _ _) =
if maybeInfo == Nothing then if maybeInfo == Nothing then
return () return decl
else if elem x (pPorts partInfo) then else if elem x (pPorts partInfo) then
tell [(x, info)] tell [(x, info)] >> return decl
else else
error $ "Modport not in port list: " ++ show (t, x) scopedErrorM $
"Modport not in port list: " ++ show t ++ " " ++ x
++ ". Is this an interface missing a port list?" ++ ". Is this an interface missing a port list?"
where where
maybeInfo = extractModportInfo t maybeInfo = extractModportInfo t
Just info = maybeInfo Just info = maybeInfo
collectDecl _ = return () checkDecl decl = return decl
extractModportInfo :: Type -> Maybe (Identifier, Identifier) extractModportInfo :: Type -> Maybe (Identifier, Identifier)
extractModportInfo (InterfaceT "" "" _) = Just ("", "") extractModportInfo (InterfaceT "" "" _) = Just ("", "")
...@@ -309,6 +313,10 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) = ...@@ -309,6 +313,10 @@ convertDescription parts (Part attrs extern Module lifetime name ports items) =
convertDescription _ other = other convertDescription _ other = other
isDecl :: ModuleItem -> Bool
isDecl (MIPackageItem Decl{}) = True
isDecl _ = False
-- produce the implicit modport decls for an interface bundle -- produce the implicit modport decls for an interface bundle
impliedModport :: [ModuleItem] -> [ModportDecl] impliedModport :: [ModuleItem] -> [ModportDecl]
impliedModport = impliedModport =
...@@ -525,8 +533,8 @@ inlineInstance global ranges modportBindings items partName ...@@ -525,8 +533,8 @@ inlineInstance global ranges modportBindings items partName
checkExprResolution local expr = checkExprResolution local expr =
if not (exprResolves local expr) && exprResolves global expr if not (exprResolves local expr) && exprResolves global expr
then then
error $ "inlining instance \"" ++ instanceName ++ "\" of " scopedError local $ "inlining instance \"" ++ instanceName
++ inlineKind ++ " \"" ++ partName ++ "\" of " ++ inlineKind ++ " \"" ++ partName
++ "\" would make expression \"" ++ show expr ++ "\" would make expression \"" ++ show expr
++ "\" used in \"" ++ instanceName ++ "\" used in \"" ++ instanceName
++ "\" resolvable when it wasn't previously" ++ "\" resolvable when it wasn't previously"
......
// pattern: inlining instance "intf" of interface "Interface" would make expression "x" used in "intf" resolvable when it wasn't previously // pattern: inlining instance "intf" of interface "Interface" would make expression "x" used in "intf" resolvable when it wasn't previously
// location: interface_bad_expr.sv:4:5
interface Interface; interface Interface;
assign x = 1; assign x = 1;
endinterface endinterface
......
// pattern: inlining instance "intf" of interface "Interface" would make expression "x" used in "intf" resolvable when it wasn't previously // pattern: inlining instance "intf" of interface "Interface" would make expression "x" used in "intf" resolvable when it wasn't previously
// location: interface_bad_expr_genvar.sv:4:5
interface Interface; interface Interface;
assign x = 1; assign x = 1;
endinterface endinterface
......
// pattern: port intf has type Interface1, but the binding intf2 has type Interface2 // pattern: port intf has type Interface1, but the binding intf2 has type Interface2
// location: interface_mismatch_1.sv:9:5
`include "interface_mismatch.svh" `include "interface_mismatch.svh"
module Module(intf); module Module(intf);
Interface1 intf; Interface1 intf;
......
// pattern: port intf has type Interface1, but the binding intf2\.ModportA has type Interface2\.ModportA // pattern: port intf has type Interface1, but the binding intf2\.ModportA has type Interface2\.ModportA
// location: interface_mismatch_2.sv:9:5
`include "interface_mismatch.svh" `include "interface_mismatch.svh"
module Module(intf); module Module(intf);
Interface1 intf; Interface1 intf;
......
// pattern: port intf has type Interface1\.ModportB, but the binding intf1\.ModportA has type Interface1\.ModportA // pattern: port intf has type Interface1\.ModportB, but the binding intf1\.ModportA has type Interface1\.ModportA
// location: interface_mismatch_3.sv:9:5
`include "interface_mismatch.svh" `include "interface_mismatch.svh"
module Module(intf); module Module(intf);
Interface1.ModportB intf; Interface1.ModportB intf;
......
// pattern: could not resolve modport binding intf1\.ModportC for port intf of type Interface1\.ModportB // pattern: could not resolve modport binding intf1\.ModportC for port intf of type Interface1\.ModportB
// location: interface_mismatch_4.sv:9:5
`include "interface_mismatch.svh" `include "interface_mismatch.svh"
module Module(intf); module Module(intf);
Interface1.ModportB intf; Interface1.ModportB intf;
......
// pattern: could not resolve modport binding intf1\.ModportC for port intf of type Interface1\.ModportC // pattern: could not resolve modport binding intf1\.ModportC for port intf of type Interface1\.ModportC
// location: interface_mismatch_5.sv:9:5
`include "interface_mismatch.svh" `include "interface_mismatch.svh"
module Module(intf); module Module(intf);
Interface1.ModportC intf; Interface1.ModportC intf;
......
// pattern: could not find modport intf1\.ModportC // pattern: could not find modport intf1\.ModportC
// location: interface_mismatch_6.sv:9:5
`include "interface_mismatch.svh" `include "interface_mismatch.svh"
module Module(intf); module Module(intf);
Interface1.ModportC intf; Interface1.ModportC intf;
......
// pattern: can't deduce modport for interface j bound to port j, within scope top
// location: interface_modport_missing.sv:14:5
interface Interface; interface Interface;
logic x; logic x;
endinterface endinterface
module Module(i, j); module Module(i, j);
Interface i; Interface i;
logic j; logic j;
assign i.x = j.x; assign i.x = j.x;
endmodule endmodule
module top; module top;
Interface i(); Interface i();
Interface j(); Interface j();
......
// pattern: Modport not in port list: Interface i\. Is this an interface missing a port list\?
// location: interface_modport_unlisted.sv:7:5
interface Interface; interface Interface;
logic x; logic x;
endinterface endinterface
module Module; module Module;
Interface i; Interface i;
endmodule endmodule
// pattern: instance m of Module has unconnected interface ports: i
// location: interface_unbound_modport.sv:11:5
interface Interface; interface Interface;
logic x; logic x;
endinterface endinterface
module Module(i); module Module(i);
Interface i; Interface i;
endmodule endmodule
module top; module top;
Interface i(); Interface i();
Module m(); Module m();
......
// pattern: instance m of Module has unconnected interface ports: i, k
// location: interface_unbound_modports.sv:13:5
interface Interface;
logic x;
endinterface
module Module(i, j, k);
Interface i;
Interface j;
Interface k;
endmodule
module top;
Interface j();
Module m(.j);
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