Skip to content

Commit

Permalink
Add LI-2 CFU GCD_CFU_LI2; tidy other CFUs
Browse files Browse the repository at this point in the history
  • Loading branch information
grayresearch committed Jun 4, 2020
1 parent 986712a commit b8eea8d
Show file tree
Hide file tree
Showing 6 changed files with 227 additions and 43 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# Copyright (C) 2019, Gray Research LLC
#
HDRS=cfu.vh
SRCS=tb.v cfu.v popcount.v bnn.v mulacc.v
SRCS=tb.v cfu.v popcount.v bnn.v mulacc.v gcd.v

v/tb: $(HDRS) $(SRCS)
verilator -Wall --cc $(SRCS) --top-module TB --Mdir v --exe tb.cpp
Expand Down
28 changes: 14 additions & 14 deletions bnn.v
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,21 @@

// Test bench
module BNNDotProd32TB #(
parameter CFU_FUNC_ID_W = 5,
parameter CFU_FUNC_ID_W = 1,
parameter CFU_REQ_DATA_W = 32,
parameter CFU_RESP_DATA_W = CFU_REQ_DATA_W
) (
input clk,
input [15:0] cycle,
input [15:0] lfsr);

wire [CFU_FUNC_ID_W-1:0] req_func_id = 0;
reg [CFU_REQ_DATA_W-1:0] req_data0 `vp = 0;
reg [CFU_REQ_DATA_W-1:0] req_data1 `vp = 0;
reg [CFU_RESP_DATA_W-1:0] resp_data `vp = 0;
wire `CFU_FUNC_ID req_func_id = 0;
reg `CFU_REQ_DATA req_data0 `vp = 0;
reg `CFU_REQ_DATA req_data1 `vp = 0;
reg `CFU_RESP_DATA resp_data `vp = 0;

reg [CFU_RESP_DATA_W-1:0] xnor_ `vp = 0;
reg [CFU_RESP_DATA_W-1:0] answer `vp = 0;
reg `CFU_RESP_DATA xnor_ `vp = 0;
reg `CFU_RESP_DATA answer `vp = 0;
int i;
always @* begin
req_data0 = {cycle-1'b1,cycle};
Expand Down Expand Up @@ -68,20 +68,20 @@ CFU_LI:
- feature_level: 0
- cfu_req_data_w: [32]
- cfu_resp_data_w: [32]
- cfu_func_id_w: [5]
- cfu_func_id_w: [1]
*/
module BNNDotProd32_CFU_LI0 #(
parameter CFU_FUNC_ID_W = 5,
parameter CFU_FUNC_ID_W = 1,
parameter CFU_REQ_DATA_W = 32,
parameter CFU_RESP_DATA_W = 32
) (
input req_valid, // unused
input [CFU_FUNC_ID_W-1:0] req_func_id, // unused
input [CFU_REQ_DATA_W-1:0] req_data0,
input [CFU_REQ_DATA_W-1:0] req_data1,
output [CFU_RESP_DATA_W-1:0] resp_data
input `CFU_FUNC_ID req_func_id, // unused
input `CFU_REQ_DATA req_data0,
input `CFU_REQ_DATA req_data1,
output `CFU_RESP_DATA resp_data
);
wire [CFU_REQ_DATA_W-1:0] xnor_ = req_data0 ~^ req_data1;
wire `CFU_REQ_DATA xnor_ = req_data0 ~^ req_data1;
wire [5:0] count;
Popcount32 count_(.i(xnor_), .popcount(count));
assign resp_data = {26'b0,count};
Expand Down
182 changes: 182 additions & 0 deletions gcd.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
// Copyright (C) 2019, Gray Research LLC
//

/* verilator lint_off DECLFILENAME */

`include "cfu.vh"

