Commit 4026ae8f by Zachary Snow

interface conversion respects shadowed variables

parent 4bebb85c
...@@ -8,12 +8,14 @@ module Convert.Interface (convert) where ...@@ -8,12 +8,14 @@ module Convert.Interface (convert) where
import Data.Maybe (mapMaybe) import Data.Maybe (mapMaybe)
import Control.Monad.Writer import Control.Monad.Writer
import Control.Monad.State
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import qualified Data.Set as Set import qualified Data.Set as Set
import Convert.Traverse import Convert.Traverse
import Language.SystemVerilog.AST import Language.SystemVerilog.AST
type Idents = Set.Set Identifier
type Interface = ([Identifier], [ModuleItem]) type Interface = ([Identifier], [ModuleItem])
type Interfaces = Map.Map Identifier Interface type Interfaces = Map.Map Identifier Interface
type Module = ([Identifier], [(Identifier, Type)]) type Module = ([Identifier], [(Identifier, Type)])
...@@ -72,11 +74,8 @@ convertDescription :: Interfaces -> Modules -> Description -> Description ...@@ -72,11 +74,8 @@ convertDescription :: Interfaces -> Modules -> Description -> Description
convertDescription interfaces modules (Part attrs extern Module lifetime name ports items) = convertDescription interfaces modules (Part attrs extern Module lifetime name ports items) =
Part attrs extern Module lifetime name ports' items' Part attrs extern Module lifetime name ports' items'
where where
items' = items' = map (flattenInstances instances modports) $
map (traverseNestedModuleItems $ traverseExprs' ExcludeTFs (traverseNestedExprs $ convertExpr instances modports)) $ map (traverseNestedModuleItems expandInterface) items
map (traverseNestedModuleItems $ traverseLHSs' ExcludeTFs (traverseNestedLHSs $ convertLHS instances modports)) $
map (traverseNestedModuleItems mapInterface) $
items
ports' = concatMap convertPort ports ports' = concatMap convertPort ports
-- collect the interface type of all interface instances in this module -- collect the interface type of all interface instances in this module
...@@ -106,8 +105,8 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po ...@@ -106,8 +105,8 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
else return () else return ()
collectInstanceM _ = return () collectInstanceM _ = return ()
mapInterface :: ModuleItem -> ModuleItem expandInterface :: ModuleItem -> ModuleItem
mapInterface (orig @ (MIPackageItem (Decl (Variable _ _ ident _ _)))) = expandInterface (orig @ (MIPackageItem (Decl (Variable _ _ ident _ _)))) =
-- expand instantiation of a modport -- expand instantiation of a modport
if Map.member ident modports if Map.member ident modports
then Generate $ map GenModuleItem $ then Generate $ map GenModuleItem $
...@@ -129,7 +128,7 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po ...@@ -129,7 +128,7 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
where port' = if null modportName where port' = if null modportName
then port then port
else ident ++ '_' : port else ident ++ '_' : port
mapInterface (Instance part params ident [] instancePorts) = expandInterface (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
Just interface -> Just interface ->
...@@ -150,23 +149,7 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po ...@@ -150,23 +149,7 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
if null addedParams if null addedParams
then params then params
else paramsNamed ++ addedParams else paramsNamed ++ addedParams
mapInterface (orig @ (MIPackageItem (Function _ _ _ decls _))) = expandInterface other = other
convertTF decls orig
mapInterface (orig @ (MIPackageItem (Task _ _ decls _))) =
convertTF decls orig
mapInterface other = other
convertTF :: [Decl] -> ModuleItem -> ModuleItem
convertTF decls =
traverseExprs (traverseNestedExprs $ convertExpr its mps) .
traverseLHSs (traverseNestedLHSs $ convertLHS its mps)
where
locals = Set.fromList $ map declVarIdent decls
its = Map.withoutKeys instances locals
mps = Map.withoutKeys modports locals
declVarIdent :: Decl -> Identifier
declVarIdent (Variable _ _ x _ _) = x
declVarIdent _ = ""
expandPortBinding :: Identifier -> PortBinding -> Int -> ([ParamBinding], [PortBinding]) expandPortBinding :: Identifier -> PortBinding -> Int -> ([ParamBinding], [PortBinding])
expandPortBinding moduleName ("", binding) idx = expandPortBinding moduleName ("", binding) idx =
...@@ -272,31 +255,69 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po ...@@ -272,31 +255,69 @@ convertDescription interfaces modules (Part attrs extern Module lifetime name po
where d' = if d == Local then Inout else d where d' = if d == Local then Inout else d
collectModportDecls _ = return () collectModportDecls _ = return ()
convertExpr :: Instances -> Modports -> Expr -> Expr
convertExpr its mps (orig @ (Dot (Ident x) y)) =
if Map.member x mps || Map.member x its
then Ident (x ++ "_" ++ y)
else orig
convertExpr _ _ other = other
convertLHS :: Instances -> Modports -> LHS -> LHS
convertLHS its mps (orig @ (LHSDot (LHSIdent x) y)) =
if Map.member x mps || Map.member x its
then LHSIdent (x ++ "_" ++ y)
else orig
convertLHS _ _ other = other
convertPort :: Identifier -> [Identifier] convertPort :: Identifier -> [Identifier]
convertPort ident = convertPort ident =
case Map.lookup ident modports of case Map.lookup ident modports of
Nothing -> [ident] Nothing -> [ident]
Just (interfaceName, modportName) -> Just (interfaceName, modportName) ->
map (\(_, x, _, _) -> map (\(_, x, _, _) -> ident ++ "_" ++ x) modportDecls
ident ++ "_" ++ x) modportDecls
where where
interfaceItems = snd $ lookupInterface interfaceName interfaceItems = snd $ lookupInterface interfaceName
modportDecls = lookupModport interfaceItems modportName modportDecls = lookupModport interfaceItems modportName
convertDescription _ _ other = other convertDescription _ _ other = other
-- replaces accesses of interface or modport members with their corresponding
-- flattened (exploded) data declarations
flattenInstances :: Instances -> Modports -> ModuleItem -> ModuleItem
flattenInstances instances modports =
\item -> evalState (rewriter item) Set.empty
where
rewriter = traverseScopesM traverseDeclM
(traverseNestedModuleItemsM traverseModuleItemM) traverseStmtM
traverseModuleItemM :: ModuleItem -> State Idents ModuleItem
traverseModuleItemM =
traverseExprsM traverseExprM >=>
traverseLHSsM traverseLHSM
traverseStmtM :: Stmt -> State Idents Stmt
traverseStmtM =
traverseStmtExprsM traverseExprM >=>
traverseStmtLHSsM traverseLHSM
traverseDeclM :: Decl -> State Idents Decl
traverseDeclM decl = do
item <- traverseModuleItemM (MIPackageItem $ Decl decl)
let MIPackageItem (Decl decl') = item
case decl' of
Variable _ _ ident _ _ -> modify $ Set.insert ident
Param _ _ ident _ -> modify $ Set.insert ident
ParamType{} -> return ()
CommentDecl{} -> return ()
return decl'
traverseExprM = traverseNestedExprsM convertExprM
traverseLHSM = traverseNestedLHSsM convertLHSM
convertExprM :: Expr -> State Idents Expr
convertExprM (orig @ (Dot (Ident x) y)) = do
substituteNonLocal orig repl x
where repl = Ident (x ++ "_" ++ y)
convertExprM other = return other
convertLHSM :: LHS -> State Idents LHS
convertLHSM (orig @ (LHSDot (LHSIdent x) y)) = do
substituteNonLocal orig repl x
where repl = LHSIdent (x ++ "_" ++ y)
convertLHSM other = return other
substituteNonLocal :: a -> a -> Identifier -> State Idents a
substituteNonLocal orig repl ident = do
locals <- get
return $ if Map.member ident modports || Map.member ident instances
then if Set.notMember ident locals
then repl
else orig
else orig
-- add a prefix to all standard identifiers in a module item -- add a prefix to all standard identifiers in a module item
prefixModuleItems :: (Identifier -> Identifier) -> ModuleItem -> ModuleItem prefixModuleItems :: (Identifier -> Identifier) -> ModuleItem -> ModuleItem
......
interface I;
task x;
input logic [31:0] i;
$display("I x(%0d)", i);
endtask
endinterface
module top;
I i();
logic [31:0] w = 31;
logic [31:0] y = 42;
typedef struct packed { logic [31:0] x, y; } E;
task x;
input E i;
$display("x('{%0d, %0d})", i.x, i.y);
endtask
task automatic z;
input E t;
begin : foo
E i = t;
$display("z('{%0d, %0d})", i.x, i.y);
end
endtask
initial begin
i.x(y);
x({w, y});
z({w, y});
end
endmodule
module top;
task i_x;
input reg [31:0] i;
$display("I x(%0d)", i);
endtask
wire [31:0] w = 31;
wire [31:0] y = 42;
task x;
input reg [31:0] a, b;
$display("x('{%0d, %0d})", a, b);
endtask
task automatic z;
input reg [31:0] a, b;
$display("z('{%0d, %0d})", a, b);
endtask
initial begin
i_x(y);
x(w, y);
z(w, y);
end
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