Commit 2bc2eb59 by Zachary Snow

advanced typeof support

- most binary operators
- ternary expressions
- bitwise negation
- number literals
- size casts
- concat and repeat expressions
parent d0a6b0f5
......@@ -12,7 +12,9 @@
module Convert.TypeOf (convert) where
import Control.Monad.State
import Data.List (elemIndex)
import Data.Maybe (fromMaybe, mapMaybe)
import Data.Int (Int32)
import qualified Data.Map.Strict as Map
import Convert.Traverse
......@@ -71,6 +73,11 @@ traverseTypeM (TypeOf expr) = typeof expr
traverseTypeM other = return other
typeof :: Expr -> State Info Type
typeof (Number n) =
return $ IntegerVector TLogic sg [r]
where
(size, sg) = parseNumber n
r = (Number $ show (size - 1), Number "0")
typeof (orig @ (Ident x)) = do
res <- gets $ Map.lookup x
return $ fromMaybe (TypeOf orig) res
......@@ -93,9 +100,71 @@ typeof (orig @ (Range e mode r)) = do
NonIndexed -> snd r
IndexedPlus -> BinOp Sub (uncurry (BinOp Add) r) (Number "1")
IndexedMinus -> BinOp Add (uncurry (BinOp Sub) r) (Number "1")
typeof (BinOp Add e Number{}) = typeof e
typeof (orig @ (Cast (Right (Ident x)) _)) = do
typeMap <- get
if Map.member x typeMap
then return $ typeOfSize (Ident x)
else return $ TypeOf orig
typeof (Cast (Right s) _) = return $ typeOfSize s
typeof (UniOp BitNot e ) = typeof e
typeof (BinOp Pow e _) = typeof e
typeof (BinOp ShiftL e _) = typeof e
typeof (BinOp ShiftR e _) = typeof e
typeof (BinOp ShiftAL e _) = typeof e
typeof (BinOp ShiftAR e _) = typeof e
typeof (BinOp Add a b) = return $ largerSizeType a b
typeof (BinOp Sub a b) = return $ largerSizeType a b
typeof (BinOp Mul a b) = return $ largerSizeType a b
typeof (BinOp Div a b) = return $ largerSizeType a b
typeof (BinOp Mod a b) = return $ largerSizeType a b
typeof (BinOp BitAnd a b) = return $ largerSizeType a b
typeof (BinOp BitXor a b) = return $ largerSizeType a b
typeof (BinOp BitXnor a b) = return $ largerSizeType a b
typeof (BinOp BitOr a b) = return $ largerSizeType a b
typeof (Mux _ a b) = return $ largerSizeType a b
typeof (Concat exprs) = return $ typeOfSize $ concatSize exprs
typeof (Repeat reps exprs) = return $ typeOfSize size
where size = BinOp Mul reps (concatSize exprs)
typeof other = return $ TypeOf other
-- determines the size and sign of a number literal
parseNumber :: String -> (Int32, Signing)
parseNumber s =
case elemIndex '\'' s of
Nothing -> (32, Signed)
Just 0 -> parseNumber $ '3' : '2' : s
Just idx -> (size, signing)
where
Just size = readNumber $ take idx s
signing = case drop (idx + 1) s of
's' : _ -> Signed
_ -> Unsigned
-- produces a type large enough to hold either expression
largerSizeType :: Expr -> Expr -> Type
largerSizeType a b =
typeOfSize larger
where
sizeof = DimsFn FnBits . Right
cond = BinOp Ge (sizeof a) (sizeof b)
larger = Mux cond (sizeof a) (sizeof b)
-- returns the total size of concatenated list of expressions
concatSize :: [Expr] -> Expr
concatSize exprs =
foldl (BinOp Add) (Number "0") $
map sizeof exprs
where
sizeof = DimsFn FnBits . Right
-- produces a generic type of the given size
typeOfSize :: Expr -> Type
typeOfSize size =
IntegerVector TLogic sg [(hi, Number "0")]
where
sg = Unspecified -- suitable for now
hi = BinOp Sub size (Number "1")
-- combines a type with unpacked ranges
injectRanges :: Type -> [Range] -> Type
injectRanges t [] = t
......
......@@ -11,7 +11,9 @@ module top;
initial begin
type(f(0)) x = f(0);
type(x) y = ~x;
$display("%b", x);
$display("%b", y);
$display("%b", $bits(x));
$display("%b", $bits(type(x)));
$display("%b", $bits(logic [0:1+$bits(type(x))]));
......@@ -19,4 +21,43 @@ module top;
void'(f(0));
t(1);
end
parameter FLAG = 1;
initial begin
logic [4:1] x = 4'b1011;
type(x ^ 3'b111) y = x ^ 3'b111;
type(x ^ 5'b11111) z = x ^ 5'b11111;
type({8 {x}}) a = {8 {x}};
type({x, y}) b = {x, y};
type(FLAG ? x : y) c = FLAG ? x : y;
type(!FLAG ? x : y) d = !FLAG ? x : y;
$display("%b %d %d", x, $left(x), $right(x));
$display("%b %d %d", y, $left(y), $right(y));
$display("%b %d %d", z, $left(z), $right(z));
$display("%b %d %d", a, $left(a), $right(a));
$display("%b %d %d", b, $left(b), $right(b));
$display("%b %d %d", c, $left(c), $right(c));
$display("%b %d %d", d, $left(d), $right(d));
end
parameter W = 4;
initial begin
logic [W-1:0] x = 4'hA;
type(FLAG ? x : '1) y = FLAG ? x : '1;
type(!FLAG ? y : '1) z = !FLAG ? y : '1;
$display("%b %d %d", x, $left(x), $right(x));
$display("%b %d %d", y, $left(y), $right(y));
$display("%b %d %d", z, $left(z), $right(z));
end
initial begin
type(1) w = 1;
type(-1) x = -1;
type(32'hffff_ffff) y = 32'hffff_ffff;
type(32'shffff_ffff) z = 32'shffff_ffff;
$display("%b %d %d %d", w, w, $left(w), $right(w));
$display("%b %d %d %d", x, x, $left(x), $right(x));
$display("%b %d %d %d", y, y, $left(y), $right(y));
$display("%b %d %d %d", z, z, $left(z), $right(z));
end
endmodule
......@@ -12,9 +12,11 @@ module top;
endtask
initial begin : block
reg x;
reg x, y;
x = f(0);
y = ~x;
$display("%b", x);
$display("%b", y);
$display("%b", 32'd1);
$display("%b", 32'd1);
$display("%b", 32'd3);
......@@ -22,4 +24,52 @@ module top;
x = f(0);
t(1);
end
parameter FLAG = 1;
initial begin : block2
reg [4:1] x;
reg [3:0] y;
reg [4:0] z;
reg [31:0] a;
reg [7:0] b;
reg [3:0] c, d;
x = 4'b1011;
y = x ^ 3'b111;
z = x ^ 5'b11111;
a = {8 {x}};
b = {x, y};
c = FLAG ? x : y;
d = !FLAG ? x : y;
$display("%b %d %d", x, 4, 1);
$display("%b %d %d", y, 3, 0);
$display("%b %d %d", z, 4, 0);
$display("%b %d %d", a, 31, 0);
$display("%b %d %d", b, 7, 0);
$display("%b %d %d", c, 3, 0);
$display("%b %d %d", d, 3, 0);
end
parameter W = 4;
initial begin : block3
reg [W-1:0] x, y, z;
x = 4'hA;
y = FLAG ? x : 4'hF;
z = !FLAG ? y : 4'hF;
$display("%b %d %d", x, W-1, 0);
$display("%b %d %d", y, W-1, 0);
$display("%b %d %d", z, W-1, 0);
end
initial begin : block4
integer w, x, z;
reg [31:0] y;
w = 1;
x = -1;
y = 32'hffff_ffff;
z = 32'shffff_ffff;
$display("%b %d %d %d", w, w, 31, 0);
$display("%b %d %d %d", x, x, 31, 0);
$display("%b %d %d %d", y, y, 31, 0);
$display("%b %d %d %d", z, z, 31, 0);
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