From 9bc946ce7e4377dc2c7cf093fbfe5c588175124b Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Mon, 12 Jul 2021 19:32:50 -0400 Subject: [PATCH] support streaming concatenations in task and function arguments --- src/Convert/Stream.hs | 42 ++++++++++++++++++++++++++++--- test/core/stream.sv | 57 +++++++++++++++++++++++++++++++++++++++++++ test/core/stream.v | 50 ++++++++++++++++++++++++++++++++++--- 3 files changed, 142 insertions(+), 7 deletions(-) diff --git a/src/Convert/Stream.hs b/src/Convert/Stream.hs index 67f0fbc..5489e3a 100644 --- a/src/Convert/Stream.hs +++ b/src/Convert/Stream.hs @@ -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 diff --git a/test/core/stream.sv b/test/core/stream.sv index 9f25c4c..8a96942 100644 --- a/test/core/stream.sv +++ b/test/core/stream.sv @@ -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 diff --git a/test/core/stream.v b/test/core/stream.v index a6cb6c2..078b252 100644 --- a/test/core/stream.v +++ b/test/core/stream.v @@ -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