mirror of https://github.com/zachjs/sv2v.git
use scoped errors in interface conversion
This commit is contained in:
parent
84edbae503
commit
d1d81eb8d6
|
|
@ -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
|
||||||
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) =
|
||||||
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) =
|
||||||
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) =
|
||||||
-- 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) =
|
||||||
(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) =
|
||||||
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) =
|
||||||
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) =
|
||||||
|
|
||||||
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
|
||||||
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"
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// 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
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// 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
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// 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;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// 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;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// 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;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// 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;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// 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;
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
// 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;
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,13 @@
|
||||||
|
// 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();
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
|
// 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
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
|
// 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();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
// 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
|
||||||
Loading…
Reference in New Issue