Commit a209335c by Zachary Snow

disambiguate typenames and interface names

parent b09fdaf7
......@@ -8,6 +8,7 @@
### New Features
* Added support for attributes in unary, binary, and ternary expressions
* Added support for shadowing interface names with local typenames
### Bug Fixes
......
......@@ -116,6 +116,7 @@ initialPhases tops selectExclude =
, Convert.FuncRoutine.convert
, selectExclude Job.Assert Convert.Assertion.convert
, selectExclude Job.Always Convert.AlwaysKW.convert
, Convert.Interface.disambiguate
, Convert.Package.convert
, Convert.StructConst.convert
, Convert.PortDecl.convert
......
......@@ -5,7 +5,7 @@
- Conversion for interfaces
-}
module Convert.Interface (convert) where
module Convert.Interface (convert, disambiguate) where
import Data.List (intercalate, (\\))
import Data.Maybe (isJust, isNothing, mapMaybe)
......@@ -38,11 +38,6 @@ convert tops files =
(map . convertDescription tops)
files
where
-- we can only collect/map non-extern interfaces and modules
collectPart :: Description -> Writer PartInfos ()
collectPart (Part _ False kw _ name ports items) =
tell $ Map.singleton name $ PartInfo kw ports items
collectPart _ = return ()
-- multidimensional instances need to be flattened before this
-- conversion can proceed
needsFlattening =
......@@ -55,6 +50,67 @@ convert tops files =
checkItem (Instance _ _ _ rs _) = when (length rs > 1) $ tell $ Any True
checkItem _ = return ()
-- we can only collect/map non-extern interfaces and modules
collectPart :: Description -> Writer PartInfos ()
collectPart (Part _ False kw _ name ports items) =
tell $ Map.singleton name $ PartInfo kw ports items
collectPart _ = return ()
-- disambiguate typenames from interface names
disambiguate :: [AST] -> [AST]
disambiguate = traverseFiles
(collectDescriptionsM collectPart)
(map . disambiguateDescription)
-- disambiguate any typenames within a description
disambiguateDescription :: PartInfos -> Description -> Description
disambiguateDescription parts (Part att ext kw lif name ports items) =
Part att ext kw lif name ports $ map traverseModuleItem items
where
typeNames = getTypeNames items
traverseModuleItem :: ModuleItem -> ModuleItem
traverseModuleItem (MIAttr attr item) =
MIAttr attr $ traverseModuleItem item
traverseModuleItem (MIPackageItem (Decl (Variable d t x a e))) =
MIPackageItem $ Decl $ Variable d (traverseType t) x a e
traverseModuleItem other = other
traverseType :: Type -> Type
traverseType (Alias interfaceName rs) =
if isInterface interfaceName && not (elem interfaceName typeNames)
then InterfaceT interfaceName "" rs
else Alias interfaceName rs
traverseType orig@(InterfaceT interfaceName _ _) =
if null interfaceName || isInterface interfaceName
then orig
else error $ "declaration type " ++ show orig ++ " appears to "
++ "refer to an interface that isn't defined"
traverseType other = other
isInterface :: Identifier -> Bool
isInterface partName =
fmap pKind (Map.lookup partName parts) == Just Interface
disambiguateDescription _ other = other
-- get all of the typenames declared anywhere in the top-level module items
getTypeNames :: [ModuleItem] -> [Identifier]
getTypeNames (MIAttr _ item : rest) = getTypeNames $ item : rest
getTypeNames (Generate genItems : rest) =
getTypeNames $ genModuleItems genItems ++ rest
getTypeNames (MIPackageItem (Decl (ParamType _ name _)) : rest) =
name : getTypeNames rest
getTypeNames (_ : rest) = getTypeNames rest
getTypeNames [] = []
-- get the top-level (i.e., un-scoped) module items within a generate block
genModuleItems :: [GenItem] -> [ModuleItem]
genModuleItems (GenModuleItem item : rest) =
item : genModuleItems rest
genModuleItems (_ : rest) = genModuleItems rest
genModuleItems [] = []
topInterfaceError :: String -> String -> a
topInterfaceError name issue = error $
"Specified top module " ++ name ++ " " ++ issue ++ ". Please " ++
......@@ -307,7 +363,6 @@ convertDescription tops parts (Part att ext Module lif name ports items) =
else if elem x (pPorts partInfo) then
tell [(x, info)] >> return decl
else
-- TODO: This does not handle shadowed typenames.
scopedErrorM $
"Modport not in port list: " ++ show t ++ " " ++ x
++ ". Is this an interface missing a port list?"
......@@ -317,23 +372,10 @@ convertDescription tops parts (Part att ext Module lif name ports items) =
checkDecl decl = return decl
extractModportInfo :: Type -> Maybe (Identifier, Identifier)
extractModportInfo (InterfaceT "" "" _) = Just ("", "")
extractModportInfo (InterfaceT interfaceName modportName _) =
if isInterface interfaceName
then Just (interfaceName, modportName)
else Nothing
extractModportInfo (Alias interfaceName _) =
if isInterface interfaceName
then Just (interfaceName, "")
else Nothing
Just (interfaceName, modportName)
extractModportInfo _ = Nothing
isInterface :: Identifier -> Bool
isInterface partName =
case Map.lookup partName parts of
Nothing -> False
Just info -> pKind info == Interface
convertDescription _ _ other = other
isDecl :: ModuleItem -> Bool
......
......@@ -62,7 +62,8 @@ instance Show Type where
show (IntegerVector kw sg rs) = printf "%s%s%s" (show kw) (showPadBefore sg) (showRanges rs)
show (IntegerAtom kw sg ) = printf "%s%s" (show kw) (showPadBefore sg)
show (NonInteger kw ) = printf "%s" (show kw)
show (InterfaceT "" "" rs) = printf "interface%s" ( showRanges rs)
show (InterfaceT "" "" rs) = printf "interface%s" (showRanges rs)
show (InterfaceT xx "" rs) = printf "%s%s" xx (showRanges rs)
show (InterfaceT xx yy rs) = printf "%s.%s%s" xx yy (showRanges rs)
show (Enum t vals r) = printf "enum %s{%s}%s" tStr (commas $ map showVal vals) (showRanges r)
where
......
interface I;
logic [3:0] x;
endinterface
module A(I i);
initial $display("A %b", i.x);
endmodule
module B #(localparam type I = logic [3:0]) (I i);
initial $display("B %b", i);
endmodule
module top;
I i();
if (1) begin : blk
......@@ -9,4 +15,7 @@ module top;
assign i = 0;
end
initial $display("%b %b", i.x, blk.i);
A a(i);
B b(i.x);
assign i.x = 1;
endmodule
module A(input wire [3:0] i);
initial $display("A %b", i);
endmodule
module B(input wire [3:0] i);
initial $display("B %b", i);
endmodule
module top;
generate
if (1) begin : i
......@@ -9,4 +15,7 @@ module top;
end
endgenerate
initial $display("%b %b", i.x, blk.i);
A a(i.x);
B b(i.x);
assign i.x = 1;
endmodule
// pattern: declaration type I.J appears to refer to an interface that isn't defined
module mod(I.J K);
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