mirror of https://github.com/zachjs/sv2v.git
fix internal interpretation of negative number literals
- detect and forbid non-positive size casts - detect and forbid negative struct pattern literal indices - avoid invalid constant folding of negative based literals
This commit is contained in:
parent
7e9fb3379c
commit
59d37468a4
|
|
@ -1,3 +1,8 @@
|
|||
## Unreleased
|
||||
|
||||
* Non-positive integer size casts are now detected and forbidden
|
||||
* Negative indices in struct pattern literals are now detected and forbidden
|
||||
|
||||
## v0.0.8
|
||||
|
||||
Future releases will have complete change logs.
|
||||
|
|
|
|||
|
|
@ -110,12 +110,17 @@ traverseExprM other =
|
|||
traverseSinglyNestedExprsM traverseExprM other
|
||||
|
||||
convertCastM :: Expr -> Expr -> Bool -> SC Expr
|
||||
convertCastM (Number size) _ _
|
||||
| maybeInt == Nothing = illegal "an integer"
|
||||
| int <= 0 = illegal "a positive integer"
|
||||
where
|
||||
maybeInt = numberToInteger size
|
||||
Just int = maybeInt
|
||||
illegal s = error $ "size cast width " ++ show size ++ " is not " ++ s
|
||||
convertCastM (Number size) (Number value) signed =
|
||||
return $ Number $
|
||||
case numberToInteger size of
|
||||
Just size' -> numberCast signed (fromIntegral size') value
|
||||
Nothing -> error $ "size cast width " ++ show size
|
||||
++ " is not an integer"
|
||||
numberCast signed (fromIntegral size') value
|
||||
where Just size' = numberToInteger size
|
||||
convertCastM size value signed = do
|
||||
value' <- traverseExprM value
|
||||
sizeUsesLocalVars <- embedScopes usesLocalVars size
|
||||
|
|
@ -177,11 +182,8 @@ castFnName size signed =
|
|||
"sv2v_cast_" ++ sizeStr ++ suffix
|
||||
where
|
||||
sizeStr = case size of
|
||||
Number n ->
|
||||
case numberToInteger n of
|
||||
Just v -> show v
|
||||
_ -> error $ "size cast width " ++ show n
|
||||
++ " is not an integer"
|
||||
Number n -> show v
|
||||
where Just v = numberToInteger n
|
||||
_ -> shortHash size
|
||||
suffix = if signed then "_signed" else ""
|
||||
|
||||
|
|
|
|||
|
|
@ -177,7 +177,7 @@ pattern NegDec :: Integer -> Expr
|
|||
pattern NegDec n <- UniOp UniSub (Dec n)
|
||||
|
||||
pattern Bas :: Integer -> Expr
|
||||
pattern Bas n <- Number (Based _ _ _ n 0)
|
||||
pattern Bas n <- Number (Based _ False _ n 0)
|
||||
|
||||
|
||||
-- returns the size of a range
|
||||
|
|
|
|||
|
|
@ -229,7 +229,8 @@ convertExpr (struct @ (Struct _ fields [])) (Pattern itemsOrig) =
|
|||
isNumbered (Right (Number n)) =
|
||||
if maybeIndex == Nothing
|
||||
then error msgNonInteger
|
||||
else index < length fieldNames || error msgOutOfBounds
|
||||
else 0 <= index && index < length fieldNames
|
||||
|| error msgOutOfBounds
|
||||
where
|
||||
maybeIndex = fmap fromIntegral $ numberToInteger n
|
||||
Just index = maybeIndex
|
||||
|
|
|
|||
|
|
@ -128,6 +128,9 @@ traverseExprM other =
|
|||
|
||||
-- carry forward the signedness of the expression when cast to the given size
|
||||
elaborateSizeCast :: Expr -> Expr -> ST Expr
|
||||
elaborateSizeCast (Number size) _ | Just 0 == numberToInteger size =
|
||||
-- special case because zero-width ranges cannot be represented
|
||||
error $ "size cast width " ++ show size ++ " is not a positive integer"
|
||||
elaborateSizeCast size value = do
|
||||
t <- typeof value
|
||||
force <- isStringParam value
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ module Language.SystemVerilog.AST.Number
|
|||
, bitToVK
|
||||
) where
|
||||
|
||||
import Data.Bits (shiftL)
|
||||
import Data.Bits ((.&.), shiftL)
|
||||
import Data.Char (digitToInt, intToDigit, toLower)
|
||||
import Data.List (elemIndex)
|
||||
import Text.Read (readMaybe)
|
||||
|
|
@ -220,8 +220,13 @@ numberToInteger :: Number -> Maybe Integer
|
|||
numberToInteger (UnbasedUnsized Bit1) = Just 1
|
||||
numberToInteger (UnbasedUnsized Bit0) = Just 0
|
||||
numberToInteger UnbasedUnsized{} = Nothing
|
||||
numberToInteger (Decimal _ _ num) = Just num
|
||||
numberToInteger (Based _ _ _ num 0) = Just num
|
||||
numberToInteger (Decimal sz sg num)
|
||||
| not sg || num .&. pow == 0 = Just num
|
||||
| num == 1 = Just $ -1
|
||||
| otherwise = Just $ negate $ num - pow
|
||||
where pow = 2 ^ (abs sz - 1)
|
||||
numberToInteger (Based sz sg _ num 0) =
|
||||
numberToInteger $ Decimal sz sg num
|
||||
numberToInteger Based{} = Nothing
|
||||
|
||||
-- return the number of bits in a number (i.e. ilog2)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,10 @@ module top;
|
|||
|
||||
$display("args %b", $size(RamPair, 1));
|
||||
$display("args %b", $size(RamPair, 1'b1));
|
||||
$display("args %b", $size(RamPair, 1'sb1));
|
||||
$display("args %b", $size(RamPair, 2'sb1));
|
||||
$display("args %b", $size(RamPair, 2'sb01));
|
||||
$display("args %b", $size(RamPair, 2'sb11));
|
||||
$display("args %b", $size(RamPair, '1));
|
||||
$display("args %b", $size(RamPair, 'o1));
|
||||
$display("args %b", $size(RamPair, 1'h1));
|
||||
|
|
|
|||
|
|
@ -37,6 +37,10 @@ module top;
|
|||
|
||||
$display("args %b", 2);
|
||||
$display("args %b", 2);
|
||||
$display("args %b", 1'bx);
|
||||
$display("args %b", 2);
|
||||
$display("args %b", 2);
|
||||
$display("args %b", 1'bx);
|
||||
$display("args %b", 2);
|
||||
$display("args %b", 2);
|
||||
$display("args %b", 2);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
// pattern: size cast width 1'sb1 is not a positive integer
|
||||
module top;
|
||||
initial $display((1'sb1)'(2));
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
// pattern: size cast width 2'sb11 is not a positive integer
|
||||
module top;
|
||||
initial $display((2'sb11)'(2));
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
// pattern: size cast width 1'sb1 is not a positive integer
|
||||
module top;
|
||||
wire x = 0;
|
||||
initial $display((1'sb1)'(x));
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
// pattern: size cast width 2'sb11 is not a positive integer
|
||||
module top;
|
||||
wire x = 0;
|
||||
initial $display((2'sb11)'(x));
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
// pattern: size cast width 1'bx is not an integer
|
||||
module top;
|
||||
wire x = 0;
|
||||
initial $display((1'bx)'(x));
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
// pattern: size cast width 0 is not a positive integer
|
||||
module top;
|
||||
initial $display((0)'(2));
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
// pattern: size cast width 0 is not a positive integer
|
||||
module top;
|
||||
wire x = 0;
|
||||
initial $display((0)'(x));
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
// pattern: pattern index -1 is out of bounds for struct packed \{..logic x;.\}
|
||||
module top;
|
||||
struct packed {
|
||||
logic x;
|
||||
} s = '{ 1'sb1: 1 };
|
||||
endmodule
|
||||
Loading…
Reference in New Issue