// Test bench
module GCDTB #(
parameter CFU_FUNC_ID_W = 1,
parameter CFU_REQ_RESP_ID_W = 8,
parameter CFU_REQ_DATA_W = 32,
parameter CFU_RESP_DATA_W = 32,
parameter CFU_ERR_ID_W = 32
) (
input clk,
input rst,
input [15:0] cycle, // unused
input [15:0] lfsr);

function integer gcdfn(input integer a, input integer b); begin
// assumes a, b > 0
while (a != b) begin
if (a > b)
a = a - b;
else
b = b - a;
end
gcdfn = a;
end endfunction

// try asserting req_valid at "random" times
wire req_valid = !rst && lfsr[0];
wire req_ready;
reg `CFU_FUNC_ID req_func_id = 0;
reg `CFU_REQ_RESP_ID req_id;
reg `CFU_REQ_DATA a;
reg `CFU_REQ_DATA b;

// last request issued
reg `CFU_REQ_RESP_ID req_id_prev;
reg `CFU_REQ_DATA a_prev;
reg `CFU_REQ_DATA b_prev;

wire resp_valid;
wire `CFU_REQ_RESP_ID resp_id;
wire `CFU_RESP_DATA resp_data;
wire resp_err;
wire `CFU_ERR_ID resp_err_id;

// request GCD of (1,1), (1,2), (2,2), (1,3), (2,3), (3,3), (1,4), etc.
always @(posedge clk) begin
if (rst) begin
req_id_prev <= 0;
a_prev <= 0;
b_prev <= 0;

req_id <= 1;
a <= 1;
b <= 1;
end
else if (req_valid && req_ready) begin
// issuing the current GCD request, so prepare next request
req_id_prev <= req_id;
a_prev <= a;
b_prev <= b;

req_id <= req_id + 1;
if (a < b) begin
a <= a + 1;
end
else begin
a <= 1;
b <= b + 1;
end
end

if (resp_valid) begin
// process GCD response
if (resp_id != req_id_prev)
$display("GCDTB: FAIL: resp_id != req_id");
else if (resp_err)
$display("GCDTB: FAIL: resp_err, resp_err_id=%1d", resp_err_id);
else if (resp_data != gcdfn(a_prev, b_prev))
$display("GCDTB: FAIL: resp_data=%1d != %1d", resp_data, gcdfn(a_prev, b_prev));
end
end

// Since a <= b, perform gcd(b,a) to force at least one swap of arguments
// in GCD_CFU_LI2.
GCD_CFU_LI2 #(
.CFU_FUNC_ID_W(CFU_FUNC_ID_W),
.CFU_REQ_RESP_ID_W(CFU_REQ_RESP_ID_W),
.CFU_REQ_DATA_W(CFU_REQ_DATA_W),
.CFU_RESP_DATA_W(CFU_RESP_DATA_W),
.CFU_ERR_ID_W(CFU_ERR_ID_W))
gcd(.clk, .rst,
.req_valid, .req_ready, .req_func_id, .req_id, .req_data0(b), .req_data1(a),
.resp_valid, .resp_id, .resp_data, .resp_err, .resp_err_id);

wire _unused_ok = &{1'b0,cycle,lfsr[15:1],resp_err_id,1'b0};
endmodule


