Commit 2429a2c9 by Zachary Snow

upgraded streaming concatenation conversion

- fix handling of truncation for unpacking
- fix handling of final limited-size chunk
- support unpacking in a declarations with assignments
- support streaming concatenations in continuous assignment
parent 11bb0537
...@@ -6,6 +6,7 @@ ...@@ -6,6 +6,7 @@
module Convert.Stream (convert) where module Convert.Stream (convert) where
import Convert.Scoper
import Convert.Traverse import Convert.Traverse
import Language.SystemVerilog.AST import Language.SystemVerilog.AST
...@@ -13,12 +14,76 @@ convert :: [AST] -> [AST] ...@@ -13,12 +14,76 @@ convert :: [AST] -> [AST]
convert = map $ traverseDescriptions convertDescription convert = map $ traverseDescriptions convertDescription
convertDescription :: Description -> Description convertDescription :: Description -> Description
convertDescription (description @ Part{}) = convertDescription = partScoper
traverseModuleItems (traverseStmts traverseStmt) description traverseDeclM traverseModuleItemM return traverseStmtM
convertDescription other = other
streamerBlock :: Expr -> Expr -> (LHS -> Expr -> Stmt) -> LHS -> Expr -> Stmt traverseDeclM :: Decl -> Scoper () Decl
streamerBlock chunk size asgn output input = traverseDeclM (Variable d t x [] (Stream StreamR _ exprs)) =
return $ Variable d t x [] expr'
where
expr = Concat exprs
expr' = resize exprSize lhsSize expr
lhsSize = DimsFn FnBits $ Left t
exprSize = sizeof expr
traverseDeclM (Variable d t x [] (expr @ (Stream StreamL chunk exprs))) = do
inProcedure <- withinProcedureM
if inProcedure
then return $ Variable d t x [] expr
else do
injectItem $ MIPackageItem func
return $ Variable d t x [] expr'
where
fnName = streamerFuncName x
func = streamerFunc fnName chunk (TypeOf $ Concat exprs) t
expr' = Call (Ident fnName) (Args [Concat exprs] [])
traverseDeclM decl = return decl
traverseModuleItemM :: ModuleItem -> Scoper () ModuleItem
traverseModuleItemM (Assign opt lhs (Stream StreamL chunk exprs)) =
injectItem (MIPackageItem func) >> return (Assign opt lhs expr')
where
fnName = streamerFuncName $ shortHash lhs
t = TypeOf $ lhsToExpr lhs
arg = Concat exprs
func = streamerFunc fnName chunk (TypeOf arg) t
expr' = Call (Ident fnName) (Args [arg] [])
traverseModuleItemM (Assign opt (LHSStream StreamL chunk lhss) expr) =
traverseModuleItemM $
Assign opt (LHSConcat lhss)
(Stream StreamL chunk [expr])
traverseModuleItemM (Assign opt lhs expr) =
return $ Assign opt lhs' expr'
where Asgn AsgnOpEq Nothing lhs' expr' =
traverseAsgn (lhs, expr) (Asgn AsgnOpEq Nothing)
traverseModuleItemM item = return item
traverseStmtM :: Stmt -> Scoper () Stmt
traverseStmtM (Asgn op mt lhs expr) =
return $ traverseAsgn (lhs, expr) (Asgn op mt)
traverseStmtM other = return other
-- produces a function used to capture an inline streaming concatenation
streamerFunc :: Identifier -> Expr -> Type -> Type -> PackageItem
streamerFunc fnName chunk rawInType rawOutType =
Function Automatic outType fnName [decl] [stmt]
where
decl = Variable Input inType "inp" [] Nil
lhs = LHSIdent fnName
expr = Stream StreamL chunk [Ident "inp"]
stmt = traverseAsgn (lhs, expr) (Asgn AsgnOpEq Nothing)
inType = sizedType rawInType
outType = sizedType rawOutType
sizedType :: Type -> Type
sizedType t = IntegerVector TLogic Unspecified [(hi, RawNum 0)]
where hi = BinOp Sub (DimsFn FnBits $ Left t) (RawNum 1)
streamerFuncName :: Identifier -> Identifier
streamerFuncName = (++) "_sv2v_strm_"
-- produces a block corresponding to the given leftward streaming concatenation
streamerBlock :: Expr -> Expr -> Expr -> (LHS -> Expr -> Stmt) -> LHS -> Expr -> Stmt
streamerBlock chunk inSize outSize asgn output input =
Block Seq "" Block Seq ""
[ Variable Local t inp [] input [ Variable Local t inp [] input
, Variable Local t out [] Nil , Variable Local t out [] Nil
...@@ -26,64 +91,72 @@ streamerBlock chunk size asgn output input = ...@@ -26,64 +91,72 @@ streamerBlock chunk size asgn output input =
] ]
[ For inits cmp incr stmt [ For inits cmp incr stmt
, If NoCheck cmp2 stmt2 Null , If NoCheck cmp2 stmt2 Null
, asgn output (Ident out) , asgn output result
] ]
where where
lo = RawNum 0 lo = RawNum 0
hi = BinOp Sub size (RawNum 1) hi = BinOp Sub inSize (RawNum 1)
t = IntegerVector TLogic Unspecified [(hi, lo)] t = IntegerVector TLogic Unspecified [(hi, lo)]
name = streamerBlockName chunk size name = streamerBlockName chunk inSize
inp = name ++ "_inp" inp = name ++ "_inp"
out = name ++ "_out" out = name ++ "_out"
idx = name ++ "_idx" idx = name ++ "_idx"
-- main chunk loop -- main chunk loop
inits = Right [(LHSIdent idx, lo)] inits = Right [(LHSIdent idx, lo)]
cmp = BinOp Lt (Ident idx) base cmp = BinOp Le (Ident idx) (BinOp Sub inSize chunk)
incr = [(LHSIdent idx, AsgnOp Add, chunk)] incr = [(LHSIdent idx, AsgnOp Add, chunk)]
lhs = LHSRange (LHSIdent out) IndexedMinus (BinOp Sub hi (Ident idx), chunk) lhs = LHSRange (LHSIdent out) IndexedMinus (BinOp Sub hi (Ident idx), chunk)
expr = Range (Ident inp) IndexedPlus (Ident idx, chunk) expr = Range (Ident inp) IndexedPlus (Ident idx, chunk)
stmt = Asgn AsgnOpEq Nothing lhs expr stmt = Asgn AsgnOpEq Nothing lhs expr
base = BinOp Mul (BinOp Div size chunk) chunk
-- final chunk loop -- final chunk loop
left = BinOp Sub size base stub = BinOp Mod inSize chunk
lhs2 = LHSRange (LHSIdent out) IndexedMinus (BinOp Sub hi base, left) lhs2 = LHSRange (LHSIdent out) IndexedPlus (RawNum 0, stub)
expr2 = Range (Ident inp) IndexedPlus (base, left) expr2 = Range (Ident inp) IndexedPlus (Ident idx, stub)
stmt2 = Asgn AsgnOpEq Nothing lhs2 expr2 stmt2 = Asgn AsgnOpEq Nothing lhs2 expr2
cmp2 = BinOp Gt left (RawNum 0) cmp2 = BinOp Gt stub (RawNum 0)
-- size mismatch padding
result = resize inSize outSize (Ident out)
streamerBlockName :: Expr -> Expr -> Identifier streamerBlockName :: Expr -> Expr -> Identifier
streamerBlockName chunk size = streamerBlockName chunk size =
"_sv2v_strm_" ++ shortHash (chunk, size) "_sv2v_strm_" ++ shortHash (chunk, size)
traverseStmt :: Stmt -> Stmt -- pad or truncate the right side of an expression
traverseStmt (Asgn op mt lhs expr) = resize :: Expr -> Expr -> Expr -> Expr
traverseAsgn (lhs, expr) (Asgn op mt) resize inSize outSize expr =
traverseStmt other = other Mux
(BinOp Le inSize outSize)
zeroBit :: Expr (BinOp ShiftL expr (BinOp Sub outSize inSize))
zeroBit = Number $ Based 1 False Binary 0 0 (BinOp ShiftR expr (BinOp Sub inSize outSize))
-- rewrite a given assignment if it uses a streaming concatenation
traverseAsgn :: (LHS, Expr) -> (LHS -> Expr -> Stmt) -> Stmt traverseAsgn :: (LHS, Expr) -> (LHS -> Expr -> Stmt) -> Stmt
traverseAsgn (lhs, Stream StreamR _ exprs) constructor = traverseAsgn (lhs, Stream StreamR _ exprs) constructor =
constructor lhs expr constructor lhs $ resize exprSize lhsSize expr
where where
expr = Concat $ exprs ++ [Repeat delta [zeroBit]] expr = Concat exprs
size = DimsFn FnBits $ Right $ lhsToExpr lhs lhsSize = sizeof $ lhsToExpr lhs
exprSize = DimsFn FnBits $ Right (Concat exprs) exprSize = sizeof expr
delta = BinOp Sub size exprSize
traverseAsgn (LHSStream StreamR _ lhss, expr) constructor = traverseAsgn (LHSStream StreamR _ lhss, expr) constructor =
constructor (LHSConcat lhss) expr constructor lhs $ resize exprSize lhsSize expr
traverseAsgn (lhs, Stream StreamL chunk exprs) constructor = do
streamerBlock chunk size constructor lhs expr
where where
expr = Concat $ Repeat delta [zeroBit] : exprs lhs = LHSConcat lhss
size = DimsFn FnBits $ Right $ lhsToExpr lhs lhsSize = sizeof $ lhsToExpr lhs
exprSize = DimsFn FnBits $ Right (Concat exprs) exprSize = sizeof expr
delta = BinOp Sub size exprSize traverseAsgn (lhs, Stream StreamL chunk exprs) constructor =
traverseAsgn (LHSStream StreamL chunk lhss, expr) constructor = do streamerBlock chunk exprSize lhsSize constructor lhs expr
streamerBlock chunk size constructor lhs expr where
expr = Concat exprs
lhsSize = sizeof $ lhsToExpr lhs
exprSize = sizeof expr
traverseAsgn (LHSStream StreamL chunk lhss, expr) constructor =
streamerBlock chunk exprSize lhsSize constructor lhs expr
where where
lhs = LHSConcat lhss lhs = LHSConcat lhss
size = DimsFn FnBits $ Right expr lhsSize = sizeof $ lhsToExpr lhs
exprSize = sizeof expr
traverseAsgn (lhs, expr) constructor = traverseAsgn (lhs, expr) constructor =
constructor lhs expr constructor lhs expr
sizeof :: Expr -> Expr
sizeof = DimsFn FnBits . Right
...@@ -32,9 +32,8 @@ module top; ...@@ -32,9 +32,8 @@ module top;
temp = {>>7{20'h60708}}; temp = {>>7{20'h60708}};
$display("%h", temp); $display("%h", temp);
// TODO: Handle this edge case. temp = {<<7{20'h60708}};
//temp = {<<7{20'h60708}}; $display("%h", temp);
//$display("%h", temp);
temp = {>>7{16'h0708}}; temp = {>>7{16'h0708}};
$display("%h", temp); $display("%h", temp);
......
...@@ -36,14 +36,9 @@ module top; ...@@ -36,14 +36,9 @@ module top;
function automatic [23:0] pack_r_7_24; function automatic [23:0] pack_r_7_24;
input [23:0] in; input [23:0] in;
integer i; integer i;
begin
for (i = 0; i < 24; i = i + 7) begin for (i = 0; i < 24; i = i + 7) begin
pack_r_7_24[i+:7] = in[i+:7]; pack_r_7_24[i+:7] = in[i+:7];
end end
for (i = 0; i < 24; i = i + 7) begin
pack_r_7_24[i+:7] = in[i+:7];
end
end
endfunction endfunction
function automatic [23:0] pack_l_7_24; function automatic [23:0] pack_l_7_24;
input [23:0] in; input [23:0] in;
...@@ -53,10 +48,8 @@ module top; ...@@ -53,10 +48,8 @@ module top;
for (i = 0; i < 24; i = i + 7) begin for (i = 0; i < 24; i = i + 7) begin
pack_l_7_24[23-i-:7] = in[i+:7]; pack_l_7_24[23-i-:7] = in[i+:7];
end end
e = i - 7; i = i - 7;
for (i = 0; i < 24-e; i = i + 1) begin pack_l_7_24[0+:24%7] = in[i+:24%7];
pack_l_7_24[i] = in[i+e];
end
end end
endfunction endfunction
initial begin initial begin
...@@ -70,7 +63,7 @@ module top; ...@@ -70,7 +63,7 @@ module top;
$display("%h", pack_l_7_24(24'h060708)); $display("%h", pack_l_7_24(24'h060708));
$display("%h", pack_r_7_24(24'h607080)); $display("%h", pack_r_7_24(24'h607080));
//$display("%h", pack_l_7_24(24'h0c0708)); $display("%h", pack_l_7_24(24'h0c0708));
$display("%h", pack_r_7_24(24'h070800)); $display("%h", pack_r_7_24(24'h070800));
$display("%h", pack_l_7_24(24'h000708)); $display("%h", pack_l_7_24(24'h000708));
...@@ -105,53 +98,3 @@ module top; ...@@ -105,53 +98,3 @@ module top;
end end
endmodule endmodule
// 060708
// 080706
// 060708
// 10e060
// 060708
// 1038c0
//
// 1 11 010 110001 100000000110
// 0 00 110 111000 010001100000
//
// 00 001 100000 011100001000
// 0 00 010 000000 011100000110
// 0 00 001 100000 011100001000
// 0 00 100 001110 000001100000
// 0 00 001 100000 011100001000
// 0 00 110 000100 000010000011
// 1 10 000 000010 001101110101
// 0 11 101 010010 001111000000
// 1 10 000 000010 001101110101
// 1 01 011 101100 010000000011
// 1 10 000 000010 001101110101
// 0 00 110 111000 010001100000
// 0 00 100 101110 001110111000
// 1 01 110 001110 001100010010
// 0 00 100 101110 001110111000
// 0 00 111 011100 011101001000
// 0 00 100 101110 001110111000
// 0 00 111 011101 110000001001
// 0 00 001 100000 011100001000
// 0 00 010 000000 011100000110
// 0 00 001 100000 011100001000
// 0 00 100 001110 000001100000
// 0 00 001 100000 011100001000
// 0 00 100 000011 100011000000
// 1 10 000 000010 001101110101
// 0 11 101 010010 001111000000
// 1 10 000 000010 001101110101
// 1 01 011 101100 010000000011
// 1 10 000 000010 001101110101
// 1 11 010 110001 100000000110
// 0 00 100 101110 001110111000
// 1 01 110 001110 001100010010
// 0 00 100 101110 001110111000
// 0 00 111 011100 011101001000
// 0 00 100 101110 001110111000
// 0 11 100 010001 111001011000
module Streamer(i, l1, r1, l2, r2);
parameter IN_WIDTH = 0;
parameter OUT_WIDTH = 0;
parameter CHUNK_SIZE = 0;
input wire [IN_WIDTH-1:0] i;
output wire [OUT_WIDTH-1:0] l1;
output wire [OUT_WIDTH-1:0] r1;
output reg [OUT_WIDTH-1:0] l2;
output reg [OUT_WIDTH-1:0] r2;
if (IN_WIDTH <= OUT_WIDTH) begin
wire [OUT_WIDTH-1:0] lA = {<<CHUNK_SIZE{i}};
wire [OUT_WIDTH-1:0] rA = {>>CHUNK_SIZE{i}};
wire [OUT_WIDTH-1:0] lB;
wire [OUT_WIDTH-1:0] rB;
assign lB = {<<CHUNK_SIZE{i}};
assign rB = {>>CHUNK_SIZE{i}};
assign l1 = lA == lB ? lA : 'x;
assign r1 = rA == rB ? rA : 'x;
end
if (OUT_WIDTH <= IN_WIDTH) begin
always @* {<<CHUNK_SIZE{l2}} = i;
always @* {>>CHUNK_SIZE{r2}} = i;
end
endmodule
module Streamer(i, l1, r1, l2, r2);
parameter IN_WIDTH = 0;
parameter OUT_WIDTH = 0;
parameter CHUNK_SIZE = 0;
input wire [IN_WIDTH-1:0] i;
output wire [OUT_WIDTH-1:0] l1;
output wire [OUT_WIDTH-1:0] r1;
output reg [OUT_WIDTH-1:0] l2;
output reg [OUT_WIDTH-1:0] r2;
function [IN_WIDTH-1:0] stream_left;
input [IN_WIDTH-1:0] inp;
integer idx;
localparam remainder = IN_WIDTH % CHUNK_SIZE;
localparam remainder_fake = remainder ? remainder : 1;
begin
for (idx = 0; idx + CHUNK_SIZE <= IN_WIDTH; idx = idx + CHUNK_SIZE)
stream_left[IN_WIDTH - idx - 1 -: CHUNK_SIZE] = inp[idx+:CHUNK_SIZE];
if (remainder)
stream_left[0+:remainder_fake] = inp[idx+:remainder_fake];
end
endfunction
function [OUT_WIDTH-1:0] pad;
input [IN_WIDTH-1:0] inp;
pad = IN_WIDTH > OUT_WIDTH
? inp >> IN_WIDTH - OUT_WIDTH
: inp << OUT_WIDTH - IN_WIDTH
;
endfunction
generate
if (IN_WIDTH <= OUT_WIDTH) begin
assign l1 = pad(stream_left(i));
assign r1 = pad(i);
end
if (OUT_WIDTH <= IN_WIDTH) begin
always @* l2 = pad(stream_left(i));
always @* r2 = pad(i);
end
endgenerate
endmodule
module Tester;
parameter IN_WIDTH = 0;
parameter OUT_WIDTH = 0;
parameter CHUNK_SIZE = 0;
reg [IN_WIDTH-1:0] i;
wire [OUT_WIDTH-1:0] l1, l2;
wire [OUT_WIDTH-1:0] r1, r2;
Streamer #(IN_WIDTH, OUT_WIDTH, CHUNK_SIZE)
streamer(i, l1, r1, l2, r2);
localparam DELAY = 8 * (CHUNK_SIZE + 8 * (OUT_WIDTH + 8 * IN_WIDTH));
initial #DELAY;
integer idx;
initial begin
for (idx = 0; idx < IN_WIDTH; idx = idx + 1) begin
i = 1 << idx;
#1 $display("INW=%0d OUTW=%0d CS=%0d i=%b l1=%b r1=%b l2=%b r2=%b",
IN_WIDTH, OUT_WIDTH, CHUNK_SIZE, i, l1, r1, l2, r2);
end
end
endmodule
module top;
generate
genvar i, o, c;
for (i = 1; i <= 8; i = i + 1)
for (o = 1; o <= 8; o = o + 1)
for (c = 1; c <= i; c = c + 1)
Tester #(i, o, c) tester();
endgenerate
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