mirror of https://github.com/zachjs/sv2v.git
fix cascaded generate block cast and scope resolution
- scoper item injection can no longer affect generate scoping - cast conversion injects functions into the top level when possible - cast conversion considers loop variables to be local - `else if` generate blocks are still scopes at the current level
This commit is contained in:
parent
eda9a34ad5
commit
16a13ee915
|
|
@ -117,12 +117,18 @@ convertCastM (Number size) (Number value) signed =
|
|||
++ " is not an integer"
|
||||
convertCastM size value signed = do
|
||||
value' <- traverseExprM value
|
||||
useFn <- embedScopes canUseCastFn size
|
||||
if useFn then do
|
||||
sizeUsesLocalVars <- embedScopes usesLocalVars size
|
||||
inProcedure <- withinProcedureM
|
||||
if not sizeUsesLocalVars || not inProcedure then do
|
||||
let name = castFnName size signed
|
||||
details <- lookupLocalIdentM name
|
||||
when (details == Nothing) $
|
||||
injectItem $ castFn name size signed
|
||||
let item = castFn name size signed
|
||||
if sizeUsesLocalVars
|
||||
then do
|
||||
details <- lookupLocalIdentM name
|
||||
when (details == Nothing) (injectItem item)
|
||||
else do
|
||||
details <- lookupElemM name
|
||||
when (details == Nothing) (injectTopItem item)
|
||||
return $ Call (Ident name) (Args [value'] [])
|
||||
else do
|
||||
name <- castDeclName 0
|
||||
|
|
@ -131,16 +137,19 @@ convertCastM size value signed = do
|
|||
injectDecl $ castDecl useVar name value' size signed
|
||||
return $ Ident name
|
||||
|
||||
-- checks if a cast size can be hoisted to a cast function
|
||||
canUseCastFn :: Scopes a -> Expr -> Bool
|
||||
canUseCastFn scopes size =
|
||||
not (inProcedure && anyNonLocal)
|
||||
-- checks if a cast size references any vars not defined at the top level scope
|
||||
usesLocalVars :: Scopes a -> Expr -> Bool
|
||||
usesLocalVars scopes =
|
||||
getAny . execWriter . collectNestedExprsM collectLocalVarsM
|
||||
where
|
||||
inProcedure = withinProcedure scopes
|
||||
anyNonLocal = getAny $ execWriter $
|
||||
collectNestedExprsM collectNonLocalExprM size
|
||||
collectNonLocalExprM :: Expr -> Writer Any ()
|
||||
collectNonLocalExprM expr =
|
||||
collectLocalVarsM :: Expr -> Writer Any ()
|
||||
collectLocalVarsM expr@(Ident x) =
|
||||
if isLoopVar scopes x
|
||||
then tell $ Any True
|
||||
else resolve expr
|
||||
collectLocalVarsM expr = resolve expr
|
||||
resolve :: Expr -> Writer Any ()
|
||||
resolve expr =
|
||||
case lookupElem scopes expr of
|
||||
Nothing -> return ()
|
||||
Just ([_, _], _, _) -> return ()
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ module Convert.Scoper
|
|||
, scopeType
|
||||
, insertElem
|
||||
, injectItem
|
||||
, injectTopItem
|
||||
, injectDecl
|
||||
, lookupElem
|
||||
, lookupElemM
|
||||
|
|
@ -63,6 +64,7 @@ module Convert.Scoper
|
|||
|
||||
import Control.Monad.State.Strict
|
||||
import Data.Functor.Identity (runIdentity)
|
||||
import Data.List (partition)
|
||||
import Data.Maybe (isNothing)
|
||||
import qualified Data.Map.Strict as Map
|
||||
|
||||
|
|
@ -97,7 +99,7 @@ data Scopes a = Scopes
|
|||
{ sCurrent :: [Tier]
|
||||
, sMapping :: Mapping a
|
||||
, sProcedureLoc :: [Access]
|
||||
, sInjectedItems :: [ModuleItem]
|
||||
, sInjectedItems :: [(Bool, ModuleItem)]
|
||||
, sInjectedDecls :: [Decl]
|
||||
} deriving Show
|
||||
|
||||
|
|
@ -225,7 +227,11 @@ insertElem key element = do
|
|||
|
||||
injectItem :: Monad m => ModuleItem -> ScoperT a m ()
|
||||
injectItem item =
|
||||
modify' $ \s -> s { sInjectedItems = item : sInjectedItems s }
|
||||
modify' $ \s -> s { sInjectedItems = (True, item) : sInjectedItems s }
|
||||
|
||||
injectTopItem :: Monad m => ModuleItem -> ScoperT a m ()
|
||||
injectTopItem item =
|
||||
modify' $ \s -> s { sInjectedItems = (False, item) : sInjectedItems s }
|
||||
|
||||
injectDecl :: Monad m => Decl -> ScoperT a m ()
|
||||
injectDecl decl =
|
||||
|
|
@ -233,10 +239,13 @@ injectDecl decl =
|
|||
|
||||
consumeInjectedItems :: Monad m => ScoperT a m [ModuleItem]
|
||||
consumeInjectedItems = do
|
||||
injected <- gets sInjectedItems
|
||||
-- only pull out top items if in the top scope
|
||||
inTopLevelScope <- gets $ (== 1) . length . sCurrent
|
||||
let op = if inTopLevelScope then const True else fst
|
||||
(injected, remaining) <- gets $ partition op . sInjectedItems
|
||||
when (not $ null injected) $
|
||||
modify' $ \s -> s { sInjectedItems = [] }
|
||||
return $ reverse injected
|
||||
modify' $ \s -> s { sInjectedItems = remaining }
|
||||
return $ reverse $ map snd $ injected
|
||||
|
||||
consumeInjectedDecls :: Monad m => ScoperT a m [Decl]
|
||||
consumeInjectedDecls = do
|
||||
|
|
@ -517,7 +526,7 @@ scopeModuleItemT declMapper moduleItemMapper genItemMapper stmtMapper =
|
|||
exitProcedure
|
||||
return $ Final stmt'
|
||||
fullModuleItemMapper (Generate genItems) =
|
||||
mapM fullGenItemMapper genItems >>= return . Generate
|
||||
fullGenItemBlockMapper genItems >>= return . Generate
|
||||
fullModuleItemMapper (MIAttr attr item) =
|
||||
fullModuleItemMapper item >>= return . MIAttr attr
|
||||
fullModuleItemMapper item = moduleItemMapper item
|
||||
|
|
@ -526,43 +535,48 @@ scopeModuleItemT declMapper moduleItemMapper genItemMapper stmtMapper =
|
|||
fullGenItemMapper genItem = do
|
||||
genItem' <- genItemMapper genItem
|
||||
injected <- consumeInjectedItems
|
||||
genItem'' <- scopeGenItemMapper genItem'
|
||||
mapM_ injectItem injected -- defer until enclosing block
|
||||
return genItem''
|
||||
|
||||
-- akin to fullGenItemMapper, but for lists of generate items, and
|
||||
-- allowing module items to be injected in the middle of the list
|
||||
fullGenItemBlockMapper :: [GenItem] -> ScoperT a m [GenItem]
|
||||
fullGenItemBlockMapper = fmap concat . mapM genblkStep
|
||||
genblkStep :: GenItem -> ScoperT a m [GenItem]
|
||||
genblkStep genItem = do
|
||||
genItem' <- fullGenItemMapper genItem
|
||||
injected <- consumeInjectedItems
|
||||
if null injected
|
||||
then scopeGenItemMapper genItem'
|
||||
then return [genItem']
|
||||
else do
|
||||
injected' <- mapM fullModuleItemMapper injected
|
||||
genItem'' <- scopeGenItemMapper genItem'
|
||||
let genItems = map GenModuleItem injected' ++ [genItem'']
|
||||
-- flattened during traversal
|
||||
return $ GenModuleItem $ Generate genItems
|
||||
return $ map GenModuleItem injected' ++ [genItem']
|
||||
|
||||
-- enters and exits generate block scopes as appropriate
|
||||
scopeGenItemMapper :: GenItem -> ScoperT a m GenItem
|
||||
scopeGenItemMapper (GenFor _ _ _ GenNull) = return GenNull
|
||||
scopeGenItemMapper (GenFor (index, a) b c genItem) = do
|
||||
genItem' <- scopeGenItemBranchMapper index genItem
|
||||
let GenBlock name genItems = genItem
|
||||
enterScope name index
|
||||
genItems' <- fullGenItemBlockMapper genItems
|
||||
exitScope
|
||||
let genItem' = GenBlock name genItems'
|
||||
return $ GenFor (index, a) b c genItem'
|
||||
scopeGenItemMapper (GenIf cond thenItem elseItem) = do
|
||||
thenItem' <- scopeGenItemBranchMapper "" thenItem
|
||||
elseItem' <- scopeGenItemBranchMapper "" elseItem
|
||||
thenItem' <- fullGenItemMapper thenItem
|
||||
elseItem' <- fullGenItemMapper elseItem
|
||||
return $ GenIf cond thenItem' elseItem'
|
||||
scopeGenItemMapper (GenBlock name genItems) = do
|
||||
enterScope name ""
|
||||
genItems' <- mapM fullGenItemMapper genItems
|
||||
genItems' <- fullGenItemBlockMapper genItems
|
||||
exitScope
|
||||
return $ GenBlock name genItems'
|
||||
scopeGenItemMapper (GenModuleItem moduleItem) =
|
||||
wrappedModuleItemMapper moduleItem >>= return . GenModuleItem
|
||||
scopeGenItemMapper genItem =
|
||||
scopeGenItemMapper genItem@GenCase{} =
|
||||
traverseSinglyNestedGenItemsM fullGenItemMapper genItem
|
||||
|
||||
scopeGenItemBranchMapper :: Identifier -> GenItem -> ScoperT a m GenItem
|
||||
scopeGenItemBranchMapper index (GenBlock name genItems) = do
|
||||
enterScope name index
|
||||
genItems' <- mapM fullGenItemMapper genItems
|
||||
exitScope
|
||||
return $ GenBlock name genItems'
|
||||
scopeGenItemBranchMapper index genItem = do
|
||||
enterScope "" index
|
||||
genItem' <- fullGenItemMapper genItem
|
||||
exitScope
|
||||
return genItem'
|
||||
scopeGenItemMapper GenNull = return GenNull
|
||||
|
||||
partScoper
|
||||
:: MapperM (Scoper a) Decl
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
`ifdef REF
|
||||
`define CHECK(N) (P & (1 << (Z+N+1) - 1))
|
||||
`else
|
||||
`define CHECK(N) ((Z+N+1)'(P) & (1 << (Z+N+1) - 1))
|
||||
`endif
|
||||
|
||||
`define PRINT(N) initial #P $display(`"%b bit N is set`", P);
|
||||
|
||||
module mod;
|
||||
parameter unsigned P = 1;
|
||||
parameter Z = 0;
|
||||
|
||||
if (!Z) begin : blk1
|
||||
if (`CHECK(0)) `PRINT(0)
|
||||
else if (`CHECK(1)) `PRINT(1)
|
||||
else if (`CHECK(2)) `PRINT(2)
|
||||
end
|
||||
|
||||
if (!Z) begin : blk2
|
||||
genvar i;
|
||||
if (`CHECK(3))
|
||||
`PRINT(3)
|
||||
else
|
||||
for (i = 1; i == 1 && `CHECK(4); i = i + 1)
|
||||
`PRINT(4)
|
||||
end
|
||||
|
||||
if (!Z) begin : blk3
|
||||
wire signed x = 1;
|
||||
`ifdef REF
|
||||
wire [P - 1:0] tmp = x;
|
||||
wire [7:0] y = tmp;
|
||||
`else
|
||||
wire [7:0] y = $unsigned(P'(x));
|
||||
`endif
|
||||
end
|
||||
wire [7:0] x = blk3.y;
|
||||
initial #P $display("%b x = %b", P, x);
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
`define REF
|
||||
`include "cast_top_item.sv"
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
module top;
|
||||
genvar i;
|
||||
generate
|
||||
for (i = 0; i < 32; i = i + 1)
|
||||
mod #(i) m();
|
||||
endgenerate
|
||||
endmodule
|
||||
|
|
@ -1,17 +1,20 @@
|
|||
module top;
|
||||
generate
|
||||
for (genvar i = 1; i < 5; ++i) begin
|
||||
localparam A = $unsigned(i'(1'sb1));
|
||||
localparam B = $unsigned((i + 5)'(1'sb1));
|
||||
initial begin
|
||||
integer x, y;
|
||||
x = $unsigned(i'(1'sb1));
|
||||
y = $unsigned((i + 5)'(1'sb1));
|
||||
$display("%0d %b %b", i, x, y);
|
||||
$display("%0d %b %b %b %b", i, x, y, A, B);
|
||||
end
|
||||
for (genvar j = 3; j < 6; ++j) begin
|
||||
localparam C = $unsigned((i * j)'(1'sb1));
|
||||
initial begin
|
||||
integer x;
|
||||
x = $unsigned((i * j)'(1'sb1));
|
||||
$display("%0d %0d %b", i, j, x);
|
||||
$display("%0d %0d %b %b", i, j, x, C);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,17 +2,20 @@ module top;
|
|||
generate
|
||||
genvar i, j;
|
||||
for (i = 1; i < 5; i = i + 1) begin
|
||||
localparam [i - 1:0] A = 1'sb1;
|
||||
localparam [i + 4:0] B = 1'sb1;
|
||||
initial begin : foo
|
||||
integer x, y;
|
||||
x = $unsigned(cast_i(1'sb1));
|
||||
y = (1 << (i + 5)) - 1;
|
||||
$display("%0d %b %b", i, x, y);
|
||||
$display("%0d %b %b %b %b", i, x, y, A, B);
|
||||
end
|
||||
for (j = 3; j < 6; j = j + 1) begin
|
||||
localparam [i * j - 1:0] C = 1'sb1;
|
||||
initial begin : bar
|
||||
integer x;
|
||||
x = (1 << (i * j)) - 1;
|
||||
$display("%0d %0d %b", i, j, x);
|
||||
$display("%0d %0d %b %b", i, j, x, C);
|
||||
end
|
||||
end
|
||||
function signed [i-1:0] cast_i;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
module mod(
|
||||
output wire [31:0] out
|
||||
);
|
||||
parameter P = 0;
|
||||
if (P == 1) begin : blk1
|
||||
wire w [2];
|
||||
end
|
||||
else if (P == 2) begin : blk2
|
||||
wire x [3];
|
||||
end
|
||||
else if (P == 3) begin : blk3
|
||||
wire y [5];
|
||||
end
|
||||
else begin : blk4
|
||||
wire z [7];
|
||||
end
|
||||
if (P == 1)
|
||||
assign out = $bits(blk1.w);
|
||||
else if (P == 2)
|
||||
assign out = $bits(blk2.x);
|
||||
else if (P == 3)
|
||||
assign out = $bits(blk3.y);
|
||||
else
|
||||
assign out = $bits(blk4.z);
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
module mod(
|
||||
output wire [31:0] out
|
||||
);
|
||||
parameter P = 0;
|
||||
if (P == 1)
|
||||
assign out = 2;
|
||||
else if (P == 2)
|
||||
assign out = 3;
|
||||
else if (P == 3)
|
||||
assign out = 5;
|
||||
else
|
||||
assign out = 7;
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
module top;
|
||||
wire [31:0] out1, out2, out3, out4;
|
||||
mod #(1) m1(out1);
|
||||
mod #(2) m2(out2);
|
||||
mod #(3) m3(out3);
|
||||
mod #(4) m4(out4);
|
||||
endmodule
|
||||
Loading…
Reference in New Issue