mirror of https://github.com/zachjs/sv2v.git
constant folding for size casts of number literals
- standardize number casting - fix extension of casts of unsized literals to 32 bits
This commit is contained in:
parent
3eefd03c8d
commit
103db6741f
|
|
@ -109,22 +109,12 @@ traverseExprM other =
|
|||
traverseSinglyNestedExprsM traverseExprM other
|
||||
|
||||
convertCastM :: Expr -> Expr -> Bool -> ST Expr
|
||||
convertCastM (RawNum size) (RawNum val) signed =
|
||||
return $ Number $ Decimal (fromIntegral size) signed val'
|
||||
where val' = val `mod` (2 ^ size)
|
||||
convertCastM (RawNum size) (Number (Based 1 True Binary a b)) signed =
|
||||
return $ Number $ Based (fromIntegral size) signed Binary
|
||||
(val * a) (val * b)
|
||||
where val = (2 ^ size) - 1
|
||||
convertCastM (RawNum size) (Number (UnbasedUnsized bit)) signed =
|
||||
convertCastM (RawNum size) (Number num) signed
|
||||
where
|
||||
num = Based 1 True Binary a b
|
||||
(a, b) = case bit of
|
||||
Bit0 -> (0, 0)
|
||||
Bit1 -> (1, 0)
|
||||
BitX -> (0, 1)
|
||||
BitZ -> (1, 1)
|
||||
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"
|
||||
convertCastM size value signed = do
|
||||
value' <- traverseExprM value
|
||||
useFn <- embedScopes canUseCastFn size
|
||||
|
|
|
|||
|
|
@ -391,10 +391,8 @@ typeCastUnneeded t1 t2 =
|
|||
|
||||
-- explicitly sizes top level numbers used in arithmetic expressions
|
||||
makeExplicit :: Expr -> Expr
|
||||
makeExplicit (Number (Decimal size signed values)) =
|
||||
Number $ Decimal (abs size) signed values
|
||||
makeExplicit (Number (Based size base signed values kinds)) =
|
||||
Number $ Based (abs size) base signed values kinds
|
||||
makeExplicit (Number n) =
|
||||
Number $ numberCast (numberIsSigned n) (fromIntegral $ numberBitLength n) n
|
||||
makeExplicit (BinOp op e1 e2) =
|
||||
BinOp op (makeExplicit e1) (makeExplicit e2)
|
||||
makeExplicit (UniOp op e) =
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ module Language.SystemVerilog.AST.Number
|
|||
, numberIsSigned
|
||||
, numberIsSized
|
||||
, numberToInteger
|
||||
, numberCast
|
||||
, bitToVK
|
||||
) where
|
||||
|
||||
|
|
@ -332,10 +333,7 @@ instance Semigroup Number where
|
|||
where
|
||||
size = size1 + size2
|
||||
signed = False
|
||||
base =
|
||||
if kinds1 == 0 && kinds2 == 0
|
||||
then min base1 base2
|
||||
else Binary
|
||||
base = selectBase (min base1 base2) values kinds
|
||||
trim = flip mod . (2 ^)
|
||||
values = trim size2 values2 + shiftL (trim size1 values1) size2
|
||||
kinds = trim size2 kinds2 + shiftL (trim size1 kinds1) size2
|
||||
|
|
@ -351,3 +349,67 @@ instance Semigroup Number where
|
|||
Based size signed Hex num 0
|
||||
toBased (UnbasedUnsized bit) =
|
||||
uncurry (Based 1 False Binary) (bitToVK bit)
|
||||
|
||||
-- size cast raw bits with optional sign extension
|
||||
rawCast :: Bool -> Int -> Int -> Integer -> Integer
|
||||
rawCast signed inSize outSize val =
|
||||
if outSize <= inSize then
|
||||
val `mod` (2 ^ outSize)
|
||||
else if signed && val >= 2 ^ (inSize - 1) then
|
||||
valTrim + 2 ^ outSize - 2 ^ inSize
|
||||
else
|
||||
valTrim
|
||||
where valTrim = val `mod` (2 ^ inSize)
|
||||
|
||||
-- check if the based number is valid under the given base
|
||||
checkBase :: Integer -> Integer -> Integer -> Bool
|
||||
checkBase _ _ 0 = True
|
||||
checkBase base v k =
|
||||
-- kind bits in this chunk must all be the same
|
||||
(rK == 0 || rK == base - 1) &&
|
||||
-- if the X/Z, it must be all X or all Z
|
||||
(rK == 0 || rV == 0 || rV == base - 1) &&
|
||||
-- check the next chunk
|
||||
checkBase base qV qK
|
||||
where
|
||||
(qV, rV) = v `divMod` base
|
||||
(qK, rK) = k `divMod` base
|
||||
|
||||
-- select the maximal valid base
|
||||
selectBase :: Base -> Integer -> Integer -> Base
|
||||
selectBase Binary _ _ = Binary
|
||||
selectBase Octal v k =
|
||||
if checkBase 8 v k
|
||||
then Octal
|
||||
else Binary
|
||||
selectBase Hex v k =
|
||||
if checkBase 16 v k
|
||||
then Hex
|
||||
else selectBase Octal v k
|
||||
|
||||
-- utility for size and/or sign casting a number
|
||||
numberCast :: Bool -> Int -> Number -> Number
|
||||
numberCast outSigned outSize (Decimal inSizeRaw inSigned inVal) =
|
||||
Decimal outSize outSigned outVal
|
||||
where
|
||||
inSize = abs inSizeRaw
|
||||
outVal = rawCast inSigned inSize outSize inVal
|
||||
numberCast outSigned outSize (Based inSizeRaw inSigned inBase inVal inKnd) =
|
||||
Based outSize outSigned outBase outVal outKnd
|
||||
where
|
||||
inSize = abs inSizeRaw
|
||||
-- sign extend signed inputs, or unsized literals with a leading X/Z
|
||||
doExtend = inSigned || inKnd >= 2 ^ (inSize - 1) && inSizeRaw < 0
|
||||
outVal = rawCast doExtend inSize outSize inVal
|
||||
outKnd = rawCast doExtend inSize outSize inKnd
|
||||
-- note that we could try patching the upper bits of the result to allow
|
||||
-- the use of a higher base as in 5'(6'ozx), but this should be rare
|
||||
outBase = selectBase inBase outVal outKnd
|
||||
numberCast signed size (UnbasedUnsized bit) =
|
||||
numberCast signed size $
|
||||
uncurry (Based 1 True Binary) $
|
||||
case bit of
|
||||
Bit0 -> (0, 0)
|
||||
Bit1 -> (1, 0)
|
||||
BitX -> (0, 1)
|
||||
BitZ -> (1, 1)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
`define TEST(size, literal) \
|
||||
$display(`"size'(literal) = %b`", size'(literal));
|
||||
module top;
|
||||
initial begin
|
||||
`include "cast_literal.vh"
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
`define TEST(size, literal) \
|
||||
tmp``size = literal; \
|
||||
$display(`"size'(literal) = %b`", tmp``size);
|
||||
module top;
|
||||
initial begin : blk
|
||||
reg [0:0] tmp1; reg [1:0] tmp2; reg [2:0] tmp3; reg [3:0] tmp4; reg [4:0] tmp5;
|
||||
reg [5:0] tmp6; reg [6:0] tmp7; reg [7:0] tmp8; reg [8:0] tmp9; reg [9:0] tmp10;
|
||||
reg [10:0] tmp11; reg [11:0] tmp12; reg [12:0] tmp13; reg [13:0] tmp14; reg [14:0] tmp15;
|
||||
reg [15:0] tmp16; reg [16:0] tmp17; reg [17:0] tmp18; reg [18:0] tmp19; reg [19:0] tmp20;
|
||||
reg [20:0] tmp21; reg [21:0] tmp22; reg [22:0] tmp23; reg [23:0] tmp24; reg [24:0] tmp25;
|
||||
reg [25:0] tmp26; reg [26:0] tmp27; reg [27:0] tmp28; reg [28:0] tmp29; reg [29:0] tmp30;
|
||||
reg [30:0] tmp31; reg [31:0] tmp32; reg [32:0] tmp33; reg [33:0] tmp34; reg [34:0] tmp35;
|
||||
`include "cast_literal.vh"
|
||||
end
|
||||
endmodule
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
`define TEST_ALL(literal) \
|
||||
`TEST(1, literal) `TEST(2, literal) `TEST(3, literal) `TEST(4, literal) `TEST(5, literal) \
|
||||
`TEST(6, literal) `TEST(7, literal) `TEST(8, literal) `TEST(9, literal) `TEST(10, literal) \
|
||||
`TEST(11, literal) `TEST(12, literal) `TEST(13, literal) `TEST(14, literal) `TEST(15, literal) \
|
||||
`TEST(16, literal) `TEST(17, literal) `TEST(18, literal) `TEST(19, literal) `TEST(20, literal) \
|
||||
`TEST(21, literal) `TEST(22, literal) `TEST(23, literal) `TEST(24, literal) `TEST(25, literal) \
|
||||
`TEST(26, literal) `TEST(27, literal) `TEST(28, literal) `TEST(29, literal) `TEST(30, literal) \
|
||||
`TEST(31, literal) `TEST(32, literal) `TEST(33, literal) `TEST(34, literal) `TEST(35, literal)
|
||||
|
||||
`TEST_ALL('d1)
|
||||
`TEST_ALL('sd1)
|
||||
`TEST_ALL(1'sd1)
|
||||
`TEST_ALL(32'sd1)
|
||||
`TEST_ALL('d123)
|
||||
`TEST_ALL('sd123)
|
||||
`TEST_ALL(14'sd123)
|
||||
`TEST_ALL(15'sd123)
|
||||
|
||||
`TEST_ALL('b1)
|
||||
`TEST_ALL('sb1)
|
||||
`TEST_ALL('b10)
|
||||
`TEST_ALL('sb10)
|
||||
`TEST_ALL(1'b1)
|
||||
`TEST_ALL(1'sb1)
|
||||
`TEST_ALL(2'sb1)
|
||||
`TEST_ALL(2'sb11)
|
||||
`TEST_ALL(1'sbx)
|
||||
`TEST_ALL(2'sbx)
|
||||
`TEST_ALL(2'sb0x)
|
||||
`TEST_ALL(2'sbx1)
|
||||
`TEST_ALL(2'sbz0)
|
||||
|
||||
`TEST_ALL(1'so1)
|
||||
`TEST_ALL(2'so1)
|
||||
`TEST_ALL(4'so11)
|
||||
`TEST_ALL(1'sox)
|
||||
`TEST_ALL(2'sox)
|
||||
`TEST_ALL(4'so0x)
|
||||
`TEST_ALL(4'sox1)
|
||||
`TEST_ALL(4'soz0)
|
||||
`TEST_ALL(5'so0x)
|
||||
`TEST_ALL(5'sox1)
|
||||
`TEST_ALL(5'soz0)
|
||||
`TEST_ALL(6'so0x)
|
||||
`TEST_ALL(6'sox1)
|
||||
`TEST_ALL(6'soz0)
|
||||
`TEST_ALL(7'so0x)
|
||||
`TEST_ALL(7'sox1)
|
||||
`TEST_ALL(7'soz0)
|
||||
|
||||
`TEST_ALL('bx)
|
||||
`TEST_ALL('ozx)
|
||||
`TEST_ALL('hxz)
|
||||
`TEST_ALL(1'bx)
|
||||
`TEST_ALL(5'ozx)
|
||||
`TEST_ALL(6'ozx)
|
||||
`TEST_ALL(7'hxz)
|
||||
`TEST_ALL('bzzz1)
|
||||
`TEST_ALL('ozzz1)
|
||||
`TEST_ALL('hzzz1)
|
||||
|
||||
`TEST_ALL(1'ox)
|
||||
`TEST_ALL(1'oz)
|
||||
`TEST_ALL(4'ox0)
|
||||
`TEST_ALL(4'ox1)
|
||||
`TEST_ALL(4'ox2)
|
||||
`TEST_ALL(4'ox3)
|
||||
`TEST_ALL(4'ox4)
|
||||
`TEST_ALL(4'ox5)
|
||||
`TEST_ALL(4'ox6)
|
||||
`TEST_ALL(4'ox7)
|
||||
`TEST_ALL(4'oxx)
|
||||
`TEST_ALL(4'oxz)
|
||||
`TEST_ALL(4'oz0)
|
||||
`TEST_ALL(4'oz1)
|
||||
`TEST_ALL(4'oz2)
|
||||
`TEST_ALL(4'oz3)
|
||||
`TEST_ALL(4'oz4)
|
||||
`TEST_ALL(4'oz5)
|
||||
`TEST_ALL(4'oz6)
|
||||
`TEST_ALL(4'oz7)
|
||||
`TEST_ALL(4'ozx)
|
||||
`TEST_ALL(4'ozz)
|
||||
Loading…
Reference in New Issue