diff --git a/alu.sv b/alu.sv index 1f50b7f7..88fa9f77 100644 --- a/alu.sv +++ b/alu.sv @@ -31,22 +31,18 @@ module riscv_alu ( - input logic [`ALU_OP_WIDTH-1:0] operator_i, - input logic [31:0] operand_a_i, - input logic [31:0] operand_b_i, + input logic [`ALU_OP_WIDTH-1:0] operator_i, + input logic [31:0] operand_a_i, + input logic [31:0] operand_b_i, - input logic [1:0] vector_mode_i, - input logic [1:0] cmp_mode_i, - input logic [1:0] vec_ext_i, - - output logic [31:0] result_o, - output logic flag_o + output logic [31:0] result_o, + output logic comparison_result_o ); - logic [31:0] operand_a_rev; // bit reversed signal of operand_a_i + logic [31:0] operand_a_rev; - // bit reverse operand_a for left shifts + // bit reverse operand_a for left shifts and bit counting genvar k; generate for(k = 0; k < 32; k++) @@ -55,17 +51,17 @@ module riscv_alu end endgenerate - ////////////////////////////////////////////////////////////////////////////////////////// - // ____ _ _ _ _ _ _ _ _ // - // | _ \ __ _ _ __| |_(_) |_(_) ___ _ __ ___ __| | / \ __| | __| | ___ _ __ // - // | |_) / _` | '__| __| | __| |/ _ \| '_ \ / _ \/ _` | / _ \ / _` |/ _` |/ _ \ '__| // - // | __/ (_| | | | |_| | |_| | (_) | | | | __/ (_| | / ___ \ (_| | (_| | __/ | // - // |_| \__,_|_| \__|_|\__|_|\___/|_| |_|\___|\__,_| /_/ \_\__,_|\__,_|\___|_| // - // // - ////////////////////////////////////////////////////////////////////////////////////////// - logic [3:0] carry_in; - logic [3:0] carry_out; + ///////////////////////////////////// + // _ _ _ // + // / \ __| | __| | ___ _ __ // + // / _ \ / _` |/ _` |/ _ \ '__| // + // / ___ \ (_| | (_| | __/ | // + // /_/ \_\__,_|\__,_|\___|_| // + // // + ///////////////////////////////////// + + logic carry_in; logic [31:0] adder_op_a; logic [31:0] adder_op_b; logic [31:0] adder_result; @@ -76,75 +72,25 @@ module riscv_alu // prepare operand b assign adder_op_b = (operator_i == `ALU_SUB) ? ~operand_b_i : operand_b_i; - // prepare vector carrys + // prepare carry always_comb begin - carry_in = {carry_out[2], carry_out[1], carry_out[0], 1'b0}; - case (operator_i) - `ALU_SUB, `ALU_ABS: - begin - case (vector_mode_i) - `VEC_MODE16: - begin - carry_in[0] = 1'b1; - carry_in[2] = 1'b1; - end - - `VEC_MODE8: - begin - carry_in = 4'b1111; - end - - default: // VEC_MODE32 - begin - carry_in[0] = 1'b1; - end - endcase - end - - default: - begin - case (vector_mode_i) - `VEC_MODE16: - begin - carry_in[0] = 1'b0; - carry_in[2] = 1'b0; - end - - `VEC_MODE8: - begin - carry_in = 4'b0000; - end - - default: // VEC_MODE32 - begin - carry_in[0] = 1'b0; - end - endcase - end + `ALU_SUB, + `ALU_ABS: carry_in = 1'b1; + default: carry_in = 1'b0; endcase end - // adder consisting of four slices - assign {carry_out[0], adder_result[ 7: 0]} = adder_op_a[ 7: 0] + adder_op_b[ 7: 0] + {7'b0, carry_in[0]}; - assign {carry_out[1], adder_result[15: 8]} = adder_op_a[15: 8] + adder_op_b[15: 8] + {7'b0, carry_in[1]}; - assign {carry_out[2], adder_result[23:16]} = adder_op_a[23:16] + adder_op_b[23:16] + {7'b0, carry_in[2]}; - assign {carry_out[3], adder_result[31:24]} = adder_op_a[31:24] + adder_op_b[31:24] + {7'b0, carry_in[3]}; + // adder + assign adder_result = adder_op_a + adder_op_b + {31'b0, carry_in}; // averaging by right shifting of one bit logic [31:0] result_avg; - assign result_avg[ 6: 0] = adder_result[ 7: 1]; - assign result_avg[14: 8] = adder_result[15: 9]; - assign result_avg[22:16] = adder_result[23:17]; - assign result_avg[30:24] = adder_result[31:25]; - - assign result_avg[ 7] = (vector_mode_i == `VEC_MODE8) ? ((operator_i == `ALU_AVGU) ? 1'b0 : adder_result[ 7]) : adder_result[ 8]; - assign result_avg[15] = ((vector_mode_i == `VEC_MODE16) || (vector_mode_i == `VEC_MODE8)) ? ((operator_i == `ALU_AVGU) ? 1'b0 : adder_result[15]) : adder_result[16]; - assign result_avg[23] = (vector_mode_i == `VEC_MODE8) ? ((operator_i == `ALU_AVGU) ? 1'b0 : adder_result[23]) : adder_result[24]; - assign result_avg[31] = (operator_i == `ALU_AVGU) ? 1'b0 : adder_result[31]; + assign result_avg[30:0] = adder_result[31:1]; + assign result_avg[31] = (operator_i == `ALU_AVGU) ? 1'b0 : adder_result[31]; //////////////////////////////////////// @@ -155,90 +101,28 @@ module riscv_alu // |____/|_| |_|___|_| |_| // // // //////////////////////////////////////// - logic shift_left; // should we shift left? + + logic shift_left; // should we shift left logic [31:0] shift_amt; // amount of shift - logic [31:0] shift_amt_left; // amount of shift, adapted to vector mode for sll - logic [31:0] shift_amt_int; // amount of shift, adapted to vector mode for sll logic [31:0] shift_op_a; // input of the shifter logic [31:0] shift_result; logic [31:0] shift_left_result; - // by reversing the bits of the input, we also have the reverse the order of shift amounts - always_comb - begin - case(vector_mode_i) - `VEC_MODE16: - begin - shift_amt_left[15: 0] = shift_amt[31:16]; - shift_amt_left[31:16] = shift_amt[15: 0]; - end - - `VEC_MODE8: - begin - shift_amt_left[ 7: 0] = shift_amt[31:24]; - shift_amt_left[15: 8] = shift_amt[23:16]; - shift_amt_left[23:16] = shift_amt[15: 8]; - shift_amt_left[31:24] = shift_amt[ 7: 0]; - end - - default: // VEC_MODE32 - begin - shift_amt_left[31: 0] = shift_amt[31: 0]; - end - endcase - end + assign shift_left = (operator_i == `ALU_SLL); // choose the bit reversed or the normal input for shift operand a - assign shift_op_a = (shift_left == 1'b1) ? operand_a_rev : operand_a_i; - assign shift_amt_int = (shift_left == 1'b1) ? shift_amt_left : shift_amt; + assign shift_op_a = (shift_left == 1'b1) ? operand_a_rev : operand_a_i; - // right shifts, we let the synthesizer optimize this + // right shifts always_comb begin - case(vector_mode_i) - `VEC_MODE16: - begin - if(operator_i == `ALU_SRA) - begin - shift_result[31:16] = $unsigned( $signed(shift_op_a[31:16]) >>> shift_amt_int[19:16] ); - shift_result[15: 0] = $unsigned( $signed(shift_op_a[15: 0]) >>> shift_amt_int[ 3: 0] ); - end - else - begin - shift_result[31:16] = shift_op_a[31:16] >> shift_amt_int[19:16]; - shift_result[15: 0] = shift_op_a[15: 0] >> shift_amt_int[ 3: 0]; - end - end - - `VEC_MODE8: - begin - if(operator_i == `ALU_SRA) - begin - shift_result[31:24] = $unsigned( $signed(shift_op_a[31:24]) >>> shift_amt_int[26:24] ); - shift_result[23:16] = $unsigned( $signed(shift_op_a[23:16]) >>> shift_amt_int[18:16] ); - shift_result[15: 8] = $unsigned( $signed(shift_op_a[15: 8]) >>> shift_amt_int[10: 8] ); - shift_result[ 7: 0] = $unsigned( $signed(shift_op_a[ 7: 0]) >>> shift_amt_int[ 2: 0] ); - end - else - begin - shift_result[31:24] = shift_op_a[31:24] >> shift_amt_int[26:24]; - shift_result[23:16] = shift_op_a[23:16] >> shift_amt_int[18:16]; - shift_result[15: 8] = shift_op_a[15: 8] >> shift_amt_int[10: 8]; - shift_result[ 7: 0] = shift_op_a[ 7: 0] >> shift_amt_int[ 2: 0]; - end - end - - default: // VEC_MODE32 - begin - if(operator_i == `ALU_SRA) - shift_result = $unsigned( $signed(shift_op_a) >>> shift_amt_int[4:0] ); - else if(operator_i == `ALU_ROR) - shift_result = {shift_op_a, shift_op_a} >> shift_amt_int[4:0]; - else - shift_result = shift_op_a >> shift_amt_int[4:0]; - end - endcase; // case (vec_mode_i) + if(operator_i == `ALU_SRA) + shift_result = $unsigned( $signed(shift_op_a) >>> shift_amt[4:0] ); + else if(operator_i == `ALU_ROR) + shift_result = {shift_op_a, shift_op_a} >> shift_amt[4:0]; + else + shift_result = shift_op_a >> shift_amt[4:0]; end // bit reverse the shift_result for left shifts @@ -251,7 +135,6 @@ module riscv_alu endgenerate - ////////////////////////////////////////////////////////////////// // ____ ___ __ __ ____ _ ____ ___ ____ ___ _ _ // // / ___/ _ \| \/ | _ \ / \ | _ \|_ _/ ___| / _ \| \ | | // @@ -261,145 +144,60 @@ module riscv_alu // // ////////////////////////////////////////////////////////////////// - // results - logic [3:0] is_equal; - logic [3:0] is_greater; // handles both signed and unsigned forms - - logic [3:0] sel_minmax; // mux control - logic [31:0] result_minmax; - logic [31:0] minmax_b; - - - logic do_min; - - // 8-bit vector comparisons, basic building blocks - logic [3:0] cmp_sign_mode; - logic [3:0] is_equal_vec; - logic [3:0] is_greater_vec; - - - // generate cmp_sign_mode signal that is used for comparisons below - always_comb - begin - cmp_sign_mode[3:0] = 4'b0000; // unsigned mode - - // signed mode - if ((operator_i == `ALU_GTS) || - (operator_i == `ALU_GES) || - (operator_i == `ALU_LTS) || - (operator_i == `ALU_SLTS) || - (operator_i == `ALU_SLETS) || - (operator_i == `ALU_LES) || - (operator_i == `ALU_MAX) || - (operator_i == `ALU_MIN) || - (operator_i == `ALU_ABS)) - begin - case (vector_mode_i) - `VEC_MODE16: cmp_sign_mode[3:0] = 4'b1010; - `VEC_MODE8: cmp_sign_mode[3:0] = 4'b1111; - default: cmp_sign_mode[3:0] = 4'b1000; - endcase - end - end - - // generate vector equal and greater than signals, cmp_sign_mode decides if the comparison is done signed or unsigned - genvar i; - generate - for(i = 0; i < 4; i++) - begin - assign is_equal_vec[i] = (operand_a_i[8*i+7:8*i] == operand_b_i[8*i+7:i*8]); - assign is_greater_vec[i] = $signed({operand_a_i[8*i+7] & cmp_sign_mode[i], operand_a_i[8*i+7:8*i]}) - > - $signed({operand_b_i[8*i+7] & cmp_sign_mode[i], operand_b_i[8*i+7:i*8]}); - end - endgenerate + logic is_equal; + logic is_greater; + logic cmp_signed; always_comb begin - is_equal[3:0] = {4{is_equal_vec[3] & is_equal_vec[2] & is_equal_vec[1] & is_equal_vec[0]}}; - is_greater[3:0] = {4{is_greater_vec[3] | (is_equal_vec[3] & (is_greater_vec[2] - | (is_equal_vec[2] & (is_greater_vec[1] - | (is_equal_vec[1] & (is_greater_vec[0]))))))}}; + cmp_signed = 1'b0; - case(vector_mode_i) - `VEC_MODE16: - begin - is_equal[1:0] = {2{is_equal_vec[0] & is_equal_vec[1]}}; - is_equal[3:2] = {2{is_equal_vec[2] & is_equal_vec[3]}}; - is_greater[1:0] = {2{is_greater_vec[1] | (is_equal_vec[1] & is_greater_vec[0])}}; - is_greater[3:2] = {2{is_greater_vec[3] | (is_equal_vec[3] & is_greater_vec[2])}}; - end - - `VEC_MODE8: - begin - is_equal[3:0] = is_equal_vec[3:0]; - is_greater[3:0] = is_greater_vec[3:0]; - end - - default:; // see default assignment + case (operator_i) + `ALU_GTS, + `ALU_GES, + `ALU_LTS, + `ALU_LES, + `ALU_SLTS, + `ALU_SLETS, + `ALU_MIN, + `ALU_MAX, + `ALU_ABS: cmp_signed = 1'b1; endcase end - // generate comparison results - logic [3:0] cmp_result; - logic any_result; - logic all_result; + assign is_equal = (operand_a_i == operand_b_i); + assign is_greater = $signed({operand_a_i[31] & cmp_signed, operand_a_i[30:0]}) + > + $signed({operand_b_i[31] & cmp_signed, operand_b_i[30:0]}); + // generate comparison result always_comb begin - cmp_result = is_equal; + comparison_result_o = is_equal; case (operator_i) - `ALU_EQ: cmp_result = is_equal; - `ALU_NE: cmp_result = ~is_equal; - `ALU_GTS, `ALU_GTU: cmp_result = is_greater; - `ALU_GES, `ALU_GEU: cmp_result = is_greater | is_equal; + `ALU_EQ: comparison_result_o = is_equal; + `ALU_NE: comparison_result_o = ~is_equal; + `ALU_GTS, `ALU_GTU: comparison_result_o = is_greater; + `ALU_GES, `ALU_GEU: comparison_result_o = is_greater | is_equal; `ALU_LTS, `ALU_SLTS, - `ALU_LTU, `ALU_SLTU: cmp_result = ~(is_greater | is_equal); + `ALU_LTU, `ALU_SLTU: comparison_result_o = ~(is_greater | is_equal); `ALU_SLETS, `ALU_SLETU, - `ALU_LES, `ALU_LEU: cmp_result = ~is_greater; - default:; // nothing to do - endcase //~case(operator_i) + `ALU_LES, `ALU_LEU: comparison_result_o = ~is_greater; + endcase end - assign any_result = |cmp_result; - assign all_result = &cmp_result; + logic [31:0] result_minmax; + logic sel_minmax; + logic [31:0] minmax_b; - // choose result value for min/max/abs assign minmax_b = (operator_i == `ALU_ABS) ? adder_result : operand_b_i; - assign do_min = ((operator_i == `ALU_MIN) || (operator_i == `ALU_MINU)); - - // reuse the minmax mux also for the cmove instruction - // the mux now handles, min, max, abs, cmov, ins - always_comb - begin - sel_minmax[3:0] = is_greater ^ {4{do_min}}; - - if(operator_i == `ALU_INS) - begin - if(vector_mode_i == `VEC_MODE16) - begin - sel_minmax[1:0] = {2{vec_ext_i[0]}}; - sel_minmax[3:2] = ~{2{vec_ext_i[0]}}; - end - else // `VEC_MODE8 - begin - sel_minmax[0] = (vec_ext_i != 2'b00); - sel_minmax[1] = (vec_ext_i != 2'b01); - sel_minmax[2] = (vec_ext_i != 2'b10); - sel_minmax[3] = (vec_ext_i != 2'b11); - end - end - end - - assign result_minmax[31:24] = (sel_minmax[3] == 1'b1) ? operand_a_i[31:24] : minmax_b[31:24]; - assign result_minmax[23:16] = (sel_minmax[2] == 1'b1) ? operand_a_i[23:16] : minmax_b[23:16]; - assign result_minmax[15: 8] = (sel_minmax[1] == 1'b1) ? operand_a_i[15: 8] : minmax_b[15: 8]; - assign result_minmax[ 7: 0] = (sel_minmax[0] == 1'b1) ? operand_a_i[ 7: 0] : minmax_b[ 7: 0]; + assign sel_minmax = is_greater ^ ((operator_i == `ALU_MIN) || (operator_i == `ALU_MINU)); + assign result_minmax = sel_minmax ? operand_a_i[31:0] : minmax_b[31:0]; ////////////////////////////////////////////////// @@ -411,45 +209,27 @@ module riscv_alu // // ////////////////////////////////////////////////// - logic [7:0] ext_byte; - logic [15:0] ext_word; logic [31:0] result_ext; - always_comb - begin - ext_byte = operand_a_i[7:0]; - - if(operator_i == `ALU_EXT) - begin - case(vec_ext_i) - 2'b00: ext_byte = operand_a_i[ 7: 0]; - 2'b01: ext_byte = operand_a_i[15: 8]; - 2'b10: ext_byte = operand_a_i[23:16]; - 2'b11: ext_byte = operand_a_i[31:24]; - endcase - end - end - - assign ext_word = ((vec_ext_i[0] == 1'b1) && (operator_i == `ALU_EXT)) ? operand_a_i[31:16] : operand_a_i[15:0]; - always_comb begin // zero extend byte - result_ext = {24'b0, ext_byte[7:0]}; + result_ext = {24'b0, operand_a_i[7:0]}; // sign extend byte - if((operator_i == `ALU_EXTBS) || ((operator_i == `ALU_EXT) && (vector_mode_i == `VEC_MODE8))) - result_ext = {{24{ext_byte[7]}}, ext_byte[7:0]}; + if (operator_i == `ALU_EXTBS) + result_ext = {{24 {operand_a_i[7]}}, operand_a_i[7:0]}; // zero extend half word if(operator_i == `ALU_EXTHZ) - result_ext = {16'b0, ext_word[15:0]}; + result_ext = {16'b0, operand_a_i[15:0]}; // sign extend half word - if((operator_i == `ALU_EXTHS) || ((operator_i == `ALU_EXT) && (vector_mode_i == `VEC_MODE16))) - result_ext = {{16{ext_word[15]}}, ext_word[15:0]}; + if(operator_i == `ALU_EXTHS) + result_ext = {{16 {operand_a_i[15]}}, operand_a_i[15:0]}; end + ///////////////////////////////////////////////////////////////////// // ____ _ _ ____ _ ___ // // | __ )(_) |_ / ___|___ _ _ _ __ | |_ / _ \ _ __ ___ // @@ -487,9 +267,8 @@ module riscv_alu assign fl1_result = (ff1_result == 6'd0) ? 6'd0 : (6'd33 - ff1_result); assign clb_result = (ff1_result == 6'd0) ? 6'd0 : (ff1_result - 6'd2); - // count the number of '1's in a word - logic [5:0] cnt_result; // holds the number of '1's in a word + logic [5:0] cnt_result; logic [1:0] cnt_l1[16]; logic [2:0] cnt_l2[8]; logic [3:0] cnt_l3[4]; @@ -522,6 +301,7 @@ module riscv_alu assign cnt_result = cnt_l4[0] + cnt_l4[1]; + //////////////////////////////////////////////////////// // ____ _ _ __ __ // // | _ \ ___ ___ _ _| | |_ | \/ |_ ___ __ // @@ -533,77 +313,58 @@ module riscv_alu always_comb begin - shift_left = 1'b0; shift_amt = operand_b_i; result_o = 'x; - flag_o = 1'bx; - unique case (operator_i) + case (operator_i) // Standard Operations - `ALU_ADD, `ALU_SUB: result_o = adder_result; - `ALU_AVG, `ALU_AVGU: result_o = result_avg; - `ALU_AND: result_o = operand_a_i & operand_b_i; - `ALU_OR: result_o = operand_a_i | operand_b_i; - `ALU_XOR: result_o = operand_a_i ^ operand_b_i; + `ALU_ADD, + `ALU_SUB: result_o = adder_result; + `ALU_AVG, + `ALU_AVGU: result_o = result_avg; + `ALU_AND: result_o = operand_a_i & operand_b_i; + `ALU_OR: result_o = operand_a_i | operand_b_i; + `ALU_XOR: result_o = operand_a_i ^ operand_b_i; // Shift Operations - `ALU_SLL: - begin - shift_left = 1'b1; - result_o = shift_left_result; - end + `ALU_SLL: result_o = shift_left_result; - `ALU_SRL, `ALU_SRA, `ALU_ROR: begin - shift_left = 1'b0; - result_o = shift_result; - end + `ALU_SRL, + `ALU_SRA, + `ALU_ROR: result_o = shift_result; // Extension Operations - `ALU_EXTWZ, `ALU_EXTWS: result_o = operand_a_i; - `ALU_EXTBZ, `ALU_EXTBS, `ALU_EXTHZ, `ALU_EXTHS, `ALU_EXT: result_o = result_ext; + `ALU_EXTBZ, + `ALU_EXTBS, + `ALU_EXTHZ, + `ALU_EXTHS: result_o = result_ext; - // Min/Max/Abs, INS - `ALU_MIN, `ALU_MINU, `ALU_MAX, `ALU_MAXU, `ALU_ABS, `ALU_INS: result_o = result_minmax; + // Min/Max/Abs + `ALU_MIN, `ALU_MINU, + `ALU_MAX, `ALU_MAXU, + `ALU_ABS: result_o = result_minmax; // Comparison Operations `ALU_EQ, `ALU_NE, `ALU_GTU, `ALU_GEU, `ALU_LTU, `ALU_LEU, `ALU_GTS, `ALU_GES, `ALU_LTS, `ALU_LES: begin - result_o[31:24] = {8{cmp_result[3]}}; - result_o[23:16] = {8{cmp_result[2]}}; - result_o[15: 8] = {8{cmp_result[1]}}; - result_o[ 7: 0] = {8{cmp_result[0]}}; - - case (cmp_mode_i) - `ALU_CMP_ANY: - begin - flag_o = any_result; - end - `ALU_CMP_ALL: - begin - flag_o = all_result; - end - `ALU_CMP_FULL: - begin - flag_o = cmp_result[0]; - end - default:; - endcase //~case(cmp_mode_i) + // TODO: Check which comparison operations are actually used + // Probably it's just slts/stlu/slets/sletu plus what is needed + // for branching after the flag is removed + result_o = {31'b0, comparison_result_o}; end // Set Lower Than Operations (result = 1, if a < b) - `ALU_SLTS, `ALU_SLTU: result_o = {31'b0, cmp_result[0]}; + `ALU_SLTS, `ALU_SLTU: result_o = {31'b0, comparison_result_o}; // Set Lower Equal Than Operations (result = 1, if a <= b) - `ALU_SLETS, `ALU_SLETU: result_o = {31'b0, cmp_result[0]}; + `ALU_SLETS, `ALU_SLETU: result_o = {31'b0, comparison_result_o}; `ALU_FF1: result_o = {26'h0, ff1_result}; `ALU_FL1: result_o = {26'h0, fl1_result}; `ALU_CLB: result_o = {26'h0, clb_result}; `ALU_CNT: result_o = {26'h0, cnt_result}; - - default: ; - endcase //~case(operator_i) + endcase end -endmodule //~module alu +endmodule diff --git a/compressed_decoder.sv b/compressed_decoder.sv index 70304968..af65f933 100644 --- a/compressed_decoder.sv +++ b/compressed_decoder.sv @@ -51,44 +51,19 @@ module riscv_compressed_decoder 2'b00: begin unique case (instr_i[15:13]) 3'b000: begin - if (instr_i[12] == 1'b0) begin - // c.mv -> add rd/rs1, x0, rs2 - instr_o = {7'b0, instr_i[6:2], 5'b0, 3'b0, instr_i[11:7], `OPCODE_OP}; - - if (instr_i[6:2] == 5'b0) begin - // c.jr -> jalr x0, rd/rs1, 0 - instr_o = {12'b0, instr_i[11:7], 3'b0, 5'b0, `OPCODE_JALR}; - end - end else begin - // c.add -> add rd, rd, rs2 - instr_o = {7'b0, instr_i[6:2], instr_i[11:7], 3'b000, instr_i[11:7], `OPCODE_OP}; - - if (instr_i[11:7] == 5'b0) begin - // c.ebreak -> ebreak - instr_o = {32'h00_10_00_73}; - if (instr_i[6:2] != 5'b0) - illegal_instr_o = 1'b1; - end else if (instr_i[6:2] == 5'b0) begin - // c.jalr -> jalr x1, rs1, 0 - instr_o = {12'b0, instr_i[11:7], 3'b000, 5'b00001, `OPCODE_JALR}; - end - end - + // c.addi4spn -> addi rd', x2, imm + instr_o = {2'b0, instr_i[10:7], instr_i[12:11], instr_i[5], instr_i[6], 2'b00, 5'h02, 3'b000, 2'b01, instr_i[4:2], `OPCODE_OPIMM}; + if (instr_i[12:5] == 8'b0) illegal_instr_o = 1'b1; end 3'b010: begin - // c.sw -> sw rs2', imm(rs1') - instr_o = {5'b0, instr_i[5], instr_i[12], 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b010, instr_i[11:10], instr_i[6], 2'b00, `OPCODE_STORE}; - end - - 3'b100: begin - // c.addi4spn -> addi rd', x2, imm - instr_o = {2'b0, instr_i[10:7], instr_i[12:11], instr_i[5], instr_i[6], 2'b00, 5'h02, 3'b000, 2'b01, instr_i[4:2], `OPCODE_OPIMM}; + // c.lw -> lw rd', imm(rs1') + instr_o = {5'b0, instr_i[5], instr_i[12:10], instr_i[6], 2'b00, 2'b01, instr_i[9:7], 3'b010, 2'b01, instr_i[4:2], `OPCODE_LOAD}; end 3'b110: begin - // c.lw -> lw rd', imm(rs1') - instr_o = {5'b0, instr_i[5], instr_i[12:10], instr_i[6], 2'b00, 2'b01, instr_i[9:7], 3'b010, 2'b01, instr_i[4:2], `OPCODE_LOAD}; + // c.sw -> sw rs2', imm(rs1') + instr_o = {5'b0, instr_i[5], instr_i[12], 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b010, instr_i[11:10], instr_i[6], 2'b00, `OPCODE_STORE}; end default: begin @@ -101,21 +76,89 @@ module riscv_compressed_decoder 2'b01: begin unique case (instr_i[15:13]) 3'b000: begin - // c.slli -> slli rd, rd, shamt - instr_o = {7'b0, instr_i[6:2], instr_i[11:7], 3'b001, instr_i[11:7], `OPCODE_OPIMM}; - if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1; - if (instr_i[12] == 1'b1 || instr_i[6:2] == 5'b0) illegal_instr_o = 1'b1; + // c.addi -> addi rd, rd, nzimm + // c.nop + instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], instr_i[11:7], 3'b0, instr_i[11:7], `OPCODE_OPIMM}; + end + + 3'b001, 3'b101: begin + // 001: c.jal -> jal x1, imm + // 101: c.j -> jal x0, imm + instr_o = {instr_i[12], instr_i[8], instr_i[10:9], instr_i[6], instr_i[7], instr_i[2], instr_i[11], instr_i[5:3], {9 {instr_i[12]}}, 4'b0, ~instr_i[15], `OPCODE_JAL}; end 3'b010: begin - // c.swsp -> sw rs2, imm(x2) - instr_o = {4'b0, instr_i[8:7], instr_i[12], instr_i[6:2], 5'h02, 3'b010, instr_i[11:9], 2'b00, `OPCODE_STORE}; + // c.li -> addi rd, x0, nzimm + instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], 5'b0, 3'b0, instr_i[11:7], `OPCODE_OPIMM}; + if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1; end - 3'b110: begin - // c.lwsp -> lw rd, imm(x2) - instr_o = {4'b0, instr_i[3:2], instr_i[12], instr_i[6:4], 2'b00, 5'h02, 3'b010, instr_i[11:7], `OPCODE_LOAD}; - if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1; + 3'b011: begin + // c.lui -> lui rd, imm + instr_o = {{15 {instr_i[12]}}, instr_i[6:2], instr_i[11:7], `OPCODE_LUI}; + + if (instr_i[11:7] == 5'h02) begin + // c.addi16sp -> addi x2, x2, nzimm + instr_o = {{3 {instr_i[12]}}, instr_i[4:3], instr_i[5], instr_i[2], instr_i[6], 4'b0, 5'h02, 3'b000, 5'h02, `OPCODE_OPIMM}; + end else if (instr_i[11:7] == 5'b0) begin + illegal_instr_o = 1'b1; + end + + if ({instr_i[12], instr_i[6:2]} == 6'b0) illegal_instr_o = 1'b1; + end + + 3'b100: begin + unique case (instr_i[11:10]) + 2'b00, + 2'b01: begin + // 00: c.srli -> srli rd, rd, shamt + // 01: c.srai -> srai rd, rd, shamt + instr_o = {1'b0, instr_i[10], 5'b0, instr_i[6:2], 2'b01, instr_i[9:7], 3'b101, 2'b01, instr_i[9:7], `OPCODE_OPIMM}; + if (instr_i[12] == 1'b1) illegal_instr_o = 1'b1; + if (instr_i[6:2] == 5'b0) illegal_instr_o = 1'b1; + if (instr_i[9:7] == 5'b0) illegal_instr_o = 1'b1; + end + + 2'b10: begin + // c.andi -> andi rd, rd, imm + instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], 2'b01, instr_i[9:7], 3'b111, 2'b01, instr_i[9:7], `OPCODE_OPIMM}; + end + + 2'b11: begin + unique case ({instr_i[12], instr_i[6:5]}) + 3'b001, + 3'b100, + 3'b101, + 3'b110, + 3'b111: begin + // 001: c.sll -> sll rd', rd', rs2' + // 100: c.xor -> xor rd', rd', rs2' + // 101: c.srl -> srl rd', rd', rs2' + // 110: c.or -> or rd', rd', rs2' + // 111: c.and -> and rd', rd', rs2' + instr_o = {7'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], instr_i[12], instr_i[6:5], 2'b01, instr_i[9:7], `OPCODE_OP}; + end + + 3'b000, + 3'b010: begin + // 000: c.addw + // 010: c.subw + illegal_instr_o = 1'b1; + end + + 3'b011: begin + // c.sub -> sub rd', rd', rs2' + instr_o = {2'b01, 5'b0, 2'b01, instr_i[4:2], 2'b01, instr_i[9:7], 3'b000, 2'b01, instr_i[9:7], `OPCODE_OP}; + end + endcase + end + endcase + end + + 3'b110, 3'b111: begin + // 0: c.beqz -> beq rs1', x0, imm + // 1: c.bnez -> bne rs1', x0, imm + instr_o = {{4 {instr_i[12]}}, instr_i[6:5], instr_i[2], 5'b0, 2'b01, instr_i[9:7], 2'b00, instr_i[13], instr_i[11:10], instr_i[4:3], instr_i[12], `OPCODE_BRANCH}; end default: begin @@ -127,41 +170,47 @@ module riscv_compressed_decoder // C2 2'b10: begin unique case (instr_i[15:13]) - 3'b000, 3'b001: begin - // 0: c.j -> jal x0, imm - // 1: c.jal -> jal x1, imm - instr_o = {instr_i[12], instr_i[11:7], instr_i[2], instr_i[6:3], {9 {instr_i[12]}}, 4'b0, instr_i[13], `OPCODE_JAL}; + 3'b000: begin + // c.slli -> slli rd, rd, shamt + instr_o = {7'b0, instr_i[6:2], instr_i[11:7], 3'b001, instr_i[11:7], `OPCODE_OPIMM}; + if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1; + if (instr_i[12] == 1'b1 || instr_i[6:2] == 5'b0) illegal_instr_o = 1'b1; end - 3'b010, 3'b011: begin - // 0: c.beqz -> beq rs1', x0, imm - // 1: c.bnez -> bne rs1', x0, imm - instr_o = {{3 {instr_i[12]}}, instr_i[12:10], instr_i[2], 5'b0, 2'b01, instr_i[9:7], 2'b00, instr_i[13], instr_i[6:3], instr_i[12], `OPCODE_BRANCH}; - end - - 3'b100: begin - // c.li -> addi rd, x0, nzimm - instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], 5'b0, 3'b0, instr_i[11:7], `OPCODE_OPIMM}; - + 3'b010: begin + // c.lwsp -> lw rd, imm(x2) + instr_o = {4'b0, instr_i[3:2], instr_i[12], instr_i[6:4], 2'b00, 5'h02, 3'b010, instr_i[11:7], `OPCODE_LOAD}; if (instr_i[11:7] == 5'b0) illegal_instr_o = 1'b1; end - 3'b101: begin - // c.lui -> lui rd, imm - instr_o = {{15 {instr_i[12]}}, instr_i[6:2], instr_i[11:7], `OPCODE_LUI}; + 3'b100: begin + if (instr_i[12] == 1'b0) begin + // c.mv -> add rd/rs1, x0, rs2 + instr_o = {7'b0, instr_i[6:2], 5'b0, 3'b0, instr_i[11:7], `OPCODE_OP}; - if (instr_i[11:7] == 5'b0) begin - // c.addi16sp -> addi x2, x2, nzimm - instr_o = {{3 {instr_i[12]}}, instr_i[4:2], instr_i[5], instr_i[6], 4'b0, 5'h02, 3'b000, 5'h02, `OPCODE_OPIMM}; + if (instr_i[6:2] == 5'b0) begin + // c.jr -> jalr x0, rd/rs1, 0 + instr_o = {12'b0, instr_i[11:7], 3'b0, 5'b0, `OPCODE_JALR}; + end + end else begin + // c.add -> add rd, rd, rs2 + instr_o = {7'b0, instr_i[6:2], instr_i[11:7], 3'b0, instr_i[11:7], `OPCODE_OP}; + + if (instr_i[11:7] == 5'b0) begin + // c.ebreak -> ebreak + instr_o = {32'h00_10_00_73}; + if (instr_i[6:2] != 5'b0) + illegal_instr_o = 1'b1; + end else if (instr_i[6:2] == 5'b0) begin + // c.jalr -> jalr x1, rs1, 0 + instr_o = {12'b0, instr_i[11:7], 3'b000, 5'b00001, `OPCODE_JALR}; + end end - - if ({instr_i[12], instr_i[6:2]} == 6'b0) illegal_instr_o = 1'b1; end 3'b110: begin - // c.addi -> addi rd, rd, nzimm - // c.nop - instr_o = {{6 {instr_i[12]}}, instr_i[12], instr_i[6:2], instr_i[11:7], 3'b0, instr_i[11:7], `OPCODE_OPIMM}; + // c.swsp -> sw rs2, imm(x2) + instr_o = {4'b0, instr_i[8:7], instr_i[12], instr_i[6:2], 5'h02, 3'b010, instr_i[11:9], 2'b00, `OPCODE_STORE}; end default: begin @@ -170,7 +219,6 @@ module riscv_compressed_decoder endcase end - // 2'b11: default: begin // 32 bit (or more) instruction instr_o = instr_i; diff --git a/controller.sv b/controller.sv index 6ce67932..8048e0d8 100644 --- a/controller.sv +++ b/controller.sv @@ -149,7 +149,6 @@ module riscv_controller if (illegal_insn_o) begin $display("%t: Illegal instruction (core %0d) at PC 0x%h:", $time, riscv_core.core_id_i, riscv_id_stage.current_pc_id_i); - //prettyPrintInstruction(instr_rdata_i, id_stage.current_pc_id_i); end end // synopsys translate_on diff --git a/decoder.sv b/decoder.sv index b7f7e337..6476f5f1 100644 --- a/decoder.sv +++ b/decoder.sv @@ -50,12 +50,10 @@ module riscv_decoder output logic [`ALU_OP_WIDTH-1:0] alu_operator_o, // ALU operation selection output logic [1:0] alu_op_a_mux_sel_o, // operand a selection: reg value, PC, immediate or zero output logic [1:0] alu_op_b_mux_sel_o, // operand b selection: reg value or immediate + output logic [1:0] alu_op_c_mux_sel_o, // operand c selection: reg value or jump target output logic [2:0] immediate_mux_sel_o, // immediate selection for operand b - output logic alu_op_c_mux_sel_o, // operand c selection: reg value or jump target - output logic [1:0] vector_mode_o, // selects between 32 bit, 16 bit and 8 bit vectorial modes - output logic scalar_replication_o, // activates scalar_replication for vectorial mode - output logic [1:0] alu_cmp_mode_o, // selects comparison mode for ALU (i.e. full, any, all) + output logic vector_mode_o, // selects between 32 bit, 16 bit and 8 bit vectorial modes // MUL related control signals output logic mult_en_o, // perform multiplication @@ -131,9 +129,7 @@ module riscv_decoder immediate_mux_sel_o = `IMM_I; - vector_mode_o = `VEC_MODE32; - scalar_replication_o = 1'b0; - alu_cmp_mode_o = `ALU_CMP_FULL; + vector_mode_o = 1'b0; mult_en = 1'b0; mult_signed_mode_o = 2'b00; @@ -253,6 +249,9 @@ module riscv_decoder regb_used_o = 1'b1; alu_operator = `ALU_ADD; + // pass write data through ALU operand c + alu_op_c_mux_sel_o = `OP_C_REGB_OR_FWD; + // post-increment setup if (instr_rdata_i[6:0] == `OPCODE_STORE_POST) begin prepost_useincr_o = 1'b0; @@ -480,7 +479,7 @@ module riscv_decoder 3'b101, 3'b110, 3'b111: begin // MAC with subword selection - vector_mode_o = `VEC_MODE216; + vector_mode_o = 1'b1; mult_sel_subword_o = instr_rdata_i[13:12]; mult_signed_mode_o = instr_rdata_i[31:30]; @@ -516,18 +515,18 @@ module riscv_decoder // TODO: Handle in controller end - 32'h00_10_00_73: // EBREAK + 32'h00_10_00_73: // ebreak begin // debugger trap trap_insn = 1'b1; end - 32'h10_00_00_73: // ERET + 32'h10_00_00_73: // eret begin eret_insn = 1'b1; end - 32'h10_20_00_73: // WFI + 32'h10_20_00_73: // wfi begin // flush pipeline pipe_flush = 1'b1; @@ -590,13 +589,13 @@ module riscv_decoder hwloop_end_mux_sel_o = 1'b0; // jump target end 3'b010: begin - // lp.count initialize counter from rs1 + // lp.count: initialize counter from rs1 hwloop_we[2] = 1'b1; hwloop_cnt_mux_sel_o = 1'b1; rega_used_o = 1'b1; end 3'b011: begin - // lp.counti initialize counter from I-type immediate + // lp.counti: initialize counter from I-type immediate hwloop_we[2] = 1'b1; hwloop_cnt_mux_sel_o = 1'b0; end @@ -609,16 +608,6 @@ module riscv_decoder hwloop_cnt_mux_sel_o = 1'b1; rega_used_o = 1'b1; end - 3'b101: begin - // lp.setupi: initialize counter from I-type immediate, set start - // address to next instruction and end address to PC + shifted - // z-type immediate - hwloop_we = 3'b111; - hwloop_start_mux_sel_o = 1'b1; - hwloop_end_mux_sel_o = 1'b1; - hwloop_cnt_mux_sel_o = 1'b0; - illegal_insn_o = 1'b1; // TODO: PC + z-imm currently not supported - end default: begin illegal_insn_o = 1'b1; end diff --git a/ex_stage.sv b/ex_stage.sv index b6a4ff8d..7cf43855 100644 --- a/ex_stage.sv +++ b/ex_stage.sv @@ -25,7 +25,6 @@ // Revision v0.1 - File Created // // // // // -// // //////////////////////////////////////////////////////////////////////////////// `include "defines.sv" @@ -33,62 +32,59 @@ module riscv_ex_stage ( - input logic clk, - input logic rst_n, + input logic clk, + input logic rst_n, - // ALU signals from ID stage - input logic [`ALU_OP_WIDTH-1:0] alu_operator_i, - input logic [31:0] alu_operand_a_i, - input logic [31:0] alu_operand_b_i, - input logic [31:0] alu_operand_c_i, + // ALU signals from ID stage + input logic [`ALU_OP_WIDTH-1:0] alu_operator_i, + input logic [31:0] alu_operand_a_i, + input logic [31:0] alu_operand_b_i, + input logic [31:0] alu_operand_c_i, - input logic [1:0] vector_mode_i, - input logic [1:0] alu_cmp_mode_i, - input logic [1:0] alu_vec_ext_i, + input logic vector_mode_i, - // Multiplier signals - input logic mult_en_i, - input logic [1:0] mult_sel_subword_i, - input logic [1:0] mult_signed_mode_i, - input logic mult_mac_en_i, + // Multiplier signals + input logic mult_en_i, + input logic [1:0] mult_sel_subword_i, + input logic [1:0] mult_signed_mode_i, + input logic mult_mac_en_i, - // input from ID stage - input logic [4:0] regfile_alu_waddr_i, - input logic regfile_alu_we_i, + // input from ID stage + input logic [4:0] regfile_alu_waddr_i, + input logic regfile_alu_we_i, - // directly passed through to WB stage, not used in EX - input logic regfile_we_i, - input logic [4:0] regfile_waddr_i, + // directly passed through to WB stage, not used in EX + input logic regfile_we_i, + input logic [4:0] regfile_waddr_i, - // CSR access - input logic csr_access_i, - input logic [31:0] csr_rdata_i, + // CSR access + input logic csr_access_i, + input logic [31:0] csr_rdata_i, - // Output of EX stage pipeline - output logic [4:0] regfile_waddr_wb_o, - output logic regfile_we_wb_o, + // Output of EX stage pipeline + output logic [4:0] regfile_waddr_wb_o, + output logic regfile_we_wb_o, - // Forwarding ports : to ID stage - output logic [4:0] regfile_alu_waddr_fw_o, - output logic regfile_alu_we_fw_o, - output logic [31:0] regfile_alu_wdata_fw_o, // forward to RF and ID/EX pipe, ALU & MUL + // Forwarding ports : to ID stage + output logic [4:0] regfile_alu_waddr_fw_o, + output logic regfile_alu_we_fw_o, + output logic [31:0] regfile_alu_wdata_fw_o, // forward to RF and ID/EX pipe, ALU & MUL - // To IF: Jump and branch target and decision - output logic [31:0] jump_target_o, - output logic branch_decision_o, + // To IF: Jump and branch target and decision + output logic [31:0] jump_target_o, + output logic branch_decision_o, - // Stall Control - input logic lsu_ready_ex_i, // EX part of LSU is done + // Stall Control + input logic lsu_ready_ex_i, // EX part of LSU is done - output logic ex_ready_o, // EX stage ready for new data - output logic ex_valid_o, // EX stage gets new data - input logic wb_ready_i // WB stage ready for new data + output logic ex_ready_o, // EX stage ready for new data + output logic ex_valid_o, // EX stage gets new data + input logic wb_ready_i // WB stage ready for new data ); - // Internal output of the LU logic [31:0] alu_result; - logic alu_flag; + logic alu_cmp_result; logic [31:0] mult_result; @@ -96,6 +92,8 @@ module riscv_ex_stage assign regfile_alu_we_fw_o = regfile_alu_we_i; assign regfile_alu_waddr_fw_o = regfile_alu_waddr_i; + + // EX stage result mux (ALU, MAC unit, CSR) always_comb begin regfile_alu_wdata_fw_o = alu_result; @@ -107,8 +105,9 @@ module riscv_ex_stage regfile_alu_wdata_fw_o = csr_rdata_i; end - // Branch is taken when result[0] == 1'b1 - assign branch_decision_o = alu_flag; + + // branch handling + assign branch_decision_o = alu_cmp_result; assign jump_target_o = alu_operand_c_i; @@ -120,18 +119,15 @@ module riscv_ex_stage // /_/ \_\_____\___/ // // // //////////////////////////// + riscv_alu alu_i ( - .operator_i ( alu_operator_i ), - .operand_a_i ( alu_operand_a_i ), - .operand_b_i ( alu_operand_b_i ), + .operator_i ( alu_operator_i ), + .operand_a_i ( alu_operand_a_i ), + .operand_b_i ( alu_operand_b_i ), - .vector_mode_i ( vector_mode_i ), - .cmp_mode_i ( alu_cmp_mode_i ), - .vec_ext_i ( alu_vec_ext_i ), - - .result_o ( alu_result ), - .flag_o ( alu_flag ) + .result_o ( alu_result ), + .comparison_result_o ( alu_cmp_result ) ); @@ -143,6 +139,7 @@ module riscv_ex_stage // |_| |_|\___/|_____|_| |___|_| |_____|___|_____|_| \_\ // // // //////////////////////////////////////////////////////////////// + riscv_mult mult_i ( .vector_mode_i ( vector_mode_i ), @@ -165,19 +162,19 @@ module riscv_ex_stage begin : EX_WB_Pipeline_Register if (rst_n == 1'b0) begin - regfile_waddr_wb_o <= 5'b0_0000; - regfile_we_wb_o <= 1'b0; + regfile_waddr_wb_o <= 5'b0_0000; + regfile_we_wb_o <= 1'b0; end else begin if (ex_valid_o) // wb_ready_i is implied begin - regfile_we_wb_o <= regfile_we_i; - regfile_waddr_wb_o <= regfile_waddr_i; + regfile_we_wb_o <= regfile_we_i; + regfile_waddr_wb_o <= regfile_waddr_i; end else if (wb_ready_i) begin // we are ready for a new instruction, but there is none available, // so we just flush the current one out of the pipe - regfile_we_wb_o <= 1'b0; + regfile_we_wb_o <= 1'b0; end end end diff --git a/id_stage.sv b/id_stage.sv index de68ee0c..13def688 100644 --- a/id_stage.sv +++ b/id_stage.sv @@ -78,7 +78,6 @@ module riscv_id_stage input logic wb_valid_i, // WB stage is done // To the Pipeline ID/EX - output logic [31:0] regfile_rb_data_ex_o, output logic [31:0] alu_operand_a_ex_o, output logic [31:0] alu_operand_b_ex_o, output logic [31:0] alu_operand_c_ex_o, @@ -92,9 +91,7 @@ module riscv_id_stage // ALU output logic [`ALU_OP_WIDTH-1:0] alu_operator_ex_o, - output logic [1:0] vector_mode_ex_o, - output logic [1:0] alu_cmp_mode_ex_o, - output logic [1:0] alu_vec_ext_ex_o, + output logic vector_mode_ex_o, // MUL output logic mult_en_ex_o, @@ -219,15 +216,11 @@ module riscv_id_stage logic [`ALU_OP_WIDTH-1:0] alu_operator; logic [1:0] alu_op_a_mux_sel; logic [1:0] alu_op_b_mux_sel; - logic alu_op_c_mux_sel; - logic scalar_replication; + logic [1:0] alu_op_c_mux_sel; - logic [1:0] vector_mode; - logic [1:0] alu_cmp_mode; - logic [1:0] alu_vec_ext; + logic vector_mode; logic [2:0] immediate_mux_sel; - logic [1:0] jump_target_mux_sel; // Multiplier Control @@ -278,13 +271,11 @@ module riscv_id_stage logic [1:0] operand_c_fw_mux_sel; logic [31:0] operand_a_fw_id; logic [31:0] operand_b_fw_id; + logic [31:0] operand_c_fw_id; logic [31:0] alu_operand_a; logic [31:0] alu_operand_b; logic [31:0] alu_operand_c; - logic [31:0] operand_b; // before going through the scalar replication mux - logic [31:0] operand_b_vec; // scalar replication of operand_b for 8 and 16 bit - logic [31:0] operand_c; assign instr = instr_rdata_i; @@ -307,9 +298,6 @@ module riscv_id_stage // destination registers assign regfile_waddr_id = instr[`REG_D]; - //assign alu_vec_ext = instr[9:8]; TODO - assign alu_vec_ext = '0; - // Second Register Write Adress Selection // Used for prepost load/store and multiplier assign regfile_alu_waddr_id = regfile_alu_waddr_mux_sel ? @@ -423,7 +411,6 @@ module riscv_id_stage always_comb begin : immediate_mux unique case (immediate_mux_sel) - //`IMM_VEC: immediate_b = immediate_vec_id; `IMM_I: immediate_b = imm_i_type; `IMM_S: immediate_b = imm_s_type; `IMM_U: immediate_b = imm_u_type; @@ -436,20 +423,13 @@ module riscv_id_stage always_comb begin : alu_operand_b_mux case (alu_op_b_mux_sel) - `OP_B_REGB_OR_FWD: operand_b = operand_b_fw_id; - `OP_B_REGC_OR_FWD: operand_b = alu_operand_c; - `OP_B_IMM: operand_b = immediate_b; - default: operand_b = operand_b_fw_id; + `OP_B_REGB_OR_FWD: alu_operand_b = operand_b_fw_id; + `OP_B_REGC_OR_FWD: alu_operand_b = operand_c_fw_id; + `OP_B_IMM: alu_operand_b = immediate_b; + default: alu_operand_b = operand_b_fw_id; endcase // case (alu_op_b_mux_sel) end - // scalar replication for operand B - assign operand_b_vec = (vector_mode == `VEC_MODE8) ? {4{operand_b[7:0]}} : {2{operand_b[15:0]}}; - - // choose normal or scalar replicated version of operand b - assign alu_operand_b = (scalar_replication == 1'b1) ? operand_b_vec : operand_b; - - // Operand b forwarding mux always_comb begin : operand_b_fw_mux @@ -475,8 +455,10 @@ module riscv_id_stage always_comb begin : alu_operand_c_mux case (alu_op_c_mux_sel) - `OP_C_JT: operand_c = jump_target; - default: operand_c = regfile_data_rc_id; + `OP_C_REGC_OR_FWD: alu_operand_c = operand_c_fw_id; + `OP_C_REGB_OR_FWD: alu_operand_c = operand_b_fw_id; + `OP_C_JT: alu_operand_c = jump_target; + default: alu_operand_c = operand_c_fw_id; endcase // case (alu_op_c_mux_sel) end @@ -484,11 +466,11 @@ module riscv_id_stage always_comb begin : operand_c_fw_mux case (operand_c_fw_mux_sel) - `SEL_FW_EX: alu_operand_c = regfile_alu_wdata_fw_i; - `SEL_FW_WB: alu_operand_c = regfile_wdata_wb_i; - `SEL_REGFILE: alu_operand_c = operand_c; - default: alu_operand_c = operand_c; - endcase; // case (operand_b_fw_mux_sel) + `SEL_FW_EX: operand_c_fw_id = regfile_alu_wdata_fw_i; + `SEL_FW_WB: operand_c_fw_id = regfile_wdata_wb_i; + `SEL_REGFILE: operand_c_fw_id = regfile_data_rc_id; + default: operand_c_fw_id = regfile_data_rc_id; + endcase; // case (operand_c_fw_mux_sel) end @@ -555,7 +537,6 @@ module riscv_id_stage .regb_used_o ( regb_used_dec ), .regc_used_o ( regc_used_dec ), - // from IF/ID pipeline .instr_rdata_i ( instr ), .illegal_c_insn_i ( illegal_c_insn_i ), @@ -568,8 +549,6 @@ module riscv_id_stage .immediate_mux_sel_o ( immediate_mux_sel ), .vector_mode_o ( vector_mode ), - .scalar_replication_o ( scalar_replication ), - .alu_cmp_mode_o ( alu_cmp_mode ), // MUL signals .mult_en_o ( mult_en ), @@ -615,6 +594,7 @@ module riscv_id_stage // \____\___/|_| \_| |_| |_| \_\\___/|_____|_____|_____|_| \_\ // // // //////////////////////////////////////////////////////////////////// + riscv_controller controller_i ( .clk ( clk ), @@ -830,16 +810,12 @@ module riscv_id_stage begin : ID_EX_PIPE_REGISTERS if (rst_n == 1'b0) begin - regfile_rb_data_ex_o <= 32'h0000_0000; - alu_operator_ex_o <= `ALU_NOP; alu_operand_a_ex_o <= 32'h0000_0000; alu_operand_b_ex_o <= 32'h0000_0000; alu_operand_c_ex_o <= 32'h0000_0000; - vector_mode_ex_o <= `VEC_MODE32; - alu_cmp_mode_ex_o <= `ALU_CMP_FULL; - alu_vec_ext_ex_o <= 2'h0; + vector_mode_ex_o <= '0; mult_en_ex_o <= 1'b0; mult_sel_subword_ex_o <= 2'b0; @@ -890,23 +866,18 @@ module riscv_id_stage else if (~data_misaligned_i) begin if (id_valid_o) begin // unstall the whole pipeline - regfile_rb_data_ex_o <= operand_b_fw_id; - alu_operator_ex_o <= alu_operator; alu_operand_a_ex_o <= alu_operand_a; alu_operand_b_ex_o <= alu_operand_b; alu_operand_c_ex_o <= alu_operand_c; vector_mode_ex_o <= vector_mode; - alu_cmp_mode_ex_o <= alu_cmp_mode; - alu_vec_ext_ex_o <= alu_vec_ext; mult_en_ex_o <= mult_en; mult_sel_subword_ex_o <= mult_sel_subword; mult_signed_mode_ex_o <= mult_signed_mode; mult_mac_en_ex_o <= mult_mac_en; - regfile_waddr_ex_o <= regfile_waddr_id; regfile_we_ex_o <= regfile_we_id; diff --git a/include/defines.sv b/include/defines.sv index d8ac9e68..2ec59260 100644 --- a/include/defines.sv +++ b/include/defines.sv @@ -29,6 +29,8 @@ `ifndef _CORE_DEFINES `define _CORE_DEFINES +`define TRACE_EXECUTION + //////////////////////////////////////////////// // ___ ____ _ // @@ -74,16 +76,6 @@ `define INSTR_BGE { 17'b?, 3'b101, 5'b?, `OPCODE_BRANCH } `define INSTR_BLTU { 17'b?, 3'b110, 5'b?, `OPCODE_BRANCH } `define INSTR_BGEU { 17'b?, 3'b111, 5'b?, `OPCODE_BRANCH } -// LOAD -`define INSTR_LB { 17'b?, 3'b000, 5'b?, `OPCODE_LOAD } -`define INSTR_LH { 17'b?, 3'b001, 5'b?, `OPCODE_LOAD } -`define INSTR_LW { 17'b?, 3'b010, 5'b?, `OPCODE_LOAD } -`define INSTR_LBU { 17'b?, 3'b100, 5'b?, `OPCODE_LOAD } -`define INSTR_LHU { 17'b?, 3'b101, 5'b?, `OPCODE_LOAD } -// STORE -`define INSTR_SB { 17'b?, 3'b000, 5'b?, `OPCODE_STORE } -`define INSTR_SH { 17'b?, 3'b001, 5'b?, `OPCODE_STORE } -`define INSTR_SW { 17'b?, 3'b010, 5'b?, `OPCODE_STORE } // OPIMM `define INSTR_ADDI { 17'b?, 3'b000, 5'b?, `OPCODE_OPIMM } `define INSTR_SLTI { 17'b?, 3'b010, 5'b?, `OPCODE_OPIMM } @@ -119,12 +111,6 @@ `define INSTR_EBREAK { 12'b000000000001, 13'b0, `OPCODE_SYSTEM } `define INSTR_ERET { 12'b000100000000, 13'b0, `OPCODE_SYSTEM } `define INSTR_WFI { 12'b000100000010, 13'b0, `OPCODE_SYSTEM } -`define INSTR_RDCYCLE { 5'b11000, 5'b0, 2'b00, 5'b0, 3'b010, 5'b?, `OPCODE_SYSTEM } -`define INSTR_RDCYCLEH { 5'b11001, 5'b0, 2'b00, 5'b0, 3'b010, 5'b?, `OPCODE_SYSTEM } -`define INSTR_RDTIME { 5'b11000, 5'b0, 2'b01, 5'b0, 3'b010, 5'b?, `OPCODE_SYSTEM } -`define INSTR_RDTIMEH { 5'b11001, 5'b0, 2'b01, 5'b0, 3'b010, 5'b?, `OPCODE_SYSTEM } -`define INSTR_RDINSTRET { 5'b11000, 5'b0, 2'b10, 5'b0, 3'b010, 5'b?, `OPCODE_SYSTEM } -`define INSTR_RDINSTRETH { 5'b11001, 5'b0, 2'b10, 5'b0, 3'b010, 5'b?, `OPCODE_SYSTEM } // RV32M `define INSTR_MUL { 7'b0000001, 10'b?, 3'b000, 5'b?, `OPCODE_OP } @@ -146,40 +132,6 @@ `define REG_D 11:07 -`ifndef SYNTHESIS -// synopsys translate_off -`define TRACE_EXECUTION - -function void prettyPrintInstruction(input [31:0] instr, input [31:0] pc); - string opcode; - begin - unique case (instr[6:0]) - `OPCODE_SYSTEM: opcode = "SYSTEM"; - `OPCODE_FENCE: opcode = "FENCE"; - `OPCODE_OP: opcode = "OP"; - `OPCODE_OPIMM: opcode = "OPIMM"; - `OPCODE_STORE: opcode = "STORE"; - `OPCODE_LOAD: opcode = "LOAD"; - `OPCODE_BRANCH: opcode = "BRANCH"; - `OPCODE_JALR: opcode = "JALR"; - `OPCODE_JAL: opcode = "JAL"; - `OPCODE_AUIPC: opcode = "AUIPC"; - `OPCODE_LUI: opcode = "LUI"; - default: opcode = "Unknown"; - endcase // unique case (instr[6:0]) - - $display("%t: %s Instruction 0x%h at 0x%h.", $time, opcode, instr[31:0], pc[31:0]); - $display("%t: | fct7 | rs2 | rs1 | | rd | opc. |", $time); - $display("%t: 0b %b %b %b %b %b %b", $time, instr[31:25], instr[`REG_S2], - instr[`REG_S1], instr[14:12], instr[`REG_D], instr[6:0]); - $display(); - end -endfunction // prettyPrintInstruction -// synopsys translate_on -`endif - - - ////////////////////////////////////////////////////////////////////////////// // _ _ _ _ ___ _ _ // // / \ | | | | | | / _ \ _ __ ___ _ __ __ _| |_(_) ___ _ __ ___ // @@ -191,35 +143,37 @@ endfunction // prettyPrintInstruction `define ALU_OP_WIDTH 6 -// Standard Operations +// No operation +`define ALU_NOP 6'b011111 + +// Standard arithmetic operations `define ALU_ADD 6'b000_000 `define ALU_SUB 6'b000_010 -`define ALU_AND 6'b000_011 -`define ALU_OR 6'b000_100 `define ALU_XOR 6'b000_101 +`define ALU_OR 6'b000_100 +`define ALU_AND 6'b000_011 -`define ALU_AVG 6'b000_110 -`define ALU_AVGU 6'b000_111 -// Shift Operations -`define ALU_SLL 6'b0010_00 -`define ALU_SRL 6'b0010_01 -`define ALU_SRA 6'b0010_10 -`define ALU_ROR 6'b0010_11 -// Set Lower Than Operations +// Set Lower Than operations `define ALU_SLTS 6'b0011_00 `define ALU_SLTU 6'b0011_01 `define ALU_SLETS 6'b0011_10 `define ALU_SLETU 6'b0011_11 -// Extension Operations + +// Shifts +`define ALU_SLL 6'b0010_00 +`define ALU_SRL 6'b0010_01 +`define ALU_SRA 6'b0010_10 +`define ALU_ROR 6'b0010_11 + +// Sign-/zero-extensions `define ALU_EXTHS 6'b010_000 `define ALU_EXTWS 6'b010_001 `define ALU_EXTBS 6'b010_010 `define ALU_EXTWZ 6'b010_011 `define ALU_EXTHZ 6'b010_100 `define ALU_EXTBZ 6'b010_110 -// No Operation -`define ALU_NOP 6'b011111 -// Comparison Operations + +// Comparisons `define ALU_EQ 6'b10_0000 `define ALU_NE 6'b10_0001 `define ALU_GTU 6'b10_0010 @@ -231,34 +185,24 @@ endfunction // prettyPrintInstruction `define ALU_LTS 6'b10_1100 `define ALU_LES 6'b10_1101 +// Min/max/avg +`define ALU_AVG 6'b000_110 +`define ALU_AVGU 6'b000_111 `define ALU_MIN 6'b10_1110 `define ALU_MINU 6'b11_1110 `define ALU_MAX 6'b10_1111 `define ALU_MAXU 6'b11_1111 +// Absolute value `define ALU_ABS 6'b11_1010 -`define ALU_INS 6'b11_1101 -`define ALU_EXT 6'b11_1100 - +// Bit counting `define ALU_CNT 6'b11_0000 `define ALU_FF1 6'b11_0010 `define ALU_FL1 6'b11_0011 `define ALU_CLB 6'b11_0001 -// Vector Mode -`define VEC_MODE32 2'b00 -`define VEC_MODE16 2'b10 -`define VEC_MODE8 2'b11 -`define VEC_MODE216 2'b01 - -// ALU comparison mode -`define ALU_CMP_FULL 2'b00 -`define ALU_CMP_ANY 2'b01 -`define ALU_CMP_ALL 2'b10 - - ///////////////////////////////////////////////////////// // ____ ____ ____ _ _ // // / ___/ ___| | _ \ ___ __ _(_)___| |_ ___ _ __ // @@ -281,9 +225,6 @@ endfunction // prettyPrintInstruction `define CSR_OP_CLEAR 2'b11 -// SPR for HWLoops -`define SP_GRP_HWLP 5'h0C - // SPR for debugger, not accessible by CPU `define SP_DVR0 16'h3000 `define SP_DCR0 16'h3008 @@ -328,8 +269,9 @@ endfunction // prettyPrintInstruction `define IMM_PCINCR 3'b011 // operand c selection -`define OP_C_REGC_OR_FWD 1'b0 -`define OP_C_JT 1'b1 +`define OP_C_REGC_OR_FWD 2'b00 +`define OP_C_REGB_OR_FWD 2'b01 +`define OP_C_JT 2'b10 // branch types `define BRANCH_NONE 2'b00 @@ -403,6 +345,4 @@ endfunction // prettyPrintInstruction `define DSR_INTE 1 -//`define BRANCH_PREDICTION - `endif diff --git a/mult.sv b/mult.sv index c912af60..75635a1a 100644 --- a/mult.sv +++ b/mult.sv @@ -24,44 +24,37 @@ // selection. There are no flags for multiplications anymore! // // // // // -// // -// // -// // //////////////////////////////////////////////////////////////////////////////// - `include "defines.sv" + module riscv_mult ( - input logic [1:0] vector_mode_i, - input logic [1:0] sel_subword_i, - input logic [1:0] signed_mode_i, - input logic mac_en_i, + input logic mac_en_i, + input logic vector_mode_i, + input logic [1:0] sel_subword_i, + input logic [1:0] signed_mode_i, - input logic [31:0] op_a_i, - input logic [31:0] op_b_i, - input logic [31:0] mac_i, + input logic [31:0] op_a_i, + input logic [31:0] op_b_i, + input logic [31:0] mac_i, - output logic [31:0] result_o + output logic [31:0] result_o ); - logic [31:0] result; - - logic [31:0] op_a_sel; - logic [31:0] op_b_sel; - logic [31:0] mac_int; + logic [31:0] op_a_sel; + logic [31:0] op_b_sel; + logic [31:0] mac_int; - assign mac_int = (mac_en_i == 1'b1) ? mac_i : 32'b0; - - // this block performs the subword selection and sign extensions + // perform subword selection and sign extensions always_comb begin op_a_sel = op_a_i; op_b_sel = op_b_i; - if(vector_mode_i == `VEC_MODE216) + if(vector_mode_i) begin if(sel_subword_i[1] == 1'b1) op_a_sel[15:0] = op_a_i[31:16]; @@ -78,32 +71,7 @@ module riscv_mult end end + assign mac_int = (mac_en_i == 1'b1) ? mac_i : 32'b0; + assign result_o = mac_int + op_a_sel * op_b_sel; - always_comb - begin - case(vector_mode_i) - `VEC_MODE16: - begin - result[15: 0] = mac_int[15: 0] + op_a_sel[15: 0] * op_b_sel[15: 0]; - result[31:16] = mac_int[31:16] + op_a_sel[31:16] * op_b_sel[31:16]; - end - - `VEC_MODE8: - begin - result[ 7: 0] = mac_int[ 7: 0] + op_a_sel[ 7: 0] * op_b_sel[ 7: 0]; - result[15: 8] = mac_int[15: 8] + op_a_sel[15: 8] * op_b_sel[15: 8]; - result[23:16] = mac_int[23:16] + op_a_sel[23:16] * op_b_sel[23:16]; - result[31:24] = mac_int[31:24] + op_a_sel[31:24] * op_b_sel[31:24]; - end - - default: // VEC_MODE32, VEC_MODE216 - begin - result[31: 0] = mac_int + op_a_sel * op_b_sel; - end - endcase; // case (vec_mode_i) - end - - assign result_o = result[31:0]; - -endmodule // mult - +endmodule diff --git a/riscv_core.sv b/riscv_core.sv index 5d301e22..3eecc609 100644 --- a/riscv_core.sv +++ b/riscv_core.sv @@ -61,8 +61,8 @@ module riscv_core input logic [31:0] data_rdata_i, // Interrupt inputs - input logic irq_i, // level-triggered IR line - input logic irq_nm_i, // level-triggered IR line for non-maskable IRQ + input logic irq_i, // level-triggered IR line + input logic irq_nm_i, // level-triggered IR line for non-maskable IRQ // Debug Interface input logic dbginf_stall_i, @@ -83,23 +83,22 @@ module riscv_core // IF/ID signals - logic [31:0] instr_rdata_id; // Instruction sampled inside IF stage - logic is_compressed_id; - logic illegal_c_insn_id; // Illegal compressed instruction sent to ID stage - logic [31:0] current_pc_if; // Current Program counter - logic [31:0] current_pc_id; // Current Program counter - logic pc_set; - logic [2:0] pc_mux_sel_id; // Mux selector for next PC - logic [1:0] exc_pc_mux_id; // Mux selector for exception PC + logic [31:0] instr_rdata_id; // Instruction sampled inside IF stage + logic is_compressed_id; + logic illegal_c_insn_id; // Illegal compressed instruction sent to ID stage + logic [31:0] current_pc_if; // Current Program counter + logic [31:0] current_pc_id; // Current Program counter + logic pc_set; + logic [2:0] pc_mux_sel_id; // Mux selector for next PC + logic [1:0] exc_pc_mux_id; // Mux selector for exception PC - logic branch_done; // Branch already done + logic branch_done; // Branch already done // ID performance counter signals - logic is_decoding; + logic is_decoding; - - logic useincr_addr_ex; // Active when post increment - logic data_misaligned; + logic useincr_addr_ex; // Active when post increment + logic data_misaligned; // Jump and branch target and decision (EX->IF) logic [31:0] jump_target_id, jump_target_ex; @@ -107,24 +106,16 @@ module riscv_core logic [1:0] jump_in_ex; logic branch_decision; - logic core_busy; logic if_busy; - // Register Data - logic [31:0] regfile_rb_data_ex; // from id stage to load/store unit and ex stage - - // ALU Control logic [`ALU_OP_WIDTH-1:0] alu_operator_ex; - logic [31:0] alu_operand_a_ex; - logic [31:0] alu_operand_b_ex; - logic [31:0] alu_operand_c_ex; - - logic [1:0] vector_mode_ex; - logic [1:0] alu_cmp_mode_ex; - logic [1:0] alu_vec_ext_ex; + logic [31:0] alu_operand_a_ex; + logic [31:0] alu_operand_b_ex; + logic [31:0] alu_operand_c_ex; + logic vector_mode_ex; // Multiplier Control logic mult_en_ex; @@ -253,7 +244,7 @@ module riscv_core .instr_rdata_i ( instr_rdata_i ), // outputs to ID stage - .instr_rdata_id_o ( instr_rdata_id ), // Output of IF Pipeline stage + .instr_rdata_id_o ( instr_rdata_id ), .is_compressed_id_o ( is_compressed_id ), .illegal_c_insn_id_o ( illegal_c_insn_id ), .current_pc_if_o ( current_pc_if ), // current pc in IF stage @@ -261,7 +252,7 @@ module riscv_core // control signals .pc_set_i ( pc_set ), - .exception_pc_reg_i ( epcr ), // Exception PC register + .exception_pc_reg_i ( epcr ), // exception return address .pc_mux_sel_i ( pc_mux_sel_id ), // sel for pc multiplexer .exc_pc_mux_i ( exc_pc_mux_id ), // selector for exception multiplexer @@ -345,7 +336,6 @@ module riscv_core .wb_valid_i ( wb_valid ), // From the Pipeline ID/EX - .regfile_rb_data_ex_o ( regfile_rb_data_ex ), .alu_operand_a_ex_o ( alu_operand_a_ex ), .alu_operand_b_ex_o ( alu_operand_b_ex ), .alu_operand_c_ex_o ( alu_operand_c_ex ), @@ -358,10 +348,7 @@ module riscv_core // ALU .alu_operator_ex_o ( alu_operator_ex ), - .vector_mode_ex_o ( vector_mode_ex ), // from ID to EX stage - .alu_cmp_mode_ex_o ( alu_cmp_mode_ex ), // from ID to EX stage - .alu_vec_ext_ex_o ( alu_vec_ext_ex ), // from ID to EX stage // MUL .mult_en_ex_o ( mult_en_ex ), // from ID to EX stage @@ -446,8 +433,6 @@ module riscv_core .alu_operand_c_i ( alu_operand_c_ex ), // from ID/EX pipe registers .vector_mode_i ( vector_mode_ex ), // from ID/EX pipe registers - .alu_cmp_mode_i ( alu_cmp_mode_ex ), // from ID/EX pipe registers - .alu_vec_ext_i ( alu_vec_ext_ex ), // from ID/EX pipe registers // Multipler .mult_en_i ( mult_en_ex ), @@ -496,46 +481,48 @@ module riscv_core // |_____\___/_/ \_\____/ |____/ |_| \___/|_| \_\_____| \___/|_| \_|___| |_| // // // //////////////////////////////////////////////////////////////////////////////////////// + riscv_load_store_unit load_store_unit_i ( - .clk ( clk ), - .rst_n ( rst_n ), + .clk ( clk ), + .rst_n ( rst_n ), // signal from ex stage - .data_we_ex_i ( data_we_ex ), - .data_type_ex_i ( data_type_ex ), - .data_wdata_ex_i ( regfile_rb_data_ex ), - .data_reg_offset_ex_i ( data_reg_offset_ex ), - .data_sign_ext_ex_i ( data_sign_ext_ex ), // sign extension + .data_we_ex_i ( data_we_ex ), + .data_type_ex_i ( data_type_ex ), + .data_wdata_ex_i ( alu_operand_c_ex ), + .data_reg_offset_ex_i ( data_reg_offset_ex ), + .data_sign_ext_ex_i ( data_sign_ext_ex ), // sign extension - .data_rdata_ex_o ( regfile_wdata ), - .data_req_ex_i ( data_req_ex ), - .operand_a_ex_i ( alu_operand_a_ex ), - .operand_b_ex_i ( alu_operand_b_ex ), - .addr_useincr_ex_i ( useincr_addr_ex ), + .data_rdata_ex_o ( regfile_wdata ), + .data_req_ex_i ( data_req_ex ), + .operand_a_ex_i ( alu_operand_a_ex ), + .operand_b_ex_i ( alu_operand_b_ex ), + .addr_useincr_ex_i ( useincr_addr_ex ), - .data_misaligned_ex_i ( data_misaligned_ex ), // from ID/EX pipeline - .data_misaligned_o ( data_misaligned ), + .data_misaligned_ex_i ( data_misaligned_ex ), // from ID/EX pipeline + .data_misaligned_o ( data_misaligned ), //output to data memory - .data_req_o ( data_req_o ), - .data_gnt_i ( data_gnt_i ), - .data_rvalid_i ( data_rvalid_i ), + .data_req_o ( data_req_o ), + .data_gnt_i ( data_gnt_i ), + .data_rvalid_i ( data_rvalid_i ), - .data_addr_o ( data_addr_o ), - .data_we_o ( data_we_o ), - .data_be_o ( data_be_o ), - .data_wdata_o ( data_wdata_o ), - .data_rdata_i ( data_rdata_i ), + .data_addr_o ( data_addr_o ), + .data_we_o ( data_we_o ), + .data_be_o ( data_be_o ), + .data_wdata_o ( data_wdata_o ), + .data_rdata_i ( data_rdata_i ), - .lsu_ready_ex_o ( lsu_ready_ex ), - .lsu_ready_wb_o ( lsu_ready_wb ), + .lsu_ready_ex_o ( lsu_ready_ex ), + .lsu_ready_wb_o ( lsu_ready_wb ), - .ex_valid_i ( ex_valid ) + .ex_valid_i ( ex_valid ) ); assign wb_valid = lsu_ready_wb; + ////////////////////////////////////// // ____ ____ ____ // // / ___/ ___|| _ \ ___ // @@ -545,6 +532,7 @@ module riscv_core // // // Control and Status Registers // ////////////////////////////////////// + riscv_cs_registers #( .N_EXT_PERF_COUNTERS ( N_EXT_PERF_COUNTERS ) @@ -606,6 +594,7 @@ module riscv_core // |____/|_____|____/ \___/ \____| \___/|_| \_|___| |_| // // // ///////////////////////////////////////////////////////////// + riscv_debug_unit debug_unit_i ( .clk ( clk ), @@ -730,10 +719,6 @@ module riscv_core `INSTR_BGE: printSBInstr("BGE"); `INSTR_BLTU: printSBInstr("BLTU"); `INSTR_BGEU: printSBInstr("BGEU"); - // STORE - `INSTR_SB: printSInstr("SB"); - `INSTR_SH: printSInstr("SH"); - `INSTR_SW: printSInstr("SW"); // OPIMM `INSTR_ADDI: printIInstr("ADDI"); `INSTR_SLTI: printIInstr("SLTI"); @@ -770,12 +755,6 @@ module riscv_core `INSTR_EBREAK: printMnemonic("EBREAK"); `INSTR_ERET: printMnemonic("ERET"); `INSTR_WFI: printMnemonic("WFI"); - `INSTR_RDCYCLE: printRDInstr("RDCYCLE"); - `INSTR_RDCYCLEH: printRDInstr("RDCYCLEH"); - `INSTR_RDTIME: printRDInstr("RDTIME"); - `INSTR_RDTIMEH: printRDInstr("RDTIMEH"); - `INSTR_RDINSTRET: printRDInstr("RDINSTRET"); - `INSTR_RDINSTRETH: printRDInstr("RDINSTRETH"); // RV32M `INSTR_MUL: printRInstr("MUL"); `INSTR_MULH: printRInstr("MULH"); @@ -792,6 +771,7 @@ module riscv_core {25'b?, `OPCODE_LOAD_POST}: printLoadInstr(); {25'b?, `OPCODE_STORE}: printStoreInstr(); {25'b?, `OPCODE_STORE_POST}: printStoreInstr(); + {25'b?, `OPCODE_HWLOOP}: printHwloopInstr(); default: printMnemonic("INVALID"); endcase // unique case (instr) @@ -839,15 +819,6 @@ module riscv_core end endfunction // printIInstr - function void printSInstr(input string mnemonic); - begin - riscv_core.mnemonic = mnemonic; - imm = id_stage_i.imm_s_type; - $fdisplay(f, "%7s\tx%0d (0x%h), x%0d (0x%h), 0x%0h (imm) (-> 0x%h)", mnemonic, - rs1, rs1_value, rs2, rs2_value, imm, imm+rs1_value); - end - endfunction // printSInstr - function void printSBInstr(input string mnemonic); begin riscv_core.mnemonic = mnemonic; @@ -865,13 +836,6 @@ module riscv_core end endfunction // printUJInstr - function void printRDInstr(input string mnemonic); - begin - riscv_core.mnemonic = mnemonic; - $fdisplay(f, "%7s\tx%0d", mnemonic, rd); - end - endfunction // printRDInstr - function void printCSRInstr(input string mnemonic); logic [11:0] csr; begin @@ -978,11 +942,42 @@ module riscv_core end end endfunction // printSInstr + + function void printHwloopInstr(); + string mnemonic; + begin + // set mnemonic + case (instr[14:12]) + 3'b000: mnemonic = "LSTARTI"; + 3'b001: mnemonic = "LENDI"; + 3'b010: mnemonic = "LCOUNT"; + 3'b011: mnemonic = "LCOUNTI"; + 3'b100: mnemonic = "LSETUP"; + 3'b111: begin + printMnemonic("INVALID"); + return; + end + endcase + riscv_core.mnemonic = mnemonic; + + // decode and print instruction + imm = id_stage_i.imm_i_type; + case (instr[14:12]) + // lp.starti and lp.endi + 3'b000, + 3'b001: $fdisplay(f, "%7s\tx%0d, 0x%h (-> 0x%h)", mnemonic, rd, imm, pc+imm); + // lp.count + 3'b010: $fdisplay(f, "%7s\tx%0d, x%0d (0x%h)", mnemonic, rd, rs1, rs1_value); + // lp.counti + 3'b011: $fdisplay(f, "%7s\tx%0d, 0x%h", mnemonic, rd, imm); + // lp.setup + 3'b100: $fdisplay(f, "%7s\tx%0d, x%0d (0x%h), 0x%h (-> 0x%h)", mnemonic, + rd, rs1, rs1_value, imm, pc+imm); + endcase + end + endfunction `endif // TRACE_EXECUTION // synopsys translate_on `endif - -/////////////////// -endmodule // cpu // -/////////////////// +endmodule