Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions include/tcp_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ package tcp_pkg;
localparam RX_PAYLOAD_PTR_W = PAYLOAD_PTR_W;
localparam TX_PAYLOAD_PTR_W = PAYLOAD_PTR_W;

// TODO: idx width?

localparam MALLOC_LEN_MAX = 9216;
localparam MALLOC_LEN_W = $clog2(MALLOC_LEN_MAX);

localparam RT_ACK_THRESHOLD = 3;
localparam RT_ACK_THRESHOLD_W = $clog2(RT_ACK_THRESHOLD) + 1;

Expand Down
268 changes: 134 additions & 134 deletions rx_buf_ptrs.sv

Large diffs are not rendered by default.

68 changes: 68 additions & 0 deletions rx_buf_store.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
module rx_buf_store
import tcp_pkg::*;
(
input clk
,input rst

,input wr_req_val
,input [FLOWID_W-1:0] wr_req_flowid // this and idx are concatenated to make the real waddr
,input [RX_PAYLOAD_IDX_W-1:0] wr_req_idx
,input tcp_buf wr_req_data
,output wr_req_rdy

,input rd0_req_val
,input [FLOWID_W-1:0] rd0_req_flowid
,input [RX_PAYLOAD_IDX_W-1:0] rd0_req_idx
,output logic rd0_req_rdy

,output logic rd0_resp_val
,output tcp_buf rd0_resp_data // we can't return it with the idx because the idx is incomplete (missing top bit)
,input rd0_resp_rdy

,input rd1_req_val
,input [FLOWID_W-1:0] rd1_req_flowid
,input [RX_PAYLOAD_IDX_W-1:0] rd1_req_idx
,output logic rd1_req_rdy

,output logic rd1_resp_val
,output tcp_buf rd1_resp_data
,input rd1_resp_rdy
);

// convert from flowid + index to addr
wire [FLOWID_W + MAX_PAYLOAD_IDX_W - 1:0] wr_req_addr = '{wr_req_flowid , wr_req_idx };
wire [FLOWID_W + MAX_PAYLOAD_IDX_W - 1:0] rd0_req_addr = '{rd0_req_flowid, rd0_req_idx};
wire [FLOWID_W + MAX_PAYLOAD_IDX_W - 1:0] rd1_req_addr = '{rd1_req_flowid, rd1_req_idx};

ram_2r1w_sync_backpressure #(
.width_p (TCP_BUF_W )
,.els_p (MAX_FLOW_CNT * MAX_NUM_BUFS )
) rx_state_store (
.clk (clk )
,.rst (rst )

,.wr_req_val (wr_req_val )
,.wr_req_addr (wr_req_addr )
,.wr_req_data (wr_req_data )
,.wr_req_rdy (wr_req_rdy )

,.rd0_req_val (rd0_req_val )
,.rd0_req_addr (rd0_req_addr )
,.rd0_req_rdy (rd0_req_rdy )

,.rd0_resp_val (rd0_resp_val )
,.rd0_resp_addr ()
,.rd0_resp_data (rd0_resp_data )
,.rd0_resp_rdy (rd0_resp_rdy )

,.rd1_req_val (rd1_req_val )
,.rd1_req_addr (rd1_req_addr )
,.rd1_req_rdy (rd1_req_rdy )

,.rd1_resp_val (rd1_resp_val )
,.rd1_resp_addr ()
,.rd1_resp_data (rd1_resp_data )
,.rd1_resp_rdy (rd1_resp_rdy )
);

endmodule
1 change: 1 addition & 0 deletions tcp.core
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ filesets:
- send_pkt_mux.sv
- tcp.sv
- tcp_hdr_assembler.sv
- tcp_malloc.sv
- tcp_rx.sv
- tcp_rx_ctrl.sv
- tcp_rx_datap.sv
Expand Down
332 changes: 223 additions & 109 deletions tcp.sv

Large diffs are not rendered by default.

252 changes: 252 additions & 0 deletions tcp_malloc.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,252 @@
module tcp_malloc #(
parameter PTR_W = 0 // determines how big the backing memory should be
,parameter LEN_MAX = 0 // the largest buffer that a user will request. in the naive impl, the memory is split into fixed sized chunks where this is the chunk size.
,parameter STALL = 0 // whether or not to stall when we get a malloc that we can't yet fulfill. stall=0 -> return !resp_success, stall=1 -> don't return until we fulfill the request.

