Commit fb5fd393 by Zachary Snow

support for inside expression ranges and wildcards

parent 96fe986b
...@@ -19,6 +19,7 @@ import qualified Convert.Enum ...@@ -19,6 +19,7 @@ import qualified Convert.Enum
import qualified Convert.ForDecl import qualified Convert.ForDecl
import qualified Convert.Foreach import qualified Convert.Foreach
import qualified Convert.FuncRet import qualified Convert.FuncRet
import qualified Convert.Inside
import qualified Convert.Interface import qualified Convert.Interface
import qualified Convert.IntTypes import qualified Convert.IntTypes
import qualified Convert.Jump import qualified Convert.Jump
...@@ -43,6 +44,7 @@ import qualified Convert.UnbasedUnsized ...@@ -43,6 +44,7 @@ import qualified Convert.UnbasedUnsized
import qualified Convert.Unique import qualified Convert.Unique
import qualified Convert.UnpackedArray import qualified Convert.UnpackedArray
import qualified Convert.Unsigned import qualified Convert.Unsigned
import qualified Convert.Wildcard
type Phase = [AST] -> [AST] type Phase = [AST] -> [AST]
...@@ -56,6 +58,7 @@ phases excludes = ...@@ -56,6 +58,7 @@ phases excludes =
, Convert.ForDecl.convert , Convert.ForDecl.convert
, Convert.FuncRet.convert , Convert.FuncRet.convert
, Convert.EmptyArgs.convert , Convert.EmptyArgs.convert
, Convert.Inside.convert
, Convert.IntTypes.convert , Convert.IntTypes.convert
, Convert.KWArgs.convert , Convert.KWArgs.convert
, Convert.LogOp.convert , Convert.LogOp.convert
...@@ -74,6 +77,7 @@ phases excludes = ...@@ -74,6 +77,7 @@ phases excludes =
, Convert.UnpackedArray.convert , Convert.UnpackedArray.convert
, Convert.Unsigned.convert , Convert.Unsigned.convert
, Convert.SignCast.convert , Convert.SignCast.convert
, Convert.Wildcard.convert
, Convert.Package.convert , Convert.Package.convert
, Convert.Enum.convert , Convert.Enum.convert
, Convert.NestPI.convert , Convert.NestPI.convert
......
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- Conversion for `inside` expressions
-
- The expressions are compared to each candidate using the wildcard comparison
- operator. Note that if expression has any Xs or Zs that are not wildcarded in
- the candidate, the results is `1'bx`. As required by the specification, the
- result of each comparison is combined using an OR reduction.
-
- TODO: Add support for array value ranges.
-}
module Convert.Inside (convert) where
import Convert.Traverse
import Language.SystemVerilog.AST
convert :: [AST] -> [AST]
convert =
map $
traverseDescriptions $ traverseModuleItems $
traverseExprs $ traverseNestedExprs convertExpr
convertExpr :: Expr -> Expr
convertExpr (Inside expr valueRanges) =
if length checks == 1
then head checks
else UniOp RedOr $ Concat checks
where
checks = map toCheck valueRanges
toCheck :: ExprOrRange -> Expr
toCheck (Left e) =
Mux
(BinOp TNe rxr lxlxrxr)
(Number "1'bx")
(BinOp WEq expr e)
where
lxl = BinOp BitXor expr expr
rxr = BinOp BitXor e e
lxlxrxr = BinOp BitXor lxl rxr
toCheck (Right (lo, hi)) =
BinOp LogAnd
(BinOp Le lo expr)
(BinOp Ge hi expr)
convertExpr other = other
...@@ -538,6 +538,18 @@ convertAsgn structs types (lhs, expr) = ...@@ -538,6 +538,18 @@ convertAsgn structs types (lhs, expr) =
where where
items' = map mapItem items items' = map mapItem items
mapItem (mx, e) = (mx, snd $ convertSubExpr e) mapItem (mx, e) = (mx, snd $ convertSubExpr e)
convertSubExpr (Inside e l) =
(t, Inside e' l')
where
t = IntegerVector TLogic Unspecified []
(_, e') = convertSubExpr e
l' = map mapItem l
mapItem :: ExprOrRange -> ExprOrRange
mapItem (Left a) = Left $ snd $ convertSubExpr a
mapItem (Right (a, b)) = Right (a', b')
where
(_, a') = convertSubExpr a
(_, b') = convertSubExpr b
convertSubExpr (MinTypMax a b c) = convertSubExpr (MinTypMax a b c) =
(t, MinTypMax a' b' c') (t, MinTypMax a' b' c')
where where
......
...@@ -428,6 +428,12 @@ traverseNestedExprsM mapper = exprMapper ...@@ -428,6 +428,12 @@ traverseNestedExprsM mapper = exprMapper
typeOrExprMapper (Left t) = return $ Left t typeOrExprMapper (Left t) = return $ Left t
typeOrExprMapper (Right e) = typeOrExprMapper (Right e) =
exprMapper e >>= return . Right exprMapper e >>= return . Right
exprOrRangeMapper (Left e) =
exprMapper e >>= return . Left
exprOrRangeMapper (Right (e1, e2)) = do
e1' <- exprMapper e1
e2' <- exprMapper e2
return $ Right (e1', e2')
em (String s) = return $ String s em (String s) = return $ String s
em (Number s) = return $ Number s em (Number s) = return $ Number s
em (Time s) = return $ Time s em (Time s) = return $ Time s
...@@ -487,6 +493,10 @@ traverseNestedExprsM mapper = exprMapper ...@@ -487,6 +493,10 @@ traverseNestedExprsM mapper = exprMapper
let names = map fst l let names = map fst l
exprs <- mapM exprMapper $ map snd l exprs <- mapM exprMapper $ map snd l
return $ Pattern $ zip names exprs return $ Pattern $ zip names exprs
em (Inside e l) = do
e' <- exprMapper e
l' <- mapM exprOrRangeMapper l
return $ Inside e' l'
em (MinTypMax e1 e2 e3) = do em (MinTypMax e1 e2 e3) = do
e1' <- exprMapper e1 e1' <- exprMapper e1
e2' <- exprMapper e2 e2' <- exprMapper e2
......
{- sv2v
- Author: Zachary Snow <zach@zachjs.com>
-
- Conversion for `==?` and `!=?`
-
- `a ==? b` is defined as the bitwise comparison of `a` and `b`, where X and Z
- values in `b` (but not those in `a`) are used as wildcards. We convert `a ==?
- b` to `a ^ b === b ^ b`. This works because any value xor'ed with X or Z
- becomes X.
-
- `!=?` is simply converted as the logical negation of `==?`, which is
- converted as described above.
-}
module Convert.Wildcard (convert) where
import Convert.Traverse
import Language.SystemVerilog.AST
convert :: [AST] -> [AST]
convert =
map $
traverseDescriptions $ traverseModuleItems $
traverseExprs $ traverseNestedExprs convertExpr
convertExpr :: Expr -> Expr
convertExpr (BinOp WEq l r) =
BinOp TEq
(BinOp BitXor r r)
(BinOp BitXor r l)
convertExpr (BinOp WNe l r) =
UniOp LogNot $
convertExpr $
BinOp WEq l r
convertExpr other = other
...@@ -9,6 +9,7 @@ module Language.SystemVerilog.AST.Expr ...@@ -9,6 +9,7 @@ module Language.SystemVerilog.AST.Expr
( Expr (..) ( Expr (..)
, Range , Range
, TypeOrExpr , TypeOrExpr
, ExprOrRange
, Args (..) , Args (..)
, PartSelectMode (..) , PartSelectMode (..)
, DimsFn (..) , DimsFn (..)
...@@ -34,6 +35,7 @@ import {-# SOURCE #-} Language.SystemVerilog.AST.Type ...@@ -34,6 +35,7 @@ import {-# SOURCE #-} Language.SystemVerilog.AST.Type
type Range = (Expr, Expr) type Range = (Expr, Expr)
type TypeOrExpr = Either Type Expr type TypeOrExpr = Either Type Expr
type ExprOrRange = Either Expr Range
data Expr data Expr
= String String = String String
...@@ -55,6 +57,7 @@ data Expr ...@@ -55,6 +57,7 @@ data Expr
| DimFn DimFn TypeOrExpr Expr | DimFn DimFn TypeOrExpr Expr
| Dot Expr Identifier | Dot Expr Identifier
| Pattern [(Identifier, Expr)] | Pattern [(Identifier, Expr)]
| Inside Expr [ExprOrRange]
| MinTypMax Expr Expr Expr | MinTypMax Expr Expr Expr
| Nil | Nil
deriving (Eq, Ord) deriving (Eq, Ord)
...@@ -79,6 +82,12 @@ instance Show Expr where ...@@ -79,6 +82,12 @@ instance Show Expr where
show (Cast tore e ) = printf "%s'(%s)" (showEither tore) (show e) show (Cast tore e ) = printf "%s'(%s)" (showEither tore) (show e)
show (DimsFn f v ) = printf "%s(%s)" (show f) (showEither v) show (DimsFn f v ) = printf "%s(%s)" (show f) (showEither v)
show (DimFn f v e) = printf "%s(%s, %s)" (show f) (showEither v) (show e) show (DimFn f v e) = printf "%s(%s, %s)" (show f) (showEither v) (show e)
show (Inside e l ) = printf "(%s inside { %s })" (show e) (intercalate ", " strs)
where
strs = map showExprOrRange l
showExprOrRange :: ExprOrRange -> String
showExprOrRange (Left x) = show x
showExprOrRange (Right x) = show x
show (Pattern l ) = show (Pattern l ) =
printf "'{\n%s\n}" (indent $ intercalate ",\n" $ map showPatternItem l) printf "'{\n%s\n}" (indent $ intercalate ",\n" $ map showPatternItem l)
where where
......
...@@ -1095,6 +1095,13 @@ TypeOrExpr :: { TypeOrExpr } ...@@ -1095,6 +1095,13 @@ TypeOrExpr :: { TypeOrExpr }
: TypeNonIdent { Left $1 } : TypeNonIdent { Left $1 }
| Expr { Right $1 } | Expr { Right $1 }
OpenRangeList :: { [ExprOrRange] }
: ValueRange { [$1] }
| OpenRangeList "," ValueRange { $1 ++ [$3] }
ValueRange :: { ExprOrRange }
: Expr { Left $1 }
| Range { Right $1 }
Expr :: { Expr } Expr :: { Expr }
: "(" Expr ")" { $2 } : "(" Expr ")" { $2 }
| String { String $1 } | String { String $1 }
...@@ -1120,7 +1127,7 @@ Expr :: { Expr } ...@@ -1120,7 +1127,7 @@ Expr :: { Expr }
| "'" "{" PatternItems "}" { Pattern $3 } | "'" "{" PatternItems "}" { Pattern $3 }
| "{" StreamOp StreamSize Concat "}" { Stream $2 $3 $4 } | "{" StreamOp StreamSize Concat "}" { Stream $2 $3 $4 }
| "{" StreamOp Concat "}" { Stream $2 (Number "1") $3 } | "{" StreamOp Concat "}" { Stream $2 (Number "1") $3 }
| Expr "inside" Concat { foldl1 (BinOp LogOr) $ map (BinOp Eq $1) $3 } | Expr "inside" "{" OpenRangeList "}" { Inside $1 $4 }
| "(" Expr ":" Expr ":" Expr ")" { MinTypMax $2 $4 $6 } | "(" Expr ":" Expr ":" Expr ")" { MinTypMax $2 $4 $6 }
-- binary expressions -- binary expressions
| Expr "||" Expr { BinOp LogOr $1 $3 } | Expr "||" Expr { BinOp LogOr $1 $3 }
......
...@@ -65,6 +65,7 @@ executable sv2v ...@@ -65,6 +65,7 @@ executable sv2v
Convert.ForDecl Convert.ForDecl
Convert.Foreach Convert.Foreach
Convert.FuncRet Convert.FuncRet
Convert.Inside
Convert.Interface Convert.Interface
Convert.IntTypes Convert.IntTypes
Convert.Jump Convert.Jump
...@@ -90,6 +91,7 @@ executable sv2v ...@@ -90,6 +91,7 @@ executable sv2v
Convert.Unique Convert.Unique
Convert.UnpackedArray Convert.UnpackedArray
Convert.Unsigned Convert.Unsigned
Convert.Wildcard
-- sv2v CLI modules -- sv2v CLI modules
Job Job
ghc-options: ghc-options:
......
module top; module top;
initial initial
for (logic [1:0] a = 0; a < 3; a++) begin for (logic [1:0] a = 0; a < 3; a++) begin
if (a inside {2'b01, 2'b00}) if (a inside {2'b01, 2'b00})
...@@ -6,4 +7,37 @@ module top; ...@@ -6,4 +7,37 @@ module top;
if (a inside {2'b10}) if (a inside {2'b10})
$display("buzz"); $display("buzz");
end end
initial $display("A", 3'bz11 inside {3'b?01});
initial $display("B", 3'bz11 inside {3'b1?1});
initial $display("C", 3'bz11 inside {3'b011});
initial $display("D", 3'bz11 inside {3'b1?1, 3'b011});
initial $display("E", 3'bz11 inside {3'b?01, 3'b011});
function test1;
input logic [2:0] inp;
return inp inside {3'b1?1};
endfunction
initial begin
// should match
$display("test1: %b %b", 3'b101, test1(3'b101));
$display("test1: %b %b", 3'b111, test1(3'b111));
$display("test1: %b %b", 3'b1x1, test1(3'b1x1));
$display("test1: %b %b", 3'b1z1, test1(3'b1z1));
// shouldn't match
$display("test1: %b %b", 3'b001, test1(3'b001));
$display("test1: %b %b", 3'b011, test1(3'b011));
$display("test1: %b %b", 3'b0x1, test1(3'b0x1));
$display("test1: %b %b", 3'b0z1, test1(3'b0z1));
end
function test2;
input integer inp;
return inp inside { [16:23], [32:47] };
endfunction
initial begin
for (integer i = 0; i < 64; ++i)
$display("test2(%02d) = %b", i, test2(i));
end
endmodule endmodule
module top; module top;
initial begin : foo initial begin : foo
reg [1:0] a; reg [1:0] a;
for (a = 0; a < 3; a++) begin for (a = 0; a < 3; a++) begin
...@@ -8,4 +9,38 @@ module top; ...@@ -8,4 +9,38 @@ module top;
$display("buzz"); $display("buzz");
end end
end end
initial $display("A", 1'b0);
initial $display("B", 1'bx);
initial $display("C", 1'bx);
initial $display("D", 1'bx);
initial $display("E", 1'bx);
function test1;
input [2:0] inp;
test1 = inp[0] == 1 && inp[2] == 1;
endfunction
initial begin
// should match
$display("test1: %b %b", 3'b101, test1(3'b101));
$display("test1: %b %b", 3'b111, test1(3'b111));
$display("test1: %b %b", 3'b1x1, test1(3'b1x1));
$display("test1: %b %b", 3'b1z1, test1(3'b1z1));
// shouldn't match
$display("test1: %b %b", 3'b001, test1(3'b001));
$display("test1: %b %b", 3'b011, test1(3'b011));
$display("test1: %b %b", 3'b0x1, test1(3'b0x1));
$display("test1: %b %b", 3'b0z1, test1(3'b0z1));
end
function test2;
input integer inp;
test2 = (16 <= inp && inp <= 23) || (32 <= inp && inp <= 47);
endfunction
initial begin : foobar
integer i;
for (i = 0; i < 64; ++i)
$display("test2(%02d) = %b", i, test2(i));
end
endmodule 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