Merge branch 'remove_vect'

This commit removes the vectorial ALU and updates RVC to the newest proposal.
This commit is contained in:
Sven Stucki 2015-10-18 19:57:42 +02:00
commit b957c6f682
9 changed files with 436 additions and 768 deletions

449
alu.sv
View file

@ -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

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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

66
mult.sv
View file

@ -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

View file

@ -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