// generated param
,parameter LEN_W = $clog2(LEN_MAX)
)(
input clk
,input rst

,input malloc_req_val
,input [LEN_W-1:0] malloc_req_len // in the native impl, this must equal LEN_MAX
,output malloc_req_rdy

,output malloc_resp_val
,output malloc_resp_success // 1 = addr is valid. 0 = addr is junk, retry your request or otherwise handle OOM.
,output [PTR_W-1:0] malloc_resp_addr
,input malloc_resp_rdy

,output [PTR_W:0] malloc_approx_empty_space

,input free_req_val
,input [PTR_W-1:0] free_req_addr
,input [LEN_W-1:0] free_req_len // in the native impl, this must equal LEN_MAX
,output free_req_rdy
);

localparam BACKING_SIZE_UPPER = 2**PTR_W;

localparam NUM_TOTAL_SLICES = BACKING_SIZE_UPPER/LEN_MAX; // round down, half-avail slices aren't useful
localparam SLICES_W = $clog2(NUM_TOTAL_SLICES);
localparam BACKING_SIZE_EXACT = NUM_TOTAL_SLICES * LEN_MAX;

// hookup the inputs and outputs
logic malloc_req_fifo_wr_req;
logic [LEN_W-1:0] malloc_req_fifo_wr_data;
logic malloc_req_fifo_full;
assign malloc_req_fifo_wr_req = malloc_req_val;
assign malloc_req_fifo_wr_data = malloc_req_len;
assign malloc_req_rdy = ~malloc_req_fifo_full;

logic malloc_resp_fifo_empty;
logic [PTR_W:0] malloc_resp_fifo_rd_data;
logic malloc_resp_fifo_rd_req;
assign malloc_resp_val = ~malloc_resp_fifo_empty;
assign malloc_resp_success = malloc_resp_fifo_rd_data[PTR_W];
assign malloc_resp_addr = malloc_resp_fifo_rd_data[PTR_W-1:0];
assign malloc_resp_fifo_rd_req = malloc_resp_rdy;

logic free_req_fifo_wr_req;
logic [PTR_W+LEN_W-1:0] free_req_fifo_wr_data;
logic free_req_fifo_full;
assign free_req_fifo_wr_req = free_req_val;
assign free_req_fifo_wr_data = '{free_req_addr, free_req_len};
assign free_req_rdy = ~free_req_fifo_full;

always_ff @(posedge clk) begin
if (malloc_req_val && malloc_req_rdy) begin
if (malloc_req_len != LEN_MAX) begin
$fatal("Error: naive malloc requires malloc_req_len == LEN_MAX == %d instead of %d", LEN_MAX, malloc_req_len);
end
end
if (free_req_val && free_req_rdy) begin
if (free_req_len != LEN_MAX) begin
$fatal("Error: naive malloc requires free_req_len == LEN_MAX == %d instead of %d", LEN_MAX, free_req_len);
end
end
end

// internal logic. req feeds resp, free and reset feed slices, slices also feeds resp.
// free || reset -> slices, slices && req -> resp

logic slices_fifo_rd_req;
logic slices_fifo_empty;
logic [PTR_W+LEN_W-1:0] slices_fifo_rd_data;

logic slices_fifo_wr_req;
logic [PTR_W+LEN_W-1:0] slices_fifo_wr_data;
logic slices_fifo_full;

logic malloc_req_fifo_rd_req;
logic malloc_req_fifo_empty;
logic [LEN_W-1:0] malloc_req_fifo_rd_data; // unused.

logic malloc_resp_fifo_wr_req;
logic [LEN_W:0] malloc_resp_fifo_wr_data;
logic malloc_resp_fifo_full;

logic free_req_fifo_rd_req;
logic free_req_fifo_empty;
logic [PTR_W+LEN_W-1:0] free_req_fifo_rd_data;

// not actually a fifo, but framed like one for convenience
logic reset_fifo_rd_req;
logic reset_fifo_empty;
logic [PTR_W+LEN_W-1:0] reset_fifo_rd_data;

always_ff @(posedge clk) begin
if (rst) begin
if (LEN_MAX > BACKING_SIZE_EXACT) begin
$fatal("len max > backing size of tcp malloc unit... bad configuration");
end
end else begin
if (slices_fifo_full) begin
$fatal("slices fifo should never fill up, an error was made calculating its size");
end
end
end

// free || reset -> slices
assign free_req_fifo_rd_req = ~slices_fifo_full;
assign reset_fifo_rd_req = free_req_fifo_empty && ~slices_fifo_full;
assign slices_fifo_wr_req = ~free_req_fifo_empty || (free_req_fifo_empty && ~reset_fifo_empty);
assign slices_fifo_wr_data = ~free_req_fifo_empty ? free_req_fifo_rd_data : reset_fifo_rd_data;

