mirror of https://github.com/zachjs/sv2v.git
support for inside expression ranges and wildcards
This commit is contained in:
parent
96fe986b2d
commit
fb5fd39388
|
|
@ -19,6 +19,7 @@ import qualified Convert.Enum
|
|||
import qualified Convert.ForDecl
|
||||
import qualified Convert.Foreach
|
||||
import qualified Convert.FuncRet
|
||||
import qualified Convert.Inside
|
||||
import qualified Convert.Interface
|
||||
import qualified Convert.IntTypes
|
||||
import qualified Convert.Jump
|
||||
|
|
@ -43,6 +44,7 @@ import qualified Convert.UnbasedUnsized
|
|||
import qualified Convert.Unique
|
||||
import qualified Convert.UnpackedArray
|
||||
import qualified Convert.Unsigned
|
||||
import qualified Convert.Wildcard
|
||||
|
||||
type Phase = [AST] -> [AST]
|
||||
|
||||
|
|
@ -56,6 +58,7 @@ phases excludes =
|
|||
, Convert.ForDecl.convert
|
||||
, Convert.FuncRet.convert
|
||||
, Convert.EmptyArgs.convert
|
||||
, Convert.Inside.convert
|
||||
, Convert.IntTypes.convert
|
||||
, Convert.KWArgs.convert
|
||||
, Convert.LogOp.convert
|
||||
|
|
@ -74,6 +77,7 @@ phases excludes =
|
|||
, Convert.UnpackedArray.convert
|
||||
, Convert.Unsigned.convert
|
||||
, Convert.SignCast.convert
|
||||
, Convert.Wildcard.convert
|
||||
, Convert.Package.convert
|
||||
, Convert.Enum.convert
|
||||
, Convert.NestPI.convert
|
||||
|
|
|
|||
|
|
@ -0,0 +1,46 @@
|
|||
{- 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) =
|
|||
where
|
||||
items' = map mapItem items
|
||||
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) =
|
||||
(t, MinTypMax a' b' c')
|
||||
where
|
||||
|
|
|
|||
|
|
@ -428,6 +428,12 @@ traverseNestedExprsM mapper = exprMapper
|
|||
typeOrExprMapper (Left t) = return $ Left t
|
||||
typeOrExprMapper (Right e) =
|
||||
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 (Number s) = return $ Number s
|
||||
em (Time s) = return $ Time s
|
||||
|
|
@ -487,6 +493,10 @@ traverseNestedExprsM mapper = exprMapper
|
|||
let names = map fst l
|
||||
exprs <- mapM exprMapper $ map snd l
|
||||
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
|
||||
e1' <- exprMapper e1
|
||||
e2' <- exprMapper e2
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
{- 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
|
|||
( Expr (..)
|
||||
, Range
|
||||
, TypeOrExpr
|
||||
, ExprOrRange
|
||||
, Args (..)
|
||||
, PartSelectMode (..)
|
||||
, DimsFn (..)
|
||||
|
|
@ -34,6 +35,7 @@ import {-# SOURCE #-} Language.SystemVerilog.AST.Type
|
|||
type Range = (Expr, Expr)
|
||||
|
||||
type TypeOrExpr = Either Type Expr
|
||||
type ExprOrRange = Either Expr Range
|
||||
|
||||
data Expr
|
||||
= String String
|
||||
|
|
@ -55,6 +57,7 @@ data Expr
|
|||
| DimFn DimFn TypeOrExpr Expr
|
||||
| Dot Expr Identifier
|
||||
| Pattern [(Identifier, Expr)]
|
||||
| Inside Expr [ExprOrRange]
|
||||
| MinTypMax Expr Expr Expr
|
||||
| Nil
|
||||
deriving (Eq, Ord)
|
||||
|
|
@ -79,6 +82,12 @@ instance Show Expr where
|
|||
show (Cast tore e ) = printf "%s'(%s)" (showEither tore) (show e)
|
||||
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 (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 ) =
|
||||
printf "'{\n%s\n}" (indent $ intercalate ",\n" $ map showPatternItem l)
|
||||
where
|
||||
|
|
|
|||
|
|
@ -1095,6 +1095,13 @@ TypeOrExpr :: { TypeOrExpr }
|
|||
: TypeNonIdent { Left $1 }
|
||||
| Expr { Right $1 }
|
||||
|
||||
OpenRangeList :: { [ExprOrRange] }
|
||||
: ValueRange { [$1] }
|
||||
| OpenRangeList "," ValueRange { $1 ++ [$3] }
|
||||
ValueRange :: { ExprOrRange }
|
||||
: Expr { Left $1 }
|
||||
| Range { Right $1 }
|
||||
|
||||
Expr :: { Expr }
|
||||
: "(" Expr ")" { $2 }
|
||||
| String { String $1 }
|
||||
|
|
@ -1120,7 +1127,7 @@ Expr :: { Expr }
|
|||
| "'" "{" PatternItems "}" { Pattern $3 }
|
||||
| "{" StreamOp StreamSize Concat "}" { Stream $2 $3 $4 }
|
||||
| "{" 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 }
|
||||
-- binary expressions
|
||||
| Expr "||" Expr { BinOp LogOr $1 $3 }
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ executable sv2v
|
|||
Convert.ForDecl
|
||||
Convert.Foreach
|
||||
Convert.FuncRet
|
||||
Convert.Inside
|
||||
Convert.Interface
|
||||
Convert.IntTypes
|
||||
Convert.Jump
|
||||
|
|
@ -90,6 +91,7 @@ executable sv2v
|
|||
Convert.Unique
|
||||
Convert.UnpackedArray
|
||||
Convert.Unsigned
|
||||
Convert.Wildcard
|
||||
-- sv2v CLI modules
|
||||
Job
|
||||
ghc-options:
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
module top;
|
||||
|
||||
initial
|
||||
for (logic [1:0] a = 0; a < 3; a++) begin
|
||||
if (a inside {2'b01, 2'b00})
|
||||
|
|
@ -6,4 +7,37 @@ module top;
|
|||
if (a inside {2'b10})
|
||||
$display("buzz");
|
||||
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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
module top;
|
||||
|
||||
initial begin : foo
|
||||
reg [1:0] a;
|
||||
for (a = 0; a < 3; a++) begin
|
||||
|
|
@ -8,4 +9,38 @@ module top;
|
|||
$display("buzz");
|
||||
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
|
||||
|
|
|
|||
Loading…
Reference in New Issue