Commit 7e20b741 by Zachary Snow

logic conversion handles shadowing

parent 80bfbc1e
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
module Convert.Logic (convert) where module Convert.Logic (convert) where
import Control.Monad.State
import Control.Monad.Writer import Control.Monad.Writer
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
...@@ -33,7 +34,7 @@ import Convert.Traverse ...@@ -33,7 +34,7 @@ import Convert.Traverse
import Language.SystemVerilog.AST import Language.SystemVerilog.AST
type Idents = Set.Set Identifier type Idents = Set.Set Identifier
type Ports = Map.Map (Identifier, Identifier) Direction type Ports = Map.Map Identifier [(Identifier, Direction)]
convert :: [AST] -> [AST] convert :: [AST] -> [AST]
convert = convert =
...@@ -43,19 +44,23 @@ convert = ...@@ -43,19 +44,23 @@ convert =
where where
collectPortsM :: Description -> Writer Ports () collectPortsM :: Description -> Writer Ports ()
collectPortsM (orig @ (Part _ _ _ _ name portNames _)) = collectPortsM (orig @ (Part _ _ _ _ name portNames _)) =
collectModuleItemsM collectPortDirsM orig tell $ Map.singleton name ports
where where
collectPortDirsM :: ModuleItem -> Writer Ports () ports = zip portNames (map lookupDir portNames)
collectPortDirsM (MIPackageItem (Decl (Variable dir _ ident _ _))) = dirs = execWriter $ collectModuleItemsM collectDeclDirsM orig
if dir == Local then lookupDir :: Identifier -> Direction
return () lookupDir portName =
else if elem ident portNames then case lookup portName dirs of
tell $ Map.singleton (name, ident) dir Just dir -> dir
else Nothing -> error $ "Could not find dir for port " ++
error $ "encountered decl with a dir that isn't a port: " portName ++ " in module " ++ name
++ show (dir, ident)
collectPortDirsM _ = return ()
collectPortsM _ = return () collectPortsM _ = return ()
collectDeclDirsM :: ModuleItem -> Writer [(Identifier, Direction)] ()
collectDeclDirsM (MIPackageItem (Decl (Variable dir _ ident _ _))) =
if dir == Local
then return ()
else tell [(ident, dir)]
collectDeclDirsM _ = return ()
convertDescription :: Ports -> Description -> Description convertDescription :: Ports -> Description -> Description
convertDescription ports orig = convertDescription ports orig =
...@@ -93,15 +98,16 @@ convertDescription ports orig = ...@@ -93,15 +98,16 @@ convertDescription ports orig =
where where
comment = MIPackageItem $ Decl $ CommentDecl comment = MIPackageItem $ Decl $ CommentDecl
"rewrote reg-to-output bindings" "rewrote reg-to-output bindings"
(bindings', newItemsList) = unzip $ map fixBinding bindings (bindings', newItemsList) =
unzip $ map (uncurry fixBinding) $ zip bindings [0..]
newItems = concat newItemsList newItems = concat newItemsList
fixBinding :: PortBinding -> (PortBinding, [ModuleItem]) fixBinding :: PortBinding -> Int -> (PortBinding, [ModuleItem])
fixBinding (portName, Just expr) = fixBinding (portName, Just expr) portIdx =
if portDir /= Just Output || Set.disjoint usedIdents origIdents if portDir /= Just Output || Set.disjoint usedIdents origIdents
then ((portName, Just expr), []) then ((portName, Just expr), [])
else ((portName, Just tmpExpr), items) else ((portName, Just tmpExpr), items)
where where
portDir = Map.lookup (moduleName, portName) ports portDir = lookupPortDir portName portIdx
usedIdents = execWriter $ usedIdents = execWriter $
collectNestedExprsM exprIdents expr collectNestedExprsM exprIdents expr
tmp = "sv2v_tmp_" ++ instanceName ++ "_" ++ portName tmp = "sv2v_tmp_" ++ instanceName ++ "_" ++ portName
...@@ -117,7 +123,18 @@ convertDescription ports orig = ...@@ -117,7 +123,18 @@ convertDescription ports orig =
error $ "bad non-lhs, non-net expr " error $ "bad non-lhs, non-net expr "
++ show expr ++ " connected to output port " ++ show expr ++ " connected to output port "
++ portName ++ " of " ++ instanceName ++ portName ++ " of " ++ instanceName
fixBinding other = (other, []) fixBinding other _ = (other, [])
lookupPortDir :: Identifier -> Int -> Maybe Direction
lookupPortDir "" portIdx =
case Map.lookup moduleName ports of
Nothing -> Nothing
Just l -> if portIdx >= length l
then Nothing
else Just $ snd $ l !! portIdx
lookupPortDir portName _ =
case Map.lookup moduleName ports of
Nothing -> Nothing
Just l -> lookup portName l
fixModuleItem other = other fixModuleItem other = other
-- rewrite variable declarations to have the correct type -- rewrite variable declarations to have the correct type
...@@ -141,25 +158,42 @@ convertDescription ports orig = ...@@ -141,25 +158,42 @@ convertDescription ports orig =
convertDecl other = other convertDecl other = other
regIdents :: ModuleItem -> Writer Idents () regIdents :: ModuleItem -> Writer Idents ()
regIdents (AlwaysC _ stmt) = do regIdents (item @ AlwaysC{}) = regIdents' item
collectNestedStmtsM collectReadMemsM stmt regIdents (item @ Initial{}) = regIdents' item
collectNestedStmtsM (collectStmtLHSsM (collectNestedLHSsM lhsIdents)) $ regIdents (item @ Final{}) = regIdents' item
traverseNestedStmts removeTimings stmt regIdents _ = return ()
where
removeTimings :: Stmt -> Stmt regIdents' :: ModuleItem -> Writer Idents ()
removeTimings (Timing _ s) = s regIdents' item = do
removeTimings other = other let write = traverseScopesM traverseDeclM return traverseStmtM item
collectReadMemsM :: Stmt -> Writer Idents () leftovers <- execStateT write Set.empty
collectReadMemsM (Subroutine (Ident f) (Args (_ : Just (Ident x) : _) [])) = if Set.null leftovers
then return ()
else error $ "regIdents' got leftovers: " ++ show leftovers
traverseDeclM :: Monad m => Decl -> StateT Idents m Decl
traverseDeclM (decl @ (Variable _ _ x _ _)) =
modify (Set.insert x) >> return decl
traverseDeclM decl = return decl
traverseStmtM :: Stmt -> StateT Idents (Writer Idents) Stmt
traverseStmtM (Timing _ stmt) = traverseStmtM stmt
traverseStmtM (Subroutine (Ident f) args) = do
case args of
Args [_, Just (Ident x), _] [] ->
-- assuming that no one will readmem into a local variable
if f == "$readmemh" || f == "$readmemb" if f == "$readmemh" || f == "$readmemb"
then tell $ Set.singleton x then lift $ tell $ Set.singleton x
else return () else return ()
collectReadMemsM _ = return () _ -> return ()
regIdents (Initial stmt) = return $ Subroutine (Ident f) args
regIdents $ AlwaysC Always stmt traverseStmtM stmt = do
regIdents (Final stmt) = -- only write down idents which aren't shadowed
regIdents $ AlwaysC Always stmt let regs = execWriter $ collectStmtLHSsM (collectNestedLHSsM lhsIdents) stmt
regIdents _ = return () locals <- get
let globals = Set.difference regs locals
lift $ tell globals
return stmt
lhsIdents :: LHS -> Writer Idents () lhsIdents :: LHS -> Writer Idents ()
lhsIdents (LHSIdent x) = tell $ Set.singleton x lhsIdents (LHSIdent x) = tell $ Set.singleton x
......
module Flip(x, y);
input x;
output y;
assign y = ~x;
endmodule
module Test1(o);
output [1:0] o;
logic x = 0;
for (genvar i = 0; i < 1; ++i) begin
Flip flip(x, o[i]);
end
initial begin
integer i = 0;
end
endmodule
module Test2(o);
output o;
logic x = 0;
Flip flip(x, o);
initial begin
integer o = 0;
x = 0;
end
endmodule
module Test3(o);
output o;
logic [1:0] x;
Flip flip(x[0], x[1]);
assign o = x[0];
initial x[0] = 0;
initial begin
integer x = 0;
end
endmodule
module Flip(x, y);
input x;
output y;
assign y = ~x;
endmodule
module Test1(o);
output [1:0] o;
wire x = 0;
generate
genvar i;
for (i = 0; i < 1; i = i + 1) begin
Flip flip(x, o[i]);
end
endgenerate
initial begin : blah
integer i;
i = 0;
end
endmodule
module Test2(o);
output o;
wire x = 0;
Flip flip(x, o);
initial begin : blah
integer o;
o = 0;
end
endmodule
module Test3(o);
output o;
reg x_0;
wire x_1;
Flip flip(x_0, x_1);
assign o = x_0;
initial x_0 = 0;
initial begin : blah
integer x;
x = 0;
end
endmodule
module top;
wire [1:0] o1;
Test1 bar(o1);
wire o2;
Test2 test2(o2);
wire o3;
Test3 test3(o3);
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