Commit 59d37468 by Zachary Snow

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
parent 7e9fb337
## 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);
......
// pattern: size cast width 1'sb1 is not a positive integer
module top;
initial $display((1'sb1)'(2));
endmodule
// pattern: size cast width 2'sb11 is not a positive integer
module top;
initial $display((2'sb11)'(2));
endmodule
// pattern: size cast width 1'sb1 is not a positive integer
module top;
wire x = 0;
initial $display((1'sb1)'(x));
endmodule
// pattern: size cast width 2'sb11 is not a positive integer
module top;
wire x = 0;
initial $display((2'sb11)'(x));
endmodule
// pattern: size cast width 1'bx is not an integer
module top;
wire x = 0;
initial $display((1'bx)'(x));
endmodule
// pattern: size cast width 0 is not a positive integer
module top;
initial $display((0)'(2));
endmodule
// pattern: size cast width 0 is not a positive integer
module top;
wire x = 0;
initial $display((0)'(x));
endmodule
// pattern: pattern index -1 is out of bounds for struct packed \{..logic x;.\}
module top;
struct packed {
logic x;
} s = '{ 1'sb1: 1 };
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