pipeline refactoring - fmax >= 222 mhz
This commit is contained in:
@@ -10,98 +10,83 @@ module VX_alu_unit #(
|
||||
VX_alu_req_if alu_req_if,
|
||||
|
||||
// Outputs
|
||||
VX_branch_ctl_if branch_ctl_if,
|
||||
VX_exu_to_cmt_if alu_commit_if
|
||||
VX_exu_to_cmt_if alu_commit_if
|
||||
);
|
||||
reg [`NUM_THREADS-1:0][31:0] alu_result;
|
||||
wire [`NUM_THREADS-1:0][32:0] sub_result;
|
||||
wire [`NUM_THREADS-1:0][32:0] shift_result;
|
||||
reg [`NUM_THREADS-1:0][31:0] alu_result;
|
||||
|
||||
wire [`NUM_THREADS-1:0][31:0] addsub_result;
|
||||
wire [`NUM_THREADS-1:0] less_result;
|
||||
wire [`NUM_THREADS-1:0][31:0] shift_result;
|
||||
reg [`NUM_THREADS-1:0][31:0] misc_result;
|
||||
|
||||
wire [`ALU_BITS-1:0] alu_op = alu_req_if.alu_op;
|
||||
wire [`ALU_BITS-1:0] alu_op = `ALU_OP(alu_req_if.op);
|
||||
wire [`NUM_THREADS-1:0][31:0] alu_in1 = alu_req_if.rs1_data;
|
||||
wire [`NUM_THREADS-1:0][31:0] alu_in2 = alu_req_if.rs2_data;
|
||||
|
||||
genvar i;
|
||||
wire [`NUM_THREADS-1:0][31:0] alu_in1_PC = alu_req_if.rs1_is_PC ? {`NUM_THREADS{alu_req_if.curr_PC}} : alu_in1;
|
||||
wire [`NUM_THREADS-1:0][31:0] alu_in2_imm = alu_req_if.rs2_is_imm ? {`NUM_THREADS{alu_req_if.imm}} : alu_in2;
|
||||
|
||||
for (i = 0; i < `NUM_THREADS; i++) begin
|
||||
wire negate_add = (alu_op == `ALU_SUB);
|
||||
wire signed_less = (alu_op == `ALU_SLT);
|
||||
wire signed_shift = (alu_op == `ALU_SRA);
|
||||
|
||||
wire [32:0] sub_in1 = {(alu_op != `ALU_SLTU) & (alu_op != `ALU_BLTU) & (alu_op != `ALU_BGEU) & alu_in1[i][31], alu_in1[i]};
|
||||
wire [32:0] sub_in2 = {(alu_op != `ALU_SLTU) & (alu_op != `ALU_BLTU) & (alu_op != `ALU_BGEU) & alu_in2[i][31], alu_in2[i]};
|
||||
assign sub_result[i] = $signed(sub_in1) - $signed(sub_in2);
|
||||
for (genvar i = 0; i < `NUM_THREADS; i++) begin
|
||||
wire [32:0] addsub_in1 = {alu_in1_PC[i], 1'b1};
|
||||
wire [32:0] addsub_in2 = {alu_in2_imm[i], 1'b0} ^ {33{negate_add}};
|
||||
`IGNORE_WARNINGS_BEGIN
|
||||
wire [32:0] addsub_addd = addsub_in1 + addsub_in2;
|
||||
`IGNORE_WARNINGS_END
|
||||
assign addsub_result[i] = addsub_addd[32:1];
|
||||
end
|
||||
|
||||
wire [32:0] shift_in1 = {(alu_op == `ALU_SRA) & alu_in1[i][31], alu_in1[i]};
|
||||
assign shift_result[i] = $signed(shift_in1) >>> alu_in2[i][4:0];
|
||||
|
||||
always @(*) begin
|
||||
case (alu_op)
|
||||
`ALU_SUB: alu_result[i] = sub_result[i][31:0];
|
||||
`ALU_SLL: alu_result[i] = alu_in1[i] << alu_in2[i][4:0];
|
||||
`ALU_SLT,
|
||||
`ALU_SLTU: alu_result[i] = 32'(sub_result[i][32]);
|
||||
`ALU_XOR: alu_result[i] = alu_in1[i] ^ alu_in2[i];
|
||||
`ALU_SRL,
|
||||
`ALU_SRA: alu_result[i] = shift_result[i][31:0];
|
||||
`ALU_OR: alu_result[i] = alu_in1[i] | alu_in2[i];
|
||||
`ALU_AND: alu_result[i] = alu_in1[i] & alu_in2[i];
|
||||
default: alu_result[i] = alu_in1[i] + alu_in2[i]; // ADD, LUI, AUIPC
|
||||
endcase
|
||||
end
|
||||
for (genvar i = 0; i < `NUM_THREADS; i++) begin
|
||||
wire [32:0] less_in1 = {signed_less & alu_in1[i][31], alu_in1[i]};
|
||||
wire [32:0] less_in2 = {signed_less & alu_in2_imm[i][31], alu_in2_imm[i]};
|
||||
assign less_result[i] = $signed(less_in1) < $signed(less_in2);
|
||||
end
|
||||
|
||||
for (genvar i = 0; i < `NUM_THREADS; i++) begin
|
||||
wire [32:0] shift_in1 = {signed_shift & alu_in1[i][31], alu_in1[i]};
|
||||
`IGNORE_WARNINGS_BEGIN
|
||||
wire [32:0] shift_value = $signed(shift_in1) >>> alu_in2_imm[i][4:0];
|
||||
`IGNORE_WARNINGS_END
|
||||
assign shift_result[i] = shift_value[31:0];
|
||||
end
|
||||
|
||||
wire [`NT_BITS-1:0] br_result_index;
|
||||
|
||||
VX_priority_encoder #(
|
||||
.N(`NUM_THREADS)
|
||||
) choose_alu_result (
|
||||
.data_in (alu_req_if.thread_mask),
|
||||
.data_out (br_result_index),
|
||||
`UNUSED_PIN (valid_out)
|
||||
);
|
||||
|
||||
wire [32:0] br_result = sub_result[br_result_index];
|
||||
wire br_sign = br_result[32];
|
||||
wire br_nzero = (| br_result[31:0]);
|
||||
wire br_sign_s1;
|
||||
wire br_nzero_s1;
|
||||
|
||||
wire [`BR_BITS-1:0] br_op = `IS_BR_OP(alu_req_if.alu_op) ? `BR_OP(alu_req_if.alu_op) : `BR_NO;
|
||||
wire [`BR_BITS-1:0] br_op_s1;
|
||||
|
||||
wire [31:0] br_addr = (br_op == `BR_JALR) ? alu_req_if.rs1_data[br_result_index] : alu_req_if.curr_PC;
|
||||
wire [31:0] br_dest = $signed(br_addr) + $signed(alu_req_if.offset);
|
||||
|
||||
wire is_jal = (alu_op == `ALU_JAL || alu_op == `ALU_JALR);
|
||||
wire [`NUM_THREADS-1:0][31:0] alu_jal_result = is_jal ? {`NUM_THREADS{alu_req_if.next_PC}} : alu_result;
|
||||
|
||||
wire stall = ~alu_commit_if.ready && alu_commit_if.valid;
|
||||
for (genvar i = 0; i < `NUM_THREADS; i++) begin
|
||||
always @(*) begin
|
||||
case (alu_op)
|
||||
`ALU_AND: misc_result[i] = alu_in1[i] & alu_in2_imm[i];
|
||||
`ALU_OR: misc_result[i] = alu_in1[i] | alu_in2_imm[i];
|
||||
`ALU_XOR: misc_result[i] = alu_in1[i] ^ alu_in2_imm[i];
|
||||
//`ALU_SLL,
|
||||
default: misc_result[i] = alu_in1[i] << alu_in2_imm[i][4:0];
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
for (genvar i = 0; i < `NUM_THREADS; i++) begin
|
||||
always @(*) begin
|
||||
case (`ALU_OP_CLASS(alu_op))
|
||||
0: alu_result[i] = addsub_result[i];
|
||||
1: alu_result[i] = {31'b0, less_result[i]};
|
||||
2: alu_result[i] = shift_result[i];
|
||||
default: alu_result[i] = misc_result[i];
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
VX_generic_register #(
|
||||
.N(1 + `NW_BITS + `ISTAG_BITS + (`NUM_THREADS * 32) + `BR_BITS + 32 + 1 + 1)
|
||||
.N(1 + `ISTAG_BITS + (`NUM_THREADS * 32))
|
||||
) alu_reg (
|
||||
.clk (clk),
|
||||
.reset (reset),
|
||||
.stall (stall),
|
||||
.stall (0),
|
||||
.flush (0),
|
||||
.in ({alu_req_if.valid, alu_req_if.warp_num, alu_req_if.issue_tag, alu_jal_result, br_op, br_dest, br_sign, br_nzero}),
|
||||
.out ({alu_commit_if.valid, branch_ctl_if.warp_num, alu_commit_if.issue_tag, alu_commit_if.data, br_op_s1, branch_ctl_if.dest, br_sign_s1, br_nzero_s1})
|
||||
);
|
||||
|
||||
reg br_taken;
|
||||
always @(*) begin
|
||||
case (br_op_s1)
|
||||
`BR_NE: br_taken = br_nzero_s1;
|
||||
`BR_EQ: br_taken = ~br_nzero_s1;
|
||||
`BR_LT,
|
||||
`BR_LTU: br_taken = br_sign_s1;
|
||||
`BR_GE,
|
||||
`BR_GEU: br_taken = ~br_sign_s1;
|
||||
default: br_taken = 1'b1;
|
||||
endcase
|
||||
end
|
||||
.in ({alu_req_if.valid, alu_req_if.issue_tag, alu_result}),
|
||||
.out ({alu_commit_if.valid, alu_commit_if.issue_tag, alu_commit_if.data})
|
||||
);
|
||||
|
||||
assign branch_ctl_if.valid = alu_commit_if.valid && (br_op_s1 != `BR_NO);
|
||||
assign branch_ctl_if.taken = br_taken;
|
||||
|
||||
assign alu_req_if.ready = ~stall;
|
||||
assign alu_req_if.ready = 1'b1;
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user