// Level-2 (variable latency with request flow control) GCD
// (greatest common divisor)
//
// Latency=?
// Inputs=2
// Outputs=1
//
/* Metadata
CFU_LI:
- feature_level: 2
- cfu_func_id_w: [1]
- cfu_req_data_w: [32]
- cfu_resp_data_w: [32]
- cfu_err_id_w: [32]
*/
module GCD_CFU_LI2 #(
parameter CFU_FUNC_ID_W = 1,
parameter CFU_REQ_RESP_ID_W = 8,
parameter CFU_REQ_DATA_W = 32,
parameter CFU_RESP_DATA_W = 32,
parameter CFU_ERR_ID_W = 32
) (
input clk,
input rst,
input req_valid,
output reg req_ready,
input `CFU_FUNC_ID req_func_id, // unused
input `CFU_REQ_RESP_ID req_id,
input `CFU_REQ_DATA req_data0,
input `CFU_REQ_DATA req_data1,
output reg resp_valid,
output reg `CFU_REQ_RESP_ID resp_id,
output reg `CFU_RESP_DATA resp_data,
output reg resp_err,
output reg `CFU_ERR_ID resp_err_id
);
// assert(CFU_REQ_WIDTH == CFU_RESP_WIDTH);

reg `CFU_REQ_DATA a;
reg `CFU_REQ_DATA b;

always @(posedge clk) begin
if (rst) begin
req_ready <= 1;
resp_valid <= 0;
resp_id <= 0;
resp_data <= 0;
resp_err <= 0;
resp_err_id <= 0;
end
else if (req_ready) begin
if (req_valid) begin
req_ready <= 0;
a <= req_data0;
b <= req_data1;
resp_id <= req_id;
end
resp_valid <= 0;
end
else begin
if (a < b) begin
// swap a and b
a <= b;
b <= a;
end
else if (b != 0) begin
a <= a - b;
end
else begin
req_ready <= 1; // assert until req_valid
resp_valid <= 1; // assert for one cycle ony
resp_data <= a;
end
end
end

wire _unused_ok = &{1'b0,req_func_id,1'b0};
endmodule
36 changes: 18 additions & 18 deletions mulacc.v
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

// Test bench
module MulAccTB #(
parameter CFU_FUNC_ID_W = 5,
parameter CFU_FUNC_ID_W = 1,
parameter CFU_REQ_DATA_W = 32,
parameter CFU_RESP_DATA_W = 32,
parameter CFU_ERR_ID_W = 32,
Expand All @@ -29,7 +29,7 @@ module MulAccTB #(
wire `CFU_ERR_ID resp_err_id;

always @* begin
req_valid = 1; // default: valid
req_valid = 1; // default: valid
req_func_id = 1; // default: mul-acc
req_data0 = 0;
req_data1 = 0;
Expand Down Expand Up @@ -113,14 +113,14 @@ endmodule
/* Metadata
CFU_LI:
- feature_level: 1
- cfu_func_id_w: [5]
- cfu_func_id_w: [1]
- cfu_req_data_w: [32]
- cfu_resp_data_w: [32]
- cfu_err_id_w: [32]
- cfu_resp_latecy: [3,4,5,6,7,8,9,10,11,12,13,14,15,16]
*/
module MulAcc_CFU_LI1 #(
parameter CFU_FUNC_ID_W = 5,
parameter CFU_FUNC_ID_W = 1,
parameter CFU_REQ_DATA_W = 32,
parameter CFU_RESP_DATA_W = 32,
parameter CFU_ERR_ID_W = 32,
Expand All @@ -129,23 +129,23 @@ module MulAcc_CFU_LI1 #(
input clk,
input rst,
input req_valid,
input [CFU_FUNC_ID_W-1:0] req_func_id,
input [CFU_REQ_DATA_W-1:0] req_data0,
input [CFU_REQ_DATA_W-1:0] req_data1,
input `CFU_FUNC_ID req_func_id,
input `CFU_REQ_DATA req_data0,
input `CFU_REQ_DATA req_data1,
output resp_valid,
output [CFU_RESP_DATA_W-1:0] resp_data,
output `CFU_RESP_DATA resp_data,
output resp_err,
output [CFU_ERR_ID_W-1:0] resp_err_id
output `CFU_ERR_ID resp_err_id
);
// assert(CFU_REQ_WIDTH == CFU_RESP_WIDTH);

// accumulator
reg [CFU_RESP_DATA_W-1:0] acc;
reg `CFU_RESP_DATA acc;

// response pipeline state
reg [CFU_RESP_LATENCY-1:0] valid;
reg [CFU_RESP_LATENCY-2:0] rst_acc;
reg [CFU_RESP_LATENCY-2:0] [CFU_RESP_DATA_W-1:0] prod;
reg [CFU_RESP_LATENCY-2:0] `CFU_RESP_DATA prod;

// response pipeline
int i;
Expand Down Expand Up @@ -185,7 +185,7 @@ endmodule

// Test bench
module MulAccSIMDTB #(
parameter CFU_FUNC_ID_W = 5,
parameter CFU_FUNC_ID_W = 1,
parameter CFU_REQ_DATA_W = 32,
parameter CFU_REQ_ELT_W = 8,
parameter CFU_RESP_DATA_W = 32,
Expand Down Expand Up @@ -296,7 +296,7 @@ endmodule
// Outputs=1
//
module MulAccSIMD_CFU_LI1 #(
parameter CFU_FUNC_ID_W = 5,
parameter CFU_FUNC_ID_W = 1,
parameter CFU_REQ_DATA_W = 32,
parameter CFU_RESP_DATA_W = 32,
parameter CFU_ERR_ID_W = 32,
Expand All @@ -306,13 +306,13 @@ module MulAccSIMD_CFU_LI1 #(
input clk,
input rst,
input req_valid,
input [CFU_FUNC_ID_W-1:0] req_func_id,
input [CFU_REQ_DATA_W-1:0] req_data0,
input [CFU_REQ_DATA_W-1:0] req_data1,
input `CFU_FUNC_ID req_func_id,
input `CFU_REQ_DATA req_data0,
input `CFU_REQ_DATA req_data1,
output resp_valid,
output [CFU_RESP_DATA_W-1:0] resp_data,
output `CFU_RESP_DATA resp_data,
output resp_err,
output [CFU_ERR_ID_W-1:0] resp_err_id
output `CFU_ERR_ID resp_err_id
);
localparam N_ELTS = CFU_REQ_DATA_W / CFU_REQ_ELT_W;
// assert(CFU_REQ_WIDTH == CFU_RESP_WIDTH);
Expand Down
20 changes: 10 additions & 10 deletions popcount.v
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@
`include "cfu.vh"

module PopcountTB #(
parameter CFU_FUNC_ID_W = 5,
parameter CFU_FUNC_ID_W = 1,
parameter CFU_REQ_DATA_W = 32,
parameter CFU_RESP_DATA_W = 32
) (
input clk,
input [15:0] cycle);

wire [CFU_FUNC_ID_W-1:0] req_func_id = 0;
reg [CFU_REQ_DATA_W-1:0] req_data;
reg [CFU_RESP_DATA_W-1:0] resp_data;
wire `CFU_FUNC_ID req_func_id = 0;
reg `CFU_REQ_DATA req_data;
reg `CFU_RESP_DATA resp_data;