// slices && req -> resp
assign slices_fifo_rd_req = ~malloc_resp_fifo_full && ~malloc_req_fifo_empty;
generate
if (STALL) begin
assign malloc_req_fifo_rd_req = ~malloc_resp_fifo_full && ~slices_fifo_empty;
assign malloc_resp_fifo_wr_req = ~slices_fifo_empty && ~malloc_req_fifo_empty;
assign malloc_resp_fifo_wr_data = '{1'b1, slices_fifo_rd_data[PTR_W+LEN_W-1:LEN_W]};
end else begin
assign malloc_req_fifo_rd_req = ~malloc_resp_fifo_full;
assign malloc_resp_fifo_wr_req = ~malloc_req_fifo_empty;
assign malloc_resp_fifo_wr_data = '{~slices_fifo_empty, slices_fifo_rd_data[PTR_W+LEN_W-1:LEN_W]};
end
endgenerate


// reset logic
logic [PTR_W:0] reset_current_addr_reg = 0;
logic [PTR_W:0] reset_current_addr_next;
logic reset_done = 0;
assign reset_current_addr_next = reset_current_addr_reg + LEN_MAX;

assign reset_fifo_empty = reset_done;
assign reset_fifo_rd_data = '{reset_current_addr_reg[PTR_W-1:0], LEN_MAX};

always_ff @(posedge clk) begin
if (rst) begin
reset_current_addr_reg <= '0;
reset_done <= '0;
end else begin
if (reset_fifo_rd_req && ~reset_fifo_empty) begin
// transaction occurred.
reset_current_addr_reg <= reset_current_addr_next;
if (reset_current_addr_next >= BACKING_SIZE_EXACT) begin
reset_done <= 1;
end
end
end
end

// free bytes/empty space logic
logic [PTR_W:0] free_bytes_cnt_reg = BACKING_SIZE_EXACT;
logic [PTR_W:0] free_bytes_cnt_next;
assign malloc_approx_empty_space = free_bytes_cnt_reg;

always_comb begin
free_bytes_cnt_next = free_bytes_cnt_reg;

// malloc request means one fewer slice
if (slices_fifo_rd_req && ~slices_fifo_empty) begin
free_bytes_cnt_next = free_bytes_cnt_next - LEN_MAX;
end

// slice write from the free fifo means one more slice
// notably, reset doesn't increment. it starts out totally empty.
if (slices_fifo_wr_req && ~slices_fifo_full && ~free_req_fifo_empty && free_req_fifo_rd_req) begin
free_bytes_cnt_next = free_bytes_cnt_next + LEN_MAX;
end
end

always @(posedge clk) begin
if (rst) begin
free_bytes_cnt_reg <= BACKING_SIZE_EXACT;
end else begin
free_bytes_cnt_reg <= free_bytes_cnt_next;
if (free_bytes_cnt_next > BACKING_SIZE_EXACT) begin
$fatal("bug in free bytes calculation");
end
end

end

fifo_1r1w #(
.width_p (PTR_W+LEN_W)
,.log2_els_p (SLICES_W)
) slices_fifo (
.clk (clk)
,.rst (rst)

,.rd_req (slices_fifo_rd_req )
,.empty (slices_fifo_empty )
,.rd_data (slices_fifo_rd_data )

,.wr_req (slices_fifo_wr_req )
,.wr_data (slices_fifo_wr_data )
,.full (slices_fifo_full )
);

fifo_1r1w #(
.width_p (LEN_W)
,.log2_els_p (1)
) malloc_req_fifo (
.clk (clk)
,.rst (rst)

,.rd_req (malloc_req_fifo_rd_req )
,.empty (malloc_req_fifo_empty )
,.rd_data (malloc_req_fifo_rd_data )

,.wr_req (malloc_req_fifo_wr_req )
,.wr_data (malloc_req_fifo_wr_data )
,.full (malloc_req_fifo_full )
);

fifo_1r1w #(
.width_p (1+LEN_W)
,.log2_els_p (1)
) malloc_resp_fifo (
.clk (clk)
,.rst (rst)

,.rd_req (malloc_resp_fifo_rd_req )
,.empty (malloc_resp_fifo_empty )
,.rd_data (malloc_resp_fifo_rd_data )

,.wr_req (malloc_resp_fifo_wr_req )
,.wr_data (malloc_resp_fifo_wr_data )
,.full (malloc_resp_fifo_full )
);

fifo_1r1w #(
.width_p (PTR_W+LEN_W)
,.log2_els_p (1)
) free_req_fifo (
.clk (clk)
,.rst (rst)

,.rd_req (free_req_fifo_rd_req )
,.empty (free_req_fifo_empty )
,.rd_data (free_req_fifo_rd_data )

,.wr_req (free_req_fifo_wr_req )
,.wr_data (free_req_fifo_wr_data )
,.full (free_req_fifo_full )
);

endmodule
Loading