ibuffer addition
This commit is contained in:
@@ -7,34 +7,52 @@ module VX_mul_unit #(
|
||||
input wire reset,
|
||||
|
||||
// Inputs
|
||||
VX_mul_req_if alu_req_if,
|
||||
VX_mul_req_if mul_req_if,
|
||||
|
||||
// Outputs
|
||||
VX_exu_to_cmt_if alu_commit_if
|
||||
VX_exu_to_cmt_if mul_commit_if
|
||||
);
|
||||
wire [`ISTAG_BITS-1:0] issue_tag;
|
||||
wire [`MUL_BITS-1:0] alu_op;
|
||||
wire [`NUM_THREADS-1:0][31:0] alu_in1, alu_in2;
|
||||
wire valid_in, ready_in;
|
||||
|
||||
// use a skid buffer due to MUL/DIV output arbitration adding realtime backpressure
|
||||
VX_elastic_buffer #(
|
||||
.DATAW (`ISTAG_BITS + `MUL_BITS + (2 * `NUM_THREADS * 32)),
|
||||
.SIZE (0)
|
||||
) input_buffer (
|
||||
.clk (clk),
|
||||
.reset (reset),
|
||||
.valid_in (alu_req_if.valid),
|
||||
.ready_in (alu_req_if.ready),
|
||||
.data_in ({alu_req_if.issue_tag, alu_req_if.op, alu_req_if.rs1_data, alu_req_if.rs2_data}),
|
||||
.data_out ({issue_tag, alu_op, alu_in1, alu_in2}),
|
||||
.ready_out (ready_in),
|
||||
.valid_out (valid_in)
|
||||
);
|
||||
localparam MULQ_BITS = `LOG2UP(`MULQ_SIZE);
|
||||
|
||||
wire [`MUL_BITS-1:0] alu_op = mul_req_if.op;
|
||||
wire [`NUM_THREADS-1:0][31:0] alu_in1 = mul_req_if.rs1_data;
|
||||
wire [`NUM_THREADS-1:0][31:0] alu_in2 = mul_req_if.rs2_data;
|
||||
|
||||
wire [`NW_BITS-1:0] rsp_wid;
|
||||
wire [`NUM_THREADS-1:0] rsp_thread_mask;
|
||||
wire [31:0] rsp_curr_PC;
|
||||
wire [`NR_BITS-1:0] rsp_rd;
|
||||
wire rsp_wb;
|
||||
wire [MULQ_BITS-1:0] tag_in, tag_out;
|
||||
wire valid_out;
|
||||
wire stall_out;
|
||||
wire mulq_full;
|
||||
|
||||
wire mulq_push = mul_req_if.valid && mul_req_if.ready;
|
||||
wire mulq_pop = valid_out && ~stall_out;
|
||||
|
||||
VX_cam_buffer #(
|
||||
.DATAW (`NW_BITS + `NUM_THREADS + 32 + `NR_BITS + 1),
|
||||
.SIZE (`MULQ_SIZE)
|
||||
) mul_queue (
|
||||
.clk (clk),
|
||||
.reset (reset),
|
||||
.acquire_slot (mulq_push),
|
||||
.write_addr (tag_in),
|
||||
.read_addr (tag_out),
|
||||
.release_addr (tag_out),
|
||||
.write_data ({mul_req_if.wid, mul_req_if.thread_mask, mul_req_if.curr_PC, mul_req_if.rd, mul_req_if.wb}),
|
||||
.read_data ({rsp_wid, rsp_thread_mask, rsp_curr_PC, rsp_rd, rsp_wb}),
|
||||
.release_slot (mulq_pop),
|
||||
.full (mulq_full)
|
||||
);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
wire [`NUM_THREADS-1:0][31:0] mul_result;
|
||||
wire is_mulw = (alu_op == `MUL_MUL);
|
||||
wire is_mulw_out;
|
||||
wire stall_mul;
|
||||
|
||||
for (genvar i = 0; i < `NUM_THREADS; i++) begin
|
||||
|
||||
@@ -51,7 +69,7 @@ module VX_mul_unit #(
|
||||
) multiplier (
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.clk_en(1'b1),
|
||||
.clk_en(~stall_mul),
|
||||
.dataa(mul_in1),
|
||||
.datab(mul_in2),
|
||||
.result(mul_result_tmp)
|
||||
@@ -60,20 +78,20 @@ module VX_mul_unit #(
|
||||
assign mul_result[i] = is_mulw_out ? mul_result_tmp[31:0] : mul_result_tmp[63:32];
|
||||
end
|
||||
|
||||
wire [`ISTAG_BITS-1:0] mul_issue_tag;
|
||||
wire [MULQ_BITS-1:0] mul_tag;
|
||||
wire mul_valid_out;
|
||||
|
||||
wire mul_fire = valid_in && ready_in && ~`IS_DIV_OP(alu_op);
|
||||
wire mul_fire = mul_req_if.valid && mul_req_if.ready && ~`IS_DIV_OP(alu_op);
|
||||
|
||||
VX_shift_register #(
|
||||
.DATAW(1 + `ISTAG_BITS + 1),
|
||||
.DATAW(1 + MULQ_BITS + 1),
|
||||
.DEPTH(`LATENCY_IMUL)
|
||||
) mul_shift_reg (
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.enable(1'b1),
|
||||
.in({mul_fire, issue_tag, is_mulw}),
|
||||
.out({mul_valid_out, mul_issue_tag, is_mulw_out})
|
||||
.enable(~stall_mul),
|
||||
.in({mul_fire, tag_in, is_mulw}),
|
||||
.out({mul_valid_out, mul_tag, is_mulw_out})
|
||||
);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
@@ -81,8 +99,8 @@ module VX_mul_unit #(
|
||||
wire [`NUM_THREADS-1:0][31:0] div_result;
|
||||
wire is_div = (alu_op == `MUL_DIV || alu_op == `MUL_DIVU);
|
||||
wire is_signed_div = (alu_op == `MUL_DIV || alu_op == `MUL_REM);
|
||||
reg [`NUM_THREADS-1:0] is_div_qual;
|
||||
wire [`NUM_THREADS-1:0] is_div_out;
|
||||
reg [`NUM_THREADS-1:0] is_div_qual;
|
||||
wire is_div_out;
|
||||
wire stall_div;
|
||||
|
||||
for (genvar i = 0; i < `NUM_THREADS; i++) begin
|
||||
@@ -95,8 +113,8 @@ module VX_mul_unit #(
|
||||
always @(*) begin
|
||||
if (~stall_div) begin
|
||||
is_div_qual[i] = is_div;
|
||||
div_in1_qual = alu_in1[i];
|
||||
div_in2_qual = alu_in2[i];
|
||||
div_in1_qual = alu_in1[i];
|
||||
div_in2_qual = alu_in2[i];
|
||||
if (0 == alu_in2[i]) begin
|
||||
div_in2_qual = 1;
|
||||
if (is_div) begin
|
||||
@@ -134,34 +152,52 @@ module VX_mul_unit #(
|
||||
.remainder(rem_result_tmp)
|
||||
);
|
||||
|
||||
assign div_result[i] = is_div_out[i] ? div_result_tmp : rem_result_tmp;
|
||||
assign div_result[i] = is_div_out ? div_result_tmp : rem_result_tmp;
|
||||
end
|
||||
|
||||
wire [`ISTAG_BITS-1:0] div_issue_tag;
|
||||
wire [MULQ_BITS-1:0] div_tag;
|
||||
wire div_valid_out;
|
||||
|
||||
wire div_fire = valid_in && ready_in && `IS_DIV_OP(alu_op);
|
||||
wire div_fire = mul_req_if.valid && mul_req_if.ready && `IS_DIV_OP(alu_op);
|
||||
|
||||
VX_shift_register #(
|
||||
.DATAW(1 + `ISTAG_BITS + `NUM_THREADS),
|
||||
.DATAW(1 + MULQ_BITS + 1),
|
||||
.DEPTH(`LATENCY_IDIV + 1)
|
||||
) div_shift_reg (
|
||||
.clk(clk),
|
||||
.reset(reset),
|
||||
.enable(~stall_div),
|
||||
.in({div_fire, issue_tag, is_div_qual}),
|
||||
.out({div_valid_out, div_issue_tag, is_div_out})
|
||||
.in({div_fire, tag_in, (| is_div_qual)}),
|
||||
.out({div_valid_out, div_tag, is_div_out})
|
||||
);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
assign stall_div = mul_valid_out && div_valid_out; // arbitration prioritizes MUL
|
||||
wire arbiter_hazard = mul_valid_out && div_valid_out;
|
||||
|
||||
assign stall_out = ~mul_commit_if.ready && mul_commit_if.valid;
|
||||
assign stall_mul = stall_out || mulq_full;
|
||||
assign stall_div = stall_out || mulq_full
|
||||
|| arbiter_hazard; // arbitration prioritizes MUL
|
||||
wire stall_in = stall_mul || stall_div;
|
||||
|
||||
assign valid_out = mul_valid_out || div_valid_out;
|
||||
assign tag_out = mul_valid_out ? mul_tag : div_tag;
|
||||
|
||||
wire [`NUM_THREADS-1:0][31:0] result = mul_valid_out ? mul_result : div_result;
|
||||
|
||||
VX_generic_register #(
|
||||
.N(1 + `NW_BITS + `NUM_THREADS + 32 + `NR_BITS + 1 + (`NUM_THREADS * 32))
|
||||
) alu_reg (
|
||||
.clk (clk),
|
||||
.reset (reset),
|
||||
.stall (stall_out),
|
||||
.flush (0),
|
||||
.in ({valid_out, rsp_wid, rsp_thread_mask, rsp_curr_PC, rsp_rd, rsp_wb, result}),
|
||||
.out ({mul_commit_if.valid, mul_commit_if.wid, mul_commit_if.thread_mask, mul_commit_if.curr_PC, mul_commit_if.rd, mul_commit_if.wb, mul_commit_if.data})
|
||||
);
|
||||
|
||||
// can accept new request?
|
||||
assign ready_in = ~stall_div;
|
||||
|
||||
assign alu_commit_if.valid = mul_valid_out || div_valid_out;
|
||||
assign alu_commit_if.issue_tag = mul_valid_out ? mul_issue_tag : div_issue_tag;
|
||||
assign alu_commit_if.data = mul_valid_out ? mul_result : div_result;
|
||||
assign mul_req_if.ready = ~stall_in;
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user