Commit 9bc946ce by Zachary Snow

support streaming concatenations in task and function arguments

parent 2e06d45c
......@@ -6,6 +6,8 @@
module Convert.Stream (convert) where
import Control.Monad (zipWithM)
import Convert.Scoper
import Convert.Traverse
import Language.SystemVerilog.AST
......@@ -36,6 +38,8 @@ traverseDeclM (Variable d t x [] (expr @ (Stream StreamL chunk exprs))) = do
fnName = streamerFuncName x
func = streamerFunc fnName chunk (TypeOf $ Concat exprs) t
expr' = Call (Ident fnName) (Args [Concat exprs] [])
traverseDeclM (Variable d t x a expr) =
traverseExprM expr >>= return . Variable d t x a
traverseDeclM decl @ Net{} = traverseNetAsVarM traverseDeclM decl
traverseDeclM decl = return decl
......@@ -53,15 +57,45 @@ traverseModuleItemM (Assign opt (LHSStream StreamL chunk lhss) expr) =
Assign opt (LHSConcat lhss)
(Stream StreamL chunk [expr])
traverseModuleItemM (Assign opt lhs expr) =
return $ Assign opt lhs' expr'
traverseExprM expr' >>= return . Assign opt lhs'
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
traverseStmtM (Subroutine fn (Args args [])) = do
args' <- traverseCall fn args
return $ Subroutine fn $ Args args' []
traverseStmtM (Asgn op mt lhs expr) = do
expr' <- traverseExprM expr
return $ traverseAsgn (lhs, expr') (Asgn op mt)
traverseStmtM stmt = traverseStmtExprsM traverseExprM stmt
-- replace streaming concatenations in function arguments
traverseExprM :: Expr -> Scoper () Expr
traverseExprM (Call fn (Args args [])) = do
args' <- traverseCall fn args
return $ Call fn $ Args args' []
traverseExprM expr = traverseSinglyNestedExprsM traverseExprM expr
traverseCall :: Expr -> [Expr] -> Scoper () [Expr]
traverseCall fn = zipWithM wrapper ([0..] :: [Int])
where wrapper = traverseCallArg . TypeOf . Dot fn . show
-- task and function arguments are "assignment-like contexts"
traverseCallArg :: Type -> Expr -> Scoper () Expr
traverseCallArg t expr@(Stream op _ _) = do
inProcedure <- withinProcedureM
if inProcedure && op == StreamL
then injectDecl decl >> return (Ident tmp)
else do
decl' <- traverseDeclM decl
let Variable _ _ _ _ expr' = decl'
return expr'
where
tmp = "_arg_tmp_" ++ shortHash (t, expr)
decl = Variable Local t tmp [] expr
traverseCallArg _ arg = traverseExprM arg
-- produces a function used to capture an inline streaming concatenation
streamerFunc :: Identifier -> Expr -> Type -> Type -> PackageItem
......
......@@ -12,6 +12,17 @@ module top;
$display("packet data = %b", packet.data);
end
function automatic [23:0] indirect;
input [23:0] inp;
indirect = inp;
endfunction
task printer;
input [23:0] inpA;
input [23:0] inpB;
$display("printer(%h, %h)", inpA, inpB);
endtask
initial begin
logic [23:0] temp;
......@@ -39,6 +50,39 @@ module top;
$display("%h", temp);
temp = {<<7{16'h0708}};
$display("%h", temp);
temp = indirect({>>7{16'h0708}});
$display("%h", temp);
temp = indirect({<<7{16'h0708}});
$display("%h", temp);
printer({>>7{16'h0708}}, {<<7{16'h0708}});
end
reg [23:0] init_simple_stream_var = {<<7{16'h0718}};
wire [23:0] init_simple_stream_net = {<<7{16'h0728}};
reg [23:0] init_indirect_stream_var = indirect({<<7{16'h0738}});
wire [23:0] init_indirect_stream_net = indirect({<<7{16'h0748}});
reg [23:0] asgn_simple_stream_var;
wire [23:0] asgn_simple_stream_net;
reg [23:0] asgn_indirect_stream_var;
wire [23:0] asgn_indirect_stream_net;
initial asgn_simple_stream_var = {<<7{16'h0758}};
assign asgn_simple_stream_net = {<<7{16'h0768}};
initial asgn_indirect_stream_var = indirect({<<7{16'h0778}});
assign asgn_indirect_stream_net = indirect({<<7{16'h0788}});
initial begin
#1;
$display("%b", init_simple_stream_var);
$display("%b", init_simple_stream_net);
$display("%b", init_indirect_stream_var);
$display("%b", init_indirect_stream_net);
$display("%b", asgn_simple_stream_var);
$display("%b", asgn_simple_stream_net);
$display("%b", asgn_indirect_stream_var);
$display("%b", asgn_indirect_stream_net);
end
task test_unpack;
......@@ -67,4 +111,17 @@ module top;
test_unpack(24'h12E3B8);
end
logic [0:0] i;
logic [1:0] j;
logic [2:0] k;
logic [5:0] l;
logic [11:0] m;
logic [23:0] in;
assign {<<7{i, j, k, l, m}} = in;
initial begin
#1 in = 24'h060708;
#1 in = 24'hC02375;
#1 in = 24'h12E3B8;
end
endmodule
......@@ -5,6 +5,12 @@ module top;
$display("packet data = %b", {2'b00, 2'b11});
end
task printer;
input [23:0] inpA;
input [23:0] inpB;
$display("printer(%h, %h)", inpA, inpB);
endtask
function automatic [23:0] pack_r_8_24;
input [23:0] in;
integer i;
......@@ -43,12 +49,10 @@ module top;
function automatic [23:0] pack_l_7_24;
input [23:0] in;
integer i;
integer e;
begin
for (i = 0; i < 24; i = i + 7) begin
for (i = 0; i + 7 < 24; i = i + 7) begin
pack_l_7_24[23-i-:7] = in[i+:7];
end
i = i - 7;
pack_l_7_24[0+:24%7] = in[i+:24%7];
end
endfunction
......@@ -67,6 +71,33 @@ module top;
$display("%h", pack_r_7_24(24'h070800));
$display("%h", pack_l_7_24(24'h000708));
$display("%h", pack_r_7_24(24'h070800));
$display("%h", pack_l_7_24(24'h000708));
printer(pack_r_7_24(24'h070800), pack_l_7_24(24'h000708));
end
reg [23:0] init_simple_stream_var = pack_l_7_24(24'h000718);
wire [23:0] init_simple_stream_net = pack_l_7_24(24'h000728);
reg [23:0] init_indirect_stream_var = pack_l_7_24(24'h000738);
wire [23:0] init_indirect_stream_net = pack_l_7_24(24'h000748);
reg [23:0] asgn_simple_stream_var = pack_l_7_24(24'h000758);
wire [23:0] asgn_simple_stream_net = pack_l_7_24(24'h000768);
reg [23:0] asgn_indirect_stream_var = pack_l_7_24(24'h000778);
wire [23:0] asgn_indirect_stream_net = pack_l_7_24(24'h000788);
initial begin
#1;
$display("%b", init_simple_stream_var);
$display("%b", init_simple_stream_net);
$display("%b", init_indirect_stream_var);
$display("%b", init_indirect_stream_net);
$display("%b", asgn_simple_stream_var);
$display("%b", asgn_simple_stream_net);
$display("%b", asgn_indirect_stream_var);
$display("%b", asgn_indirect_stream_net);
end
task test_unpack;
......@@ -97,4 +128,17 @@ module top;
test_unpack(24'h12E3B8);
end
wire [0:0] i;
wire [1:0] j;
wire [2:0] k;
wire [5:0] l;
wire [11:0] m;
reg [23:0] in;
assign {i, j, k, l, m} = pack_l_7_24(in);
initial begin
#1 in = 24'h060708;
#1 in = 24'hC02375;
#1 in = 24'h12E3B8;
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