int i;
reg `CFU_RESP_DATA answer `vp = 0;
Expand Down Expand Up @@ -79,20 +79,20 @@ endmodule
/* Metadata
CFU_LI:
- feature_level: 0
- cfu_func_id_w: [5]
- cfu_func_id_w: [1]
- cfu_req_data_w: [32]
- cfu_resp_data_w: [32]
*/
module Popcount32_CFU_LI0 #(
parameter CFU_FUNC_ID_W = 5,
parameter CFU_FUNC_ID_W = 1,
parameter CFU_REQ_DATA_W = 32,
parameter CFU_RESP_DATA_W = 32
) (
input req_valid,
input [CFU_FUNC_ID_W-1:0] req_func_id, // unused
input [CFU_REQ_DATA_W-1:0] req_data0,
input [CFU_REQ_DATA_W-1:0] req_data1, // unused
output [CFU_RESP_DATA_W-1:0] resp_data
input `CFU_FUNC_ID req_func_id, // unused
input `CFU_REQ_DATA req_data0,
input `CFU_REQ_DATA req_data1, // unused
output `CFU_RESP_DATA resp_data
);
wire [5:0] popcount;
Popcount32 popcount_(.i(req_data0), .popcount);
Expand Down

0 comments on commit b8eea8d

Please sign in to comment.