Commit fb5fd393 by Zachary Snow

support for inside expression ranges and wildcards

parent 96fe986b
......@@ -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
......
{- 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
......
{- 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:
......
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
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
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