mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-20 03:57:25 -04:00
[bitmanip] Add ZBT Instruction Group
This commits implements the Bit Manipulateion Extension ZBT instruction group: cmix, cmov, fsr[i] and fsl. Those are instructions depend on three ALU operands. Completeion of these instructions takes 2 clock cycles. Additionally, the rotation shifts rol and ror are made multicycle instructions. All multicycle instructions take exactly two cycles to complete. Architectural additions: * Multicycle Stage Register in ID stage. multicycle_op_stage_reg * Decoder generates alu_multicycle signal, to stall pipeline * For all ternary instructions: 1. cycle: connect alu operands a and b to rs1 and rs2 respectively 2. cycle: connect operands a and be to rs3 and rs2 respectively * Reduce the physical size of the shifter from 64 bit to 63 bit: 32-bit operand + 1 bit for arithmetic / one-shift * Make rotation shifts multicycle instructions. Instruction Details: * cmov: 1. store operand a (rs1) in stage reg. 2. return stage reg output (rs2) or rs3. if rs2 != 0 the output (rs1) is already known in the first cycle. -> variable latency implementation is possible. * cmix: 1. store rs1 & rs2 in stage reg 2. return stage_reg_q | (rs2 & ~rs3) reusing bwlogic from zbb * rol/ror: (here: ror) shift_amt = rs2 & 31; shift_amt_compl = (32 - shift_amt) & 31 1. store (rs1 >> shift_amt) in stage reg 2. return (rs1 << shift_amt_compl) | stage_reg_q * fsl/fsr: For funnel shifts, the order of applying the shift amount or its complement is determined by bit [5] of shift_amt. Pseudocode for fsr: shift_amt = rs2 & 63 shift_amt_compl = (32 - shift_amt[4:0]) 1. if (shift_amt >= 33): store (rs1 >> shift_amt_compl[4:0]) in stage reg else if (shift_amt <0 && shift_amt <= 31): store (rs1 << shift_amt[4:0]) in stage reg else if (shift_amt == 32 || shift_amt == 0): store rs1 in stage reg 2. if (shift_amt >= 33): return stage_reg_q | (rs3 << shift_amt[4:0]) else if (shift_amt <0 && shift_amt <= 31): return stage_reg_q | (rs3 >> shift_amt_compl[4:0]) else if (shift_amt == 32): return rs3 else if (shift_amt == 0): return rs1 Signed-off-by: ganoam <gnoam@live.com>
This commit is contained in:
parent
db6f8f050e
commit
4cb77b8121
12 changed files with 679 additions and 310 deletions
|
@ -64,9 +64,9 @@ Other blocks use the ALU for the following tasks:
|
|||
* It computes memory addresses for loads and stores with a Reg + Imm calculation
|
||||
* The LSU uses it to increment addresses when performing two accesses to handle an unaligned access
|
||||
|
||||
Support for the RISC-V Bitmanipulation Extension is enabled via the parameter ``RV32B``.
|
||||
Support for the RISC-V Bitmanipulation Extension (Document Version 0.92, November 8, 2019) is enabled via the parameter ``RV32B``.
|
||||
This feature is *EXPERIMENTAL* and the details of its impact are not yet documented here.
|
||||
Currently only the Zbb base extension is implemented.
|
||||
Currently the Zbb and Zbt sub-extensions are implemented.
|
||||
All instructions are carried out in a single clock cycle.
|
||||
|
||||
.. _mult-div:
|
||||
|
|
|
@ -28,18 +28,18 @@ lint_off -rule DECLFILENAME -file "*/rtl/ibex_register_file_ff.sv"
|
|||
lint_off -rule DECLFILENAME -file "*/rtl/ibex_register_file_latch.sv"
|
||||
lint_off -rule DECLFILENAME -file "*/rtl/ibex_register_file_fpga.sv"
|
||||
|
||||
// Bits of signal are not used: shift_amt_compl[5]
|
||||
// cleaner to write all bits even if not all are used
|
||||
lint_off -rule UNUSED -file "*/rtl/ibex_alu.sv" -match "*'shift_amt_compl'[5]*"
|
||||
|
||||
// Bits of signal are not used: shift_result_ext[32]
|
||||
// cleaner to write all bits even if not all are used
|
||||
lint_off -rule UNUSED -file "*/rtl/ibex_alu.sv" -match "*'shift_result_ext'[32]*"
|
||||
|
||||
// Bits of signal are not used: fetch_addr_n[0]
|
||||
// cleaner to write all bits even if not all are used
|
||||
lint_off -rule UNUSED -file "*/rtl/ibex_if_stage.sv" -match "*'fetch_addr_n'[0]*"
|
||||
|
||||
// Signal is not used, if RVB == 0: shift_result_ext_rvb
|
||||
// Needed if RVB == 1.
|
||||
lint_off -rule UNUSED -file "*/rtl/ibex_alu.sv" -match "*'shift_result_ext_rvb'*"
|
||||
|
||||
// Signal is not used, if RVB == 1: shift_result_ext
|
||||
// Needed if RVB == 0.
|
||||
lint_off -rule UNUSED -file "*/rtl/ibex_alu.sv" -match "*'shift_result_ext'*"
|
||||
|
||||
// Bits of signal are not used: alu_adder_ext_i[0]
|
||||
// Bottom bit is round, not needed
|
||||
lint_off -rule UNUSED -file "*/rtl/ibex_multdiv_fast.sv" -match "*'alu_adder_ext_i'[0]*"
|
||||
|
@ -49,7 +49,6 @@ lint_off -rule UNUSED -file "*/rtl/ibex_multdiv_fast.sv" -match "*'alu_adder_ext
|
|||
lint_off -rule UNUSED -file "*/rtl/ibex_multdiv_fast.sv" -match "*mac_res_ext*"
|
||||
lint_off -rule UNUSED -file "*/rtl/ibex_multdiv_fast.sv" -match "*mult1_res*"
|
||||
|
||||
|
||||
// Bits of signal are not used: res_adder_h[32]
|
||||
// cleaner to write all bits even if not all are used
|
||||
lint_off -rule UNUSED -file "*/rtl/ibex_multdiv_fast.sv" -match "*'res_adder_h'[32]*"
|
||||
|
|
230
rtl/ibex_alu.sv
230
rtl/ibex_alu.sv
|
@ -13,11 +13,17 @@ module ibex_alu #(
|
|||
input logic [31:0] operand_a_i,
|
||||
input logic [31:0] operand_b_i,
|
||||
|
||||
input logic instr_first_cycle_i,
|
||||
|
||||
input logic [32:0] multdiv_operand_a_i,
|
||||
input logic [32:0] multdiv_operand_b_i,
|
||||
|
||||
input logic multdiv_sel_i,
|
||||
|
||||
input logic [31:0] imd_val_q_i,
|
||||
output logic [31:0] imd_val_d_o,
|
||||
output logic imd_val_we_o,
|
||||
|
||||
output logic [31:0] adder_result_o,
|
||||
output logic [33:0] adder_result_ext_o,
|
||||
|
||||
|
@ -57,12 +63,7 @@ module ibex_alu #(
|
|||
|
||||
// MinMax OPs (RV32B Ops)
|
||||
ALU_MIN, ALU_MINU,
|
||||
ALU_MAX, ALU_MAXU,
|
||||
|
||||
// Logic-with-negate OPs (RV32B Ops)
|
||||
ALU_XNOR,
|
||||
ALU_ORN,
|
||||
ALU_ANDN: adder_op_b_negate = 1'b1;
|
||||
ALU_MAX, ALU_MAXU: adder_op_b_negate = 1'b1;
|
||||
|
||||
default:;
|
||||
endcase
|
||||
|
@ -72,8 +73,14 @@ module ibex_alu #(
|
|||
assign adder_in_a = multdiv_sel_i ? multdiv_operand_a_i : {operand_a_i,1'b1};
|
||||
|
||||
// prepare operand b
|
||||
assign operand_b_neg = {operand_b_i,1'b0} ^ {33{adder_op_b_negate}};
|
||||
assign adder_in_b = multdiv_sel_i ? multdiv_operand_b_i : operand_b_neg;
|
||||
assign operand_b_neg = {operand_b_i,1'b0} ^ {33{1'b1}};
|
||||
always_comb begin
|
||||
unique case(1'b1)
|
||||
multdiv_sel_i: adder_in_b = multdiv_operand_b_i;
|
||||
adder_op_b_negate: adder_in_b = operand_b_neg;
|
||||
default : adder_in_b = {operand_b_i, 1'b0};
|
||||
endcase
|
||||
end
|
||||
|
||||
// actual adder
|
||||
assign adder_result_ext_o = $unsigned(adder_in_a) + $unsigned(adder_in_b);
|
||||
|
@ -86,26 +93,85 @@ module ibex_alu #(
|
|||
// Shift //
|
||||
///////////
|
||||
|
||||
// The shifter structure consists of a 33-bit shifter: 32-bit operand + 1 bit extension for
|
||||
// arithmetic shifts and one-shift support.
|
||||
// Rotations and funnel shifts are implemented as multi-cycle instructions.
|
||||
// For funnel shifs, operand_a_i is tied to rs1 in the first cycle and rs3 in the
|
||||
// second cycle. operand_b_i is always tied to rs2.
|
||||
//
|
||||
// Rotation pseudocode:
|
||||
// shift_amt = rs2 & 31;
|
||||
// multicycle_result = (rs1 >> shift_amt) | (rs1 << (32 - shift_amt));
|
||||
// ^-- cycle 0 -----^ ^-- cycle 1 --------------^
|
||||
//
|
||||
// For funnel shifts, the order of applying the shift amount or its complement is determined by
|
||||
// bit [5] of shift_amt.
|
||||
// Funnel shift Pseudocode: (fsl)
|
||||
// shift_amt = rs2 & 63;
|
||||
// shift_amt_compl = 32 - shift_amt[4:0]
|
||||
// if (shift_amt >=33):
|
||||
// multicycle_result = (rs1 >> shift_amt_cmpl[4:0]) | (rs3 << shift_amt[4:0]);
|
||||
// ^-- cycle 0 ---------------^ ^-- cycle 1 ------------^
|
||||
// else if (shift_amt <= 31 && shift_amt > 0):
|
||||
// multicycle_result = (rs1 << shift_amt[4:0]) | (rs3 >> shift_amt_compl[4:0]);
|
||||
// ^-- cycle 0 ----------^ ^-- cycle 1 -------------------^
|
||||
// For shift_amt == 0, 32, both shift_amt[4:0] and shift_amt_compl[4:0] == '0.
|
||||
// these cases need to be handled separately outside the shifting structure:
|
||||
// else if (shift_amt == 32):
|
||||
// multicycle_result = rs3
|
||||
// else if (shift_amt == 0):
|
||||
// multicycle_result = rs1.
|
||||
|
||||
logic shift_left;
|
||||
logic shift_ones;
|
||||
logic shift_arith;
|
||||
logic shift_rot;
|
||||
logic shift_funnel;
|
||||
logic shift_none;
|
||||
logic shift_op_rev;
|
||||
logic shift_op_rev8;
|
||||
logic shift_op_orc_b;
|
||||
logic [4:0] shift_amt;
|
||||
logic [5:0] shift_amt;
|
||||
logic [5:0] shift_amt_compl; // complementary shift amount (32 - shift_amt)
|
||||
logic shift_multicycle;
|
||||
|
||||
assign shift_amt = operand_b_i[4:0];
|
||||
// bit shift_amt[5]: word swap bit: only considered for FSL/FSR.
|
||||
// if set, reverse operations in first and second cycle.
|
||||
assign shift_amt[5] = operand_b_i[5] && shift_funnel;
|
||||
assign shift_amt_compl = 32 - operand_b_i[4:0];
|
||||
|
||||
assign shift_amt[4:0] = instr_first_cycle_i ?
|
||||
(operand_b_i[5] && shift_funnel ? shift_amt_compl[4:0] : operand_b_i[4:0]) :
|
||||
(operand_b_i[5] && shift_funnel ? operand_b_i[4:0] : shift_amt_compl[4:0]);
|
||||
|
||||
// left shift if this is:
|
||||
// * a standard left shift (slo, sll)
|
||||
// * a rol in the first cycle
|
||||
// * a ror in the second cycle
|
||||
// * fsl: without word-swap bit: first cycle, else: second cycle
|
||||
// * fsr: without word-swap bit: second cycle, else: first cycle
|
||||
always_comb begin
|
||||
unique case (operator_i)
|
||||
ALU_SLL: shift_left = 1'b1;
|
||||
ALU_SLO: shift_left = RV32B ? 1'b1 : 1'b0;
|
||||
ALU_ROL: shift_left = RV32B ? instr_first_cycle_i : 0;
|
||||
ALU_ROR: shift_left = RV32B ? !instr_first_cycle_i : 0;
|
||||
ALU_FSL: shift_left =
|
||||
RV32B ? (shift_amt[5] ? !instr_first_cycle_i : instr_first_cycle_i) : 1'b0;
|
||||
ALU_FSR: shift_left =
|
||||
RV32B ? (shift_amt[5] ? instr_first_cycle_i : !instr_first_cycle_i) : 1'b0;
|
||||
default: shift_left = 1'b0;
|
||||
endcase
|
||||
end
|
||||
|
||||
assign shift_left = RV32B ? (operator_i == ALU_ROL) || (operator_i == ALU_SLO) ||
|
||||
(operator_i == ALU_SLL) :
|
||||
(operator_i == ALU_SLL);
|
||||
assign shift_ones = RV32B ? (operator_i == ALU_SLO) || (operator_i == ALU_SRO) : 1'b0;
|
||||
assign shift_arith = (operator_i == ALU_SRA);
|
||||
assign shift_rot = RV32B ? (operator_i == ALU_ROL) || (operator_i == ALU_ROR) : 1'b0;
|
||||
assign shift_funnel = RV32B ? (operator_i == ALU_FSL) || (operator_i == ALU_FSR) : 1'b0;
|
||||
assign shift_multicycle = shift_funnel || shift_rot;
|
||||
|
||||
assign shift_none = RV32B ? (operator_i == ALU_REV) || (operator_i == ALU_REV8) ||
|
||||
(operator_i == ALU_ORCB) :
|
||||
(operator_i == ALU_ORCB) :
|
||||
1'b0;
|
||||
|
||||
assign shift_op_rev = RV32B ? (operator_i == ALU_REV) : 1'b0;
|
||||
|
@ -113,11 +179,7 @@ module ibex_alu #(
|
|||
assign shift_op_orc_b = RV32B ? (operator_i == ALU_ORCB) : 1'b0;
|
||||
|
||||
logic [31:0] shift_result;
|
||||
logic [31:0] shift_extension_rvb;
|
||||
logic shift_extension;
|
||||
logic [32:0] shift_result_ext;
|
||||
logic [63:0] shift_result_ext_rvb;
|
||||
|
||||
|
||||
always_comb begin
|
||||
shift_result = operand_a_i;
|
||||
|
@ -127,27 +189,15 @@ module ibex_alu #(
|
|||
shift_result = operand_a_rev;
|
||||
end
|
||||
|
||||
if (RV32B) begin
|
||||
// rotation: extend with a copy of the operand
|
||||
// shift-ones: extend with ones
|
||||
// arithmetic shift: sign-extend.
|
||||
// else: zero-extend.
|
||||
shift_extension_rvb = shift_rot ?
|
||||
shift_result :
|
||||
{32{shift_ones || (shift_arith && operand_a_i[31])}};
|
||||
|
||||
shift_result_ext_rvb = {shift_extension_rvb, shift_result} >> shift_amt;
|
||||
end else begin
|
||||
shift_extension = (shift_arith && shift_result[31]);
|
||||
shift_result_ext = $signed({shift_extension, shift_result}) >>> shift_amt;
|
||||
end
|
||||
shift_result_ext = $signed({shift_ones || (shift_arith && shift_result[31]), shift_result})
|
||||
>>> shift_amt[4:0];
|
||||
|
||||
// shift, if this is a shift operation
|
||||
if (!shift_none) begin
|
||||
shift_result = RV32B ? shift_result_ext_rvb[31:0] : shift_result_ext[31:0];
|
||||
shift_result = shift_result_ext[31:0];
|
||||
end
|
||||
|
||||
// shift left: bytewise reverse. (orcomnine with '0)
|
||||
// shift left: bytewise reverse. (orcombine with '0)
|
||||
// orc_b: bytewise reverse and orcombine.
|
||||
if (shift_op_orc_b || shift_left) begin
|
||||
shift_result = (shift_op_orc_b ? shift_result : 32'h 0) |
|
||||
|
@ -182,7 +232,6 @@ module ibex_alu #(
|
|||
logic cmp_signed;
|
||||
|
||||
always_comb begin
|
||||
cmp_signed = 1'b0;
|
||||
unique case (operator_i)
|
||||
ALU_GE,
|
||||
ALU_LT,
|
||||
|
@ -191,7 +240,7 @@ module ibex_alu #(
|
|||
ALU_MIN,
|
||||
ALU_MAX: cmp_signed = 1'b1;
|
||||
|
||||
default:;
|
||||
default: cmp_signed = 1'b0;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -223,7 +272,6 @@ module ibex_alu #(
|
|||
logic cmp_result;
|
||||
|
||||
always_comb begin
|
||||
cmp_result = is_equal;
|
||||
unique case (operator_i)
|
||||
ALU_EQ: cmp_result = is_equal;
|
||||
ALU_NE: cmp_result = ~is_equal;
|
||||
|
@ -233,7 +281,7 @@ module ibex_alu #(
|
|||
ALU_MIN, ALU_MINU, //RV32B only
|
||||
ALU_SLT, ALU_SLTU: cmp_result = ~is_greater_equal;
|
||||
|
||||
default:;
|
||||
default: cmp_result = is_equal;
|
||||
endcase
|
||||
end
|
||||
|
||||
|
@ -243,6 +291,7 @@ module ibex_alu #(
|
|||
logic [5:0] bitcnt_result;
|
||||
logic [31:0] bwlogic_result;
|
||||
logic [31:0] pack_result;
|
||||
logic [31:0] multicycle_result;
|
||||
|
||||
///////////////////
|
||||
// Bitwise Logic //
|
||||
|
@ -251,21 +300,100 @@ module ibex_alu #(
|
|||
logic bwlogic_or;
|
||||
logic bwlogic_and;
|
||||
logic [31:0] bwlogic_operand_b;
|
||||
logic [31:0] bwlogic_or_op_a;
|
||||
logic [31:0] bwlogic_or_op_b;
|
||||
logic [31:0] bwlogic_or_result;
|
||||
logic [31:0] bwlogic_and_result;
|
||||
logic [31:0] bwlogic_xor_result;
|
||||
|
||||
logic bwlogic_op_b_negate;
|
||||
|
||||
always_comb begin
|
||||
unique case (operator_i)
|
||||
// Logic-with-negate OPs (RV32B Ops)
|
||||
ALU_XNOR,
|
||||
ALU_ORN,
|
||||
ALU_ANDN: bwlogic_op_b_negate = RV32B ? 1'b1 : 1'b0;
|
||||
ALU_CMIX: bwlogic_op_b_negate = RV32B ? !instr_first_cycle_i : 1'b0;
|
||||
default: bwlogic_op_b_negate = 1'b0;
|
||||
endcase
|
||||
end
|
||||
|
||||
assign bwlogic_operand_b = bwlogic_op_b_negate ? operand_b_neg[32:1] : operand_b_i;
|
||||
assign bwlogic_or_op_a = ((operator_i == ALU_CMIX) || shift_multicycle) ?
|
||||
imd_val_q_i : operand_a_i;
|
||||
assign bwlogic_or_op_b = (operator_i == ALU_CMIX) ? bwlogic_and_result :
|
||||
shift_multicycle ? shift_result : bwlogic_operand_b;
|
||||
|
||||
assign bwlogic_or_result = bwlogic_or_op_a | bwlogic_or_op_b;
|
||||
|
||||
assign bwlogic_and_result = operand_a_i & bwlogic_operand_b;
|
||||
assign bwlogic_xor_result = operand_a_i ^ bwlogic_operand_b;
|
||||
|
||||
assign bwlogic_or = (operator_i == ALU_OR) || (operator_i == ALU_ORN);
|
||||
assign bwlogic_and = (operator_i == ALU_AND) || (operator_i == ALU_ANDN);
|
||||
assign bwlogic_operand_b = RV32B ? operand_b_neg[32:1] : operand_b_i;
|
||||
|
||||
always_comb begin
|
||||
unique case (1'b1)
|
||||
bwlogic_or: bwlogic_result = operand_a_i | bwlogic_operand_b;
|
||||
bwlogic_and: bwlogic_result = operand_a_i & bwlogic_operand_b;
|
||||
default: bwlogic_result = operand_a_i ^ bwlogic_operand_b;
|
||||
bwlogic_or: bwlogic_result = bwlogic_or_result;
|
||||
bwlogic_and: bwlogic_result = bwlogic_and_result;
|
||||
default: bwlogic_result = bwlogic_xor_result;
|
||||
endcase
|
||||
end
|
||||
|
||||
if (RV32B) begin : g_alu_rvb
|
||||
|
||||
//////////////////////////////////////
|
||||
// Multicycle Bitmanip Instructions //
|
||||
//////////////////////////////////////
|
||||
// Ternary instructions + Shift Rotations
|
||||
// For ternary instructions (zbt), operand_a_i is tied to rs1 in the first cycle and rs3 in the
|
||||
// second cycle. operand_b_i is always tied to rs2.
|
||||
|
||||
always_comb begin
|
||||
unique case (operator_i)
|
||||
ALU_CMOV: begin
|
||||
imd_val_d_o = operand_a_i;
|
||||
multicycle_result = (operand_b_i == 32'h0) ? operand_a_i : imd_val_q_i;
|
||||
if (instr_first_cycle_i) begin
|
||||
imd_val_we_o = 1'b1;
|
||||
end else begin
|
||||
imd_val_we_o = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
ALU_CMIX: begin
|
||||
multicycle_result = bwlogic_or_result;
|
||||
imd_val_d_o = bwlogic_and_result;
|
||||
if (instr_first_cycle_i) begin
|
||||
imd_val_we_o = 1'b1;
|
||||
end else begin
|
||||
imd_val_we_o = 1'b0;
|
||||
end
|
||||
end
|
||||
|
||||
ALU_FSR, ALU_FSL,
|
||||
ALU_ROL, ALU_ROR: begin
|
||||
if (shift_amt[4:0] == 5'h0) begin
|
||||
multicycle_result = shift_amt[5] ? operand_a_i : imd_val_q_i;
|
||||
end else begin
|
||||
multicycle_result = bwlogic_or_result;
|
||||
end
|
||||
imd_val_d_o = shift_result;
|
||||
if (instr_first_cycle_i) begin
|
||||
imd_val_we_o = 1'b1;
|
||||
end else begin
|
||||
imd_val_we_o = 1'b0;
|
||||
end
|
||||
end
|
||||
default: begin
|
||||
imd_val_d_o = operand_a_i;
|
||||
imd_val_we_o = 1'b0;
|
||||
multicycle_result = operand_a_i;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
|
||||
///////////////
|
||||
// Min / Max //
|
||||
///////////////
|
||||
|
@ -315,10 +443,14 @@ module ibex_alu #(
|
|||
endcase
|
||||
end
|
||||
end else begin : g_no_alu_rvb
|
||||
// Rvb result signals
|
||||
assign minmax_result = '0;
|
||||
assign bitcnt_result = '0;
|
||||
assign pack_result = '0;
|
||||
// RV32B result signals
|
||||
assign minmax_result = '0;
|
||||
assign bitcnt_result = '0;
|
||||
assign pack_result = '0;
|
||||
assign multicycle_result = '0;
|
||||
// RV32B support signals
|
||||
assign imd_val_d_o = '0;
|
||||
assign imd_val_we_o = '0;
|
||||
end
|
||||
|
||||
////////////////
|
||||
|
@ -342,7 +474,6 @@ module ibex_alu #(
|
|||
ALU_SRA,
|
||||
// RV32B Ops
|
||||
ALU_SLO, ALU_SRO,
|
||||
ALU_ROL, ALU_ROR,
|
||||
ALU_REV, ALU_REV8,
|
||||
ALU_ORCB: result_o = shift_result;
|
||||
|
||||
|
@ -364,6 +495,11 @@ module ibex_alu #(
|
|||
ALU_PACK, ALU_PACKH,
|
||||
ALU_PACKU: result_o = pack_result;
|
||||
|
||||
// Ternary Bitmanip Operations (RV32B Ops)
|
||||
ALU_CMIX, ALU_CMOV,
|
||||
ALU_FSL, ALU_FSR,
|
||||
ALU_ROL, ALU_ROR: result_o = multicycle_result;
|
||||
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
|
|
142
rtl/ibex_core.sv
142
rtl/ibex_core.sv
|
@ -80,8 +80,10 @@ module ibex_core #(
|
|||
output logic [ 1:0] rvfi_mode,
|
||||
output logic [ 4:0] rvfi_rs1_addr,
|
||||
output logic [ 4:0] rvfi_rs2_addr,
|
||||
output logic [ 4:0] rvfi_rs3_addr,
|
||||
output logic [31:0] rvfi_rs1_rdata,
|
||||
output logic [31:0] rvfi_rs2_rdata,
|
||||
output logic [31:0] rvfi_rs3_rdata,
|
||||
output logic [ 4:0] rvfi_rd_addr,
|
||||
output logic [31:0] rvfi_rd_wdata,
|
||||
output logic [31:0] rvfi_pc_rdata,
|
||||
|
@ -106,17 +108,20 @@ module ibex_core #(
|
|||
// IF/ID signals
|
||||
logic instr_valid_id;
|
||||
logic instr_new_id;
|
||||
logic [31:0] instr_rdata_id; // Instruction sampled inside IF stage
|
||||
logic [31:0] instr_rdata_alu_id; // Instruction sampled inside IF stage (replicated to ease
|
||||
// fan-out)
|
||||
logic [15:0] instr_rdata_c_id; // Compressed instruction sampled inside IF stage
|
||||
logic [31:0] instr_rdata_id; // Instruction sampled inside IF stage
|
||||
logic [31:0] instr_rdata_alu_id; // Instruction sampled inside IF stage (replicated to ease
|
||||
// fan-out)
|
||||
logic [15:0] instr_rdata_c_id; // Compressed instruction sampled inside IF stage
|
||||
logic instr_is_compressed_id;
|
||||
logic instr_fetch_err; // Bus error on instr fetch
|
||||
logic instr_fetch_err_plus2; // Instruction error is misaligned
|
||||
logic illegal_c_insn_id; // Illegal compressed instruction sent to ID stage
|
||||
logic [31:0] pc_if; // Program counter in IF stage
|
||||
logic [31:0] pc_id; // Program counter in ID stage
|
||||
logic [31:0] pc_wb; // Program counter in WB stage
|
||||
logic instr_fetch_err; // Bus error on instr fetch
|
||||
logic instr_fetch_err_plus2; // Instruction error is misaligned
|
||||
logic illegal_c_insn_id; // Illegal compressed instruction sent to ID stage
|
||||
logic [31:0] pc_if; // Program counter in IF stage
|
||||
logic [31:0] pc_id; // Program counter in ID stage
|
||||
logic [31:0] pc_wb; // Program counter in WB stage
|
||||
logic [33:0] imd_val_d_ex; // Intermediate register for multicycle Ops
|
||||
logic [33:0] imd_val_q_ex; // Intermediate register for multicycle Ops
|
||||
logic imd_val_we_ex;
|
||||
|
||||
logic data_ind_timing;
|
||||
logic icache_enable;
|
||||
|
@ -125,9 +130,9 @@ module ibex_core #(
|
|||
logic instr_first_cycle_id;
|
||||
logic instr_valid_clear;
|
||||
logic pc_set;
|
||||
pc_sel_e pc_mux_id; // Mux selector for next PC
|
||||
exc_pc_sel_e exc_pc_mux_id; // Mux selector for exception PC
|
||||
exc_cause_e exc_cause; // Exception cause
|
||||
pc_sel_e pc_mux_id; // Mux selector for next PC
|
||||
exc_pc_sel_e exc_pc_mux_id; // Mux selector for exception PC
|
||||
exc_cause_e exc_cause; // Exception cause
|
||||
|
||||
logic lsu_load_err;
|
||||
logic lsu_store_err;
|
||||
|
@ -287,13 +292,21 @@ module ibex_core #(
|
|||
logic rvfi_set_trap_pc_q;
|
||||
logic [31:0] rvfi_insn_id;
|
||||
logic [4:0] rvfi_rs1_addr_id;
|
||||
logic [4:0] rvfi_rs1_addr_d;
|
||||
logic [4:0] rvfi_rs1_addr_q;
|
||||
logic [4:0] rvfi_rs2_addr_id;
|
||||
logic [4:0] rvfi_rs2_addr_d;
|
||||
logic [4:0] rvfi_rs2_addr_q;
|
||||
logic [4:0] rvfi_rs3_addr_id;
|
||||
logic [4:0] rvfi_rs3_addr_d;
|
||||
logic [31:0] rvfi_rs1_data_d;
|
||||
logic [31:0] rvfi_rs1_data_id;
|
||||
logic [31:0] rvfi_rs1_data_q;
|
||||
logic [31:0] rvfi_rs2_data_d;
|
||||
logic [31:0] rvfi_rs2_data_id;
|
||||
logic [31:0] rvfi_rs2_data_q;
|
||||
logic [31:0] rvfi_rs3_data_d;
|
||||
logic [31:0] rvfi_rs3_data_id;
|
||||
logic [4:0] rvfi_rd_addr_wb;
|
||||
logic [4:0] rvfi_rd_addr_q;
|
||||
logic [4:0] rvfi_rd_addr_d;
|
||||
|
@ -424,13 +437,13 @@ module ibex_core #(
|
|||
.DataIndTiming ( DataIndTiming ),
|
||||
.WritebackStage ( WritebackStage )
|
||||
) id_stage_i (
|
||||
.clk_i ( clk ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.clk_i ( clk ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
||||
// Processor Enable
|
||||
.fetch_enable_i ( fetch_enable_i ),
|
||||
.ctrl_busy_o ( ctrl_busy ),
|
||||
.illegal_insn_o ( illegal_insn_id ),
|
||||
.fetch_enable_i ( fetch_enable_i ),
|
||||
.ctrl_busy_o ( ctrl_busy ),
|
||||
.illegal_insn_o ( illegal_insn_id ),
|
||||
|
||||
// from/to IF-ID pipeline register
|
||||
.instr_valid_i ( instr_valid_id ),
|
||||
|
@ -469,6 +482,10 @@ module ibex_core #(
|
|||
.alu_operand_a_ex_o ( alu_operand_a_ex ),
|
||||
.alu_operand_b_ex_o ( alu_operand_b_ex ),
|
||||
|
||||
.imd_val_q_ex_o ( imd_val_q_ex ),
|
||||
.imd_val_d_ex_i ( imd_val_d_ex ),
|
||||
.imd_val_we_ex_i ( imd_val_we_ex ),
|
||||
|
||||
.bt_a_operand_o ( bt_a_operand ),
|
||||
.bt_b_operand_o ( bt_b_operand ),
|
||||
|
||||
|
@ -549,7 +566,6 @@ module ibex_core #(
|
|||
.ready_wb_i ( ready_wb ),
|
||||
.outstanding_load_wb_i ( outstanding_load_wb ),
|
||||
.outstanding_store_wb_i ( outstanding_store_wb ),
|
||||
|
||||
// Performance Counters
|
||||
.perf_jump_o ( perf_jump ),
|
||||
.perf_branch_o ( perf_branch ),
|
||||
|
@ -565,40 +581,47 @@ module ibex_core #(
|
|||
assign unused_illegal_insn_id = illegal_insn_id;
|
||||
|
||||
ibex_ex_block #(
|
||||
.RV32M ( RV32M ),
|
||||
.RV32B ( RV32B ),
|
||||
.BranchTargetALU ( BranchTargetALU ),
|
||||
.MultiplierImplementation ( MultiplierImplementation )
|
||||
.RV32M ( RV32M ),
|
||||
.RV32B ( RV32B ),
|
||||
.BranchTargetALU ( BranchTargetALU ),
|
||||
.MultiplierImplementation ( MultiplierImplementation )
|
||||
) ex_block_i (
|
||||
.clk_i ( clk ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.clk_i ( clk ),
|
||||
.rst_ni ( rst_ni ),
|
||||
|
||||
// ALU signal from ID stage
|
||||
.alu_operator_i ( alu_operator_ex ),
|
||||
.alu_operand_a_i ( alu_operand_a_ex ),
|
||||
.alu_operand_b_i ( alu_operand_b_ex ),
|
||||
.alu_operator_i ( alu_operator_ex ),
|
||||
.alu_operand_a_i ( alu_operand_a_ex ),
|
||||
.alu_operand_b_i ( alu_operand_b_ex ),
|
||||
.alu_instr_first_cycle_i ( instr_first_cycle_id ),
|
||||
|
||||
// Branch target ALU signal from ID stage
|
||||
.bt_a_operand_i ( bt_a_operand ),
|
||||
.bt_b_operand_i ( bt_b_operand ),
|
||||
.bt_a_operand_i ( bt_a_operand ),
|
||||
.bt_b_operand_i ( bt_b_operand ),
|
||||
|
||||
// Multipler/Divider signal from ID stage
|
||||
.multdiv_operator_i ( multdiv_operator_ex ),
|
||||
.mult_en_i ( mult_en_ex ),
|
||||
.div_en_i ( div_en_ex ),
|
||||
.multdiv_sel_i ( multdiv_sel_ex ),
|
||||
.multdiv_signed_mode_i ( multdiv_signed_mode_ex ),
|
||||
.multdiv_operand_a_i ( multdiv_operand_a_ex ),
|
||||
.multdiv_operand_b_i ( multdiv_operand_b_ex ),
|
||||
.multdiv_ready_id_i ( multdiv_ready_id ),
|
||||
.multdiv_operator_i ( multdiv_operator_ex ),
|
||||
.mult_en_i ( mult_en_ex ),
|
||||
.div_en_i ( div_en_ex ),
|
||||
.multdiv_sel_i ( multdiv_sel_ex ),
|
||||
.multdiv_signed_mode_i ( multdiv_signed_mode_ex ),
|
||||
.multdiv_operand_a_i ( multdiv_operand_a_ex ),
|
||||
.multdiv_operand_b_i ( multdiv_operand_b_ex ),
|
||||
.multdiv_ready_id_i ( multdiv_ready_id ),
|
||||
|
||||
// Intermediate value register
|
||||
.imd_val_we_o ( imd_val_we_ex ),
|
||||
.imd_val_d_o ( imd_val_d_ex ),
|
||||
.imd_val_q_i ( imd_val_q_ex ),
|
||||
|
||||
// Outputs
|
||||
.alu_adder_result_ex_o ( alu_adder_result_ex ), // to LSU
|
||||
.result_ex_o ( result_ex ), // to ID
|
||||
.alu_adder_result_ex_o ( alu_adder_result_ex ), // to LSU
|
||||
.result_ex_o ( result_ex ), // to ID
|
||||
|
||||
.branch_target_o ( branch_target_ex ), // to IF
|
||||
.branch_decision_o ( branch_decision ), // to ID
|
||||
.branch_target_o ( branch_target_ex ), // to IF
|
||||
.branch_decision_o ( branch_decision ), // to ID
|
||||
|
||||
.ex_valid_o ( ex_valid )
|
||||
.ex_valid_o ( ex_valid )
|
||||
);
|
||||
|
||||
/////////////////////
|
||||
|
@ -756,7 +779,8 @@ module ibex_core #(
|
|||
assign rvfi_rs1_data_id = id_stage_i.rf_rdata_a_fwd;
|
||||
assign rvfi_rs2_addr_id = rf_raddr_b;
|
||||
assign rvfi_rs2_data_id = id_stage_i.rf_rdata_b_fwd;
|
||||
|
||||
assign rvfi_rs3_addr_id = rf_raddr_a;
|
||||
assign rvfi_rs3_data_id = id_stage_i.rf_rdata_a_fwd;
|
||||
assign rvfi_rd_addr_wb = rf_waddr_wb;
|
||||
assign rvfi_rd_wdata_wb = rf_we_wb ? rf_wdata_wb : rf_wdata_lsu;
|
||||
assign rvfi_rd_we_wb = rf_we_wb | rf_we_lsu;
|
||||
|
@ -931,8 +955,10 @@ module ibex_core #(
|
|||
logic [ 1:0] rvfi_stage_mode [RVFI_STAGES-1:0];
|
||||
logic [ 4:0] rvfi_stage_rs1_addr [RVFI_STAGES-1:0];
|
||||
logic [ 4:0] rvfi_stage_rs2_addr [RVFI_STAGES-1:0];
|
||||
logic [ 4:0] rvfi_stage_rs3_addr [RVFI_STAGES-1:0];
|
||||
logic [31:0] rvfi_stage_rs1_rdata [RVFI_STAGES-1:0];
|
||||
logic [31:0] rvfi_stage_rs2_rdata [RVFI_STAGES-1:0];
|
||||
logic [31:0] rvfi_stage_rs3_rdata [RVFI_STAGES-1:0];
|
||||
logic [ 4:0] rvfi_stage_rd_addr [RVFI_STAGES-1:0];
|
||||
logic [31:0] rvfi_stage_rd_wdata [RVFI_STAGES-1:0];
|
||||
logic [31:0] rvfi_stage_pc_rdata [RVFI_STAGES-1:0];
|
||||
|
@ -954,8 +980,10 @@ module ibex_core #(
|
|||
assign rvfi_mode = rvfi_stage_mode [RVFI_STAGES-1];
|
||||
assign rvfi_rs1_addr = rvfi_stage_rs1_addr [RVFI_STAGES-1];
|
||||
assign rvfi_rs2_addr = rvfi_stage_rs2_addr [RVFI_STAGES-1];
|
||||
assign rvfi_rs3_addr = rvfi_stage_rs3_addr [RVFI_STAGES-1];
|
||||
assign rvfi_rs1_rdata = rvfi_stage_rs1_rdata[RVFI_STAGES-1];
|
||||
assign rvfi_rs2_rdata = rvfi_stage_rs2_rdata[RVFI_STAGES-1];
|
||||
assign rvfi_rs3_rdata = rvfi_stage_rs3_rdata[RVFI_STAGES-1];
|
||||
assign rvfi_rd_addr = rvfi_stage_rd_addr [RVFI_STAGES-1];
|
||||
assign rvfi_rd_wdata = rvfi_stage_rd_wdata [RVFI_STAGES-1];
|
||||
assign rvfi_pc_rdata = rvfi_stage_pc_rdata [RVFI_STAGES-1];
|
||||
|
@ -1012,6 +1040,7 @@ module ibex_core #(
|
|||
rvfi_stage_mode[i] <= {PRIV_LVL_M};
|
||||
rvfi_stage_rs1_addr[i] <= '0;
|
||||
rvfi_stage_rs2_addr[i] <= '0;
|
||||
rvfi_stage_rs3_addr[i] <= '0;
|
||||
rvfi_stage_pc_rdata[i] <= '0;
|
||||
rvfi_stage_pc_wdata[i] <= '0;
|
||||
rvfi_stage_mem_rmask[i] <= '0;
|
||||
|
@ -1019,6 +1048,7 @@ module ibex_core #(
|
|||
rvfi_stage_valid[i] <= '0;
|
||||
rvfi_stage_rs1_rdata[i] <= '0;
|
||||
rvfi_stage_rs2_rdata[i] <= '0;
|
||||
rvfi_stage_rs3_rdata[i] <= '0;
|
||||
rvfi_stage_rd_wdata[i] <= '0;
|
||||
rvfi_stage_rd_addr[i] <= '0;
|
||||
rvfi_stage_mem_rdata[i] <= '0;
|
||||
|
@ -1035,14 +1065,16 @@ module ibex_core #(
|
|||
rvfi_stage_order[i] <= rvfi_order + 64'(rvfi_valid);
|
||||
rvfi_stage_insn[i] <= rvfi_insn_id;
|
||||
rvfi_stage_mode[i] <= {priv_mode_id};
|
||||
rvfi_stage_rs1_addr[i] <= rvfi_rs1_addr_id;
|
||||
rvfi_stage_rs2_addr[i] <= rvfi_rs2_addr_id;
|
||||
rvfi_stage_rs1_addr[i] <= rvfi_rs1_addr_d;
|
||||
rvfi_stage_rs2_addr[i] <= rvfi_rs2_addr_d;
|
||||
rvfi_stage_rs3_addr[i] <= rvfi_rs3_addr_d;
|
||||
rvfi_stage_pc_rdata[i] <= pc_id;
|
||||
rvfi_stage_pc_wdata[i] <= pc_if;
|
||||
rvfi_stage_mem_rmask[i] <= rvfi_mem_mask_int;
|
||||
rvfi_stage_mem_wmask[i] <= data_we_o ? rvfi_mem_mask_int : 4'b0000;
|
||||
rvfi_stage_rs1_rdata[i] <= rvfi_rs1_data_d;
|
||||
rvfi_stage_rs2_rdata[i] <= rvfi_rs2_data_d;
|
||||
rvfi_stage_rs3_rdata[i] <= rvfi_rs3_data_d;
|
||||
rvfi_stage_rd_addr[i] <= rvfi_rd_addr_d;
|
||||
rvfi_stage_rd_wdata[i] <= rvfi_rd_wdata_d;
|
||||
rvfi_stage_mem_rdata[i] <= rvfi_mem_rdata_d;
|
||||
|
@ -1059,12 +1091,14 @@ module ibex_core #(
|
|||
rvfi_stage_mode[i] <= rvfi_stage_mode[i-1];
|
||||
rvfi_stage_rs1_addr[i] <= rvfi_stage_rs1_addr[i-1];
|
||||
rvfi_stage_rs2_addr[i] <= rvfi_stage_rs2_addr[i-1];
|
||||
rvfi_stage_rs3_addr[i] <= rvfi_stage_rs3_addr[i-1];
|
||||
rvfi_stage_pc_rdata[i] <= rvfi_stage_pc_rdata[i-1];
|
||||
rvfi_stage_pc_wdata[i] <= rvfi_stage_pc_wdata[i-1];
|
||||
rvfi_stage_mem_rmask[i] <= rvfi_stage_mem_rmask[i-1];
|
||||
rvfi_stage_mem_wmask[i] <= rvfi_stage_mem_wmask[i-1];
|
||||
rvfi_stage_rs1_rdata[i] <= rvfi_stage_rs1_rdata[i-1];
|
||||
rvfi_stage_rs2_rdata[i] <= rvfi_stage_rs2_rdata[i-1];
|
||||
rvfi_stage_rs3_rdata[i] <= rvfi_stage_rs3_rdata[i-1];
|
||||
rvfi_stage_rd_addr[i] <= rvfi_stage_rd_addr[i-1];
|
||||
rvfi_stage_mem_wdata[i] <= rvfi_stage_mem_wdata[i-1];
|
||||
rvfi_stage_mem_addr[i] <= rvfi_stage_mem_addr[i-1];
|
||||
|
@ -1132,23 +1166,37 @@ module ibex_core #(
|
|||
end
|
||||
end
|
||||
|
||||
// Source register data are kept stable for each instruction cycle
|
||||
// Source registers 1 and 2 are read in the first instruction cycle
|
||||
// Source register 3 is read in the second instruction cycle.
|
||||
always_comb begin
|
||||
if (instr_first_cycle_id) begin
|
||||
rvfi_rs1_data_d = rvfi_rs1_data_id;
|
||||
rvfi_rs1_addr_d = rvfi_rs1_addr_id;
|
||||
rvfi_rs2_data_d = rvfi_rs2_data_id;
|
||||
rvfi_rs2_addr_d = rvfi_rs2_addr_id;
|
||||
rvfi_rs3_data_d = '0;
|
||||
rvfi_rs3_addr_d = '0;
|
||||
end else begin
|
||||
rvfi_rs1_data_d = rvfi_rs1_data_q;
|
||||
rvfi_rs1_addr_d = rvfi_rs1_addr_q;
|
||||
rvfi_rs2_data_d = rvfi_rs2_data_q;
|
||||
rvfi_rs2_addr_d = rvfi_rs2_addr_q;
|
||||
rvfi_rs3_data_d = rvfi_rs3_data_id;
|
||||
rvfi_rs3_addr_d = rvfi_rs3_addr_id;
|
||||
end
|
||||
end
|
||||
always_ff @(posedge clk or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
rvfi_rs1_data_q <= '0;
|
||||
rvfi_rs1_addr_q <= '0;
|
||||
rvfi_rs2_data_q <= '0;
|
||||
rvfi_rs2_addr_q <= '0;
|
||||
|
||||
end else begin
|
||||
rvfi_rs1_data_q <= rvfi_rs1_data_d;
|
||||
rvfi_rs1_addr_q <= rvfi_rs1_addr_d;
|
||||
rvfi_rs2_data_q <= rvfi_rs2_data_d;
|
||||
rvfi_rs2_addr_q <= rvfi_rs2_addr_d;
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -85,8 +85,10 @@ module ibex_core_tracing #(
|
|||
logic [ 1:0] rvfi_mode;
|
||||
logic [ 4:0] rvfi_rs1_addr;
|
||||
logic [ 4:0] rvfi_rs2_addr;
|
||||
logic [ 4:0] rvfi_rs3_addr;
|
||||
logic [31:0] rvfi_rs1_rdata;
|
||||
logic [31:0] rvfi_rs2_rdata;
|
||||
logic [31:0] rvfi_rs3_rdata;
|
||||
logic [ 4:0] rvfi_rd_addr;
|
||||
logic [31:0] rvfi_rd_wdata;
|
||||
logic [31:0] rvfi_pc_rdata;
|
||||
|
@ -158,8 +160,10 @@ module ibex_core_tracing #(
|
|||
.rvfi_mode,
|
||||
.rvfi_rs1_addr,
|
||||
.rvfi_rs2_addr,
|
||||
.rvfi_rs3_addr,
|
||||
.rvfi_rs1_rdata,
|
||||
.rvfi_rs2_rdata,
|
||||
.rvfi_rs3_rdata,
|
||||
.rvfi_rd_addr,
|
||||
.rvfi_rd_wdata,
|
||||
.rvfi_pc_rdata,
|
||||
|
@ -190,8 +194,10 @@ module ibex_core_tracing #(
|
|||
.rvfi_mode,
|
||||
.rvfi_rs1_addr,
|
||||
.rvfi_rs2_addr,
|
||||
.rvfi_rs3_addr,
|
||||
.rvfi_rs1_rdata,
|
||||
.rvfi_rs2_rdata,
|
||||
.rvfi_rs3_rdata,
|
||||
.rvfi_rd_addr,
|
||||
.rvfi_rd_wdata,
|
||||
.rvfi_pc_rdata,
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
// Source/Destination register instruction index
|
||||
`define REG_S1 19:15
|
||||
`define REG_S2 24:20
|
||||
`define REG_S3 31:27
|
||||
`define REG_D 11:07
|
||||
|
||||
/**
|
||||
|
@ -73,6 +74,7 @@ module ibex_decoder #(
|
|||
// immediate or zero
|
||||
output ibex_pkg::op_b_sel_e alu_op_b_mux_sel_o, // operand b selection: reg value or
|
||||
// immediate
|
||||
output logic alu_multicycle_o, // ternary bitmanip instruction
|
||||
|
||||
// MULT & DIV
|
||||
output logic mult_en_o, // perform integer multiplication
|
||||
|
@ -110,6 +112,8 @@ module ibex_decoder #(
|
|||
logic [31:0] instr;
|
||||
logic [31:0] instr_alu;
|
||||
|
||||
logic use_rs3;
|
||||
|
||||
csr_op_e csr_op;
|
||||
|
||||
opcode_e opcode;
|
||||
|
@ -136,7 +140,7 @@ module ibex_decoder #(
|
|||
assign zimm_rs1_type_o = { 27'b0, instr[`REG_S1] }; // rs1
|
||||
|
||||
// source registers
|
||||
assign rf_raddr_a_o = instr[`REG_S1]; // rs1
|
||||
assign rf_raddr_a_o = use_rs3 ? instr[`REG_S3] : instr[`REG_S1]; // rs3 / rs1
|
||||
assign rf_raddr_b_o = instr[`REG_S2]; // rs2
|
||||
|
||||
// destination register
|
||||
|
@ -347,24 +351,28 @@ module ibex_decoder #(
|
|||
end
|
||||
|
||||
3'b101: begin
|
||||
unique case (instr[31:25])
|
||||
7'b000_0000, // srli
|
||||
7'b010_0000: illegal_insn = 1'b0; // srai
|
||||
if (instr[26]) begin
|
||||
illegal_insn = RV32B ? 1'b0 : 1'b1; // fsri
|
||||
end else begin
|
||||
unique case (instr[31:25])
|
||||
7'b000_0000, // srli
|
||||
7'b010_0000: illegal_insn = 1'b0; // srai
|
||||
|
||||
7'b001_0000, // sroi
|
||||
7'b011_0000: illegal_insn = RV32B ? 1'b0 : 1'b1; // rori
|
||||
7'b001_0000, // sroi
|
||||
7'b011_0000: illegal_insn = RV32B ? 1'b0 : 1'b1; // rori
|
||||
|
||||
7'b011_0100: begin
|
||||
unique case(instr[24:20])
|
||||
5'b11111, // rev
|
||||
5'b11000, // rev8
|
||||
5'b00111: illegal_insn = RV32B ? 1'b0 : 1'b1; // orc.b
|
||||
7'b011_0100: begin
|
||||
unique case(instr[24:20])
|
||||
5'b11111, // rev
|
||||
5'b11000, // rev8
|
||||
5'b00111: illegal_insn = RV32B ? 1'b0 : 1'b1; // orc.b
|
||||
|
||||
default: illegal_insn = 1'b1;
|
||||
endcase
|
||||
end
|
||||
default: illegal_insn = 1'b1;
|
||||
endcase
|
||||
default: illegal_insn = 1'b1;
|
||||
endcase
|
||||
end
|
||||
default: illegal_insn = 1'b1;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
default: illegal_insn = 1'b1;
|
||||
|
@ -375,92 +383,95 @@ module ibex_decoder #(
|
|||
rf_ren_a_o = 1'b1;
|
||||
rf_ren_b_o = 1'b1;
|
||||
rf_we = 1'b1;
|
||||
|
||||
if (instr[31]) begin
|
||||
illegal_insn = 1'b1;
|
||||
end else begin
|
||||
unique case ({instr[30:25], instr[14:12]})
|
||||
// RV32I ALU operations
|
||||
{6'b00_0000, 3'b000},
|
||||
{6'b10_0000, 3'b000},
|
||||
{6'b00_0000, 3'b010},
|
||||
{6'b00_0000, 3'b011},
|
||||
{6'b00_0000, 3'b100},
|
||||
{6'b00_0000, 3'b110},
|
||||
{6'b00_0000, 3'b111},
|
||||
{6'b00_0000, 3'b001},
|
||||
{6'b00_0000, 3'b101},
|
||||
{6'b10_0000, 3'b101}: illegal_insn = 1'b0;
|
||||
if ({instr[26], instr[13:12]} == {1'b1, 2'b01}) begin
|
||||
illegal_insn = RV32B ? 1'b0 : 1'b1; // cmix / cmov / fsl / fsr
|
||||
end else begin
|
||||
unique case ({instr[30:25], instr[14:12]})
|
||||
// RV32I ALU operations
|
||||
{6'b00_0000, 3'b000},
|
||||
{6'b10_0000, 3'b000},
|
||||
{6'b00_0000, 3'b010},
|
||||
{6'b00_0000, 3'b011},
|
||||
{6'b00_0000, 3'b100},
|
||||
{6'b00_0000, 3'b110},
|
||||
{6'b00_0000, 3'b111},
|
||||
{6'b00_0000, 3'b001},
|
||||
{6'b00_0000, 3'b101},
|
||||
{6'b10_0000, 3'b101}: illegal_insn = 1'b0;
|
||||
|
||||
// supported RV32B instructions (zbb)
|
||||
{6'b10_0000, 3'b111}, // andn
|
||||
{6'b10_0000, 3'b110}, // orn
|
||||
{6'b10_0000, 3'b100}, // xnor
|
||||
{6'b01_0000, 3'b001}, // slo
|
||||
{6'b01_0000, 3'b101}, // sro
|
||||
{6'b11_0000, 3'b001}, // rol
|
||||
{6'b11_0000, 3'b101}, // ror
|
||||
{6'b00_0101, 3'b100}, // min
|
||||
{6'b00_0101, 3'b101}, // max
|
||||
{6'b00_0101, 3'b110}, // minu
|
||||
{6'b00_0101, 3'b111}, // maxu
|
||||
{6'b00_0100, 3'b100}, // pack
|
||||
{6'b10_0100, 3'b100}, // packu
|
||||
{6'b00_0100, 3'b111}: illegal_insn = RV32B ? 1'b0 : 1'b1; // packh
|
||||
// supported RV32B instructions (zbb)
|
||||
{6'b10_0000, 3'b111}, // andn
|
||||
{6'b10_0000, 3'b110}, // orn
|
||||
{6'b10_0000, 3'b100}, // xnor
|
||||
{6'b01_0000, 3'b001}, // slo
|
||||
{6'b01_0000, 3'b101}, // sro
|
||||
{6'b11_0000, 3'b001}, // rol
|
||||
{6'b11_0000, 3'b101}, // ror
|
||||
{6'b00_0101, 3'b100}, // min
|
||||
{6'b00_0101, 3'b101}, // max
|
||||
{6'b00_0101, 3'b110}, // minu
|
||||
{6'b00_0101, 3'b111}, // maxu
|
||||
{6'b00_0100, 3'b100}, // pack
|
||||
{6'b10_0100, 3'b100}, // packu
|
||||
{6'b00_0100, 3'b111}: illegal_insn = RV32B ? 1'b0 : 1'b1; // packh
|
||||
|
||||
// supported RV32M instructions
|
||||
{6'b00_0001, 3'b000}: begin // mul
|
||||
multdiv_operator_o = MD_OP_MULL;
|
||||
mult_en_o = RV32M ? 1'b1 : 1'b0;
|
||||
multdiv_signed_mode_o = 2'b00;
|
||||
illegal_insn = RV32M ? 1'b0 : 1'b1;
|
||||
end
|
||||
{6'b00_0001, 3'b001}: begin // mulh
|
||||
multdiv_operator_o = MD_OP_MULH;
|
||||
mult_en_o = RV32M ? 1'b1 : 1'b0;
|
||||
multdiv_signed_mode_o = 2'b11;
|
||||
illegal_insn = RV32M ? 1'b0 : 1'b1;
|
||||
end
|
||||
{6'b00_0001, 3'b010}: begin // mulhsu
|
||||
multdiv_operator_o = MD_OP_MULH;
|
||||
mult_en_o = RV32M ? 1'b1 : 1'b0;
|
||||
multdiv_signed_mode_o = 2'b01;
|
||||
illegal_insn = RV32M ? 1'b0 : 1'b1;
|
||||
end
|
||||
{6'b00_0001, 3'b011}: begin // mulhu
|
||||
multdiv_operator_o = MD_OP_MULH;
|
||||
mult_en_o = RV32M ? 1'b1 : 1'b0;
|
||||
multdiv_signed_mode_o = 2'b00;
|
||||
illegal_insn = RV32M ? 1'b0 : 1'b1;
|
||||
end
|
||||
{6'b00_0001, 3'b100}: begin // div
|
||||
multdiv_operator_o = MD_OP_DIV;
|
||||
div_en_o = RV32M ? 1'b1 : 1'b0;
|
||||
multdiv_signed_mode_o = 2'b11;
|
||||
illegal_insn = RV32M ? 1'b0 : 1'b1;
|
||||
end
|
||||
{6'b00_0001, 3'b101}: begin // divu
|
||||
multdiv_operator_o = MD_OP_DIV;
|
||||
div_en_o = RV32M ? 1'b1 : 1'b0;
|
||||
multdiv_signed_mode_o = 2'b00;
|
||||
illegal_insn = RV32M ? 1'b0 : 1'b1;
|
||||
end
|
||||
{6'b00_0001, 3'b110}: begin // rem
|
||||
multdiv_operator_o = MD_OP_REM;
|
||||
div_en_o = RV32M ? 1'b1 : 1'b0;
|
||||
multdiv_signed_mode_o = 2'b11;
|
||||
illegal_insn = RV32M ? 1'b0 : 1'b1;
|
||||
end
|
||||
{6'b00_0001, 3'b111}: begin // remu
|
||||
multdiv_operator_o = MD_OP_REM;
|
||||
div_en_o = RV32M ? 1'b1 : 1'b0;
|
||||
multdiv_signed_mode_o = 2'b00;
|
||||
illegal_insn = RV32M ? 1'b0 : 1'b1;
|
||||
end
|
||||
default: begin
|
||||
illegal_insn = 1'b1;
|
||||
end
|
||||
endcase
|
||||
// supported RV32M instructions
|
||||
{6'b00_0001, 3'b000}: begin // mul
|
||||
multdiv_operator_o = MD_OP_MULL;
|
||||
mult_en_o = RV32M ? 1'b1 : 1'b0;
|
||||
multdiv_signed_mode_o = 2'b00;
|
||||
illegal_insn = RV32M ? 1'b0 : 1'b1;
|
||||
end
|
||||
{6'b00_0001, 3'b001}: begin // mulh
|
||||
multdiv_operator_o = MD_OP_MULH;
|
||||
mult_en_o = RV32M ? 1'b1 : 1'b0;
|
||||
multdiv_signed_mode_o = 2'b11;
|
||||
illegal_insn = RV32M ? 1'b0 : 1'b1;
|
||||
end
|
||||
{6'b00_0001, 3'b010}: begin // mulhsu
|
||||
multdiv_operator_o = MD_OP_MULH;
|
||||
mult_en_o = RV32M ? 1'b1 : 1'b0;
|
||||
multdiv_signed_mode_o = 2'b01;
|
||||
illegal_insn = RV32M ? 1'b0 : 1'b1;
|
||||
end
|
||||
{6'b00_0001, 3'b011}: begin // mulhu
|
||||
multdiv_operator_o = MD_OP_MULH;
|
||||
mult_en_o = RV32M ? 1'b1 : 1'b0;
|
||||
multdiv_signed_mode_o = 2'b00;
|
||||
illegal_insn = RV32M ? 1'b0 : 1'b1;
|
||||
end
|
||||
{6'b00_0001, 3'b100}: begin // div
|
||||
multdiv_operator_o = MD_OP_DIV;
|
||||
div_en_o = RV32M ? 1'b1 : 1'b0;
|
||||
multdiv_signed_mode_o = 2'b11;
|
||||
illegal_insn = RV32M ? 1'b0 : 1'b1;
|
||||
end
|
||||
{6'b00_0001, 3'b101}: begin // divu
|
||||
multdiv_operator_o = MD_OP_DIV;
|
||||
div_en_o = RV32M ? 1'b1 : 1'b0;
|
||||
multdiv_signed_mode_o = 2'b00;
|
||||
illegal_insn = RV32M ? 1'b0 : 1'b1;
|
||||
end
|
||||
{6'b00_0001, 3'b110}: begin // rem
|
||||
multdiv_operator_o = MD_OP_REM;
|
||||
div_en_o = RV32M ? 1'b1 : 1'b0;
|
||||
multdiv_signed_mode_o = 2'b11;
|
||||
illegal_insn = RV32M ? 1'b0 : 1'b1;
|
||||
end
|
||||
{6'b00_0001, 3'b111}: begin // remu
|
||||
multdiv_operator_o = MD_OP_REM;
|
||||
div_en_o = RV32M ? 1'b1 : 1'b0;
|
||||
multdiv_signed_mode_o = 2'b00;
|
||||
illegal_insn = RV32M ? 1'b0 : 1'b1;
|
||||
end
|
||||
default: begin
|
||||
illegal_insn = 1'b1;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -593,6 +604,9 @@ module ibex_decoder #(
|
|||
|
||||
opcode_alu = opcode_e'(instr_alu[6:0]);
|
||||
|
||||
use_rs3 = 1'b0;
|
||||
alu_multicycle_o = 1'b0;
|
||||
|
||||
unique case (opcode_alu)
|
||||
|
||||
///////////
|
||||
|
@ -760,6 +774,15 @@ module ibex_decoder #(
|
|||
|
||||
3'b101: begin
|
||||
if (RV32B) begin
|
||||
if (instr_alu[26] == 1'b1) begin
|
||||
alu_operator_o = ALU_FSR;
|
||||
alu_multicycle_o = 1'b1;
|
||||
if (instr_first_cycle_i) begin
|
||||
use_rs3 = 1'b0;
|
||||
end else begin
|
||||
use_rs3 = 1'b1;
|
||||
end
|
||||
end
|
||||
// We don't factor in instr[31] here to make the ALU decoder more symmetric for
|
||||
// Reg-Reg and Reg-Imm ALU operations. Instr[31] is only needed to detect illegal
|
||||
// encodings for Reg-Reg ALU operations (see non-ALU decoder).
|
||||
|
@ -767,7 +790,10 @@ module ibex_decoder #(
|
|||
6'b00_0000: alu_operator_o = ALU_SRL; // Shift Right Logical by Immediate
|
||||
6'b10_0000: alu_operator_o = ALU_SRA; // Shift Right Arithmetically by Immediate
|
||||
6'b01_0000: alu_operator_o = ALU_SRO; // Shift Right Ones by Immediate
|
||||
6'b11_0000: alu_operator_o = ALU_ROR; // Rotate Right by Immediate
|
||||
6'b11_0000: begin
|
||||
alu_operator_o = ALU_ROR; // Rotate Right by Immediate
|
||||
alu_multicycle_o = 1'b1;
|
||||
end
|
||||
6'b11_0100: begin
|
||||
if (instr_alu[24:20] == 5'b11111) begin
|
||||
alu_operator_o = ALU_REV; // Reverse
|
||||
|
@ -800,6 +826,49 @@ module ibex_decoder #(
|
|||
alu_op_a_mux_sel_o = OP_A_REG_A;
|
||||
alu_op_b_mux_sel_o = OP_B_REG_B;
|
||||
|
||||
if (instr_alu[26]) begin
|
||||
if (RV32B) begin
|
||||
unique case ({instr_alu[26:25], instr_alu[14:12]})
|
||||
{2'b11, 3'b001}: begin
|
||||
alu_operator_o = ALU_CMIX; // cmix
|
||||
alu_multicycle_o = 1'b1;
|
||||
if (instr_first_cycle_i) begin
|
||||
use_rs3 = 1'b0;
|
||||
end else begin
|
||||
use_rs3 = 1'b1;
|
||||
end
|
||||
end
|
||||
{2'b11, 3'b101}: begin
|
||||
alu_operator_o = ALU_CMOV; // cmov
|
||||
alu_multicycle_o = 1'b1;
|
||||
if (instr_first_cycle_i) begin
|
||||
use_rs3 = 1'b0;
|
||||
end else begin
|
||||
use_rs3 = 1'b1;
|
||||
end
|
||||
end
|
||||
{2'b10, 3'b001}: begin
|
||||
alu_operator_o = ALU_FSL; // fsl
|
||||
alu_multicycle_o = 1'b1;
|
||||
if (instr_first_cycle_i) begin
|
||||
use_rs3 = 1'b0;
|
||||
end else begin
|
||||
use_rs3 = 1'b1;
|
||||
end
|
||||
end
|
||||
{2'b10, 3'b101}: begin
|
||||
alu_operator_o = ALU_FSR; // fsr
|
||||
alu_multicycle_o = 1'b1;
|
||||
if (instr_first_cycle_i) begin
|
||||
use_rs3 = 1'b0;
|
||||
end else begin
|
||||
use_rs3 = 1'b1;
|
||||
end
|
||||
end
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
end
|
||||
unique case ({instr_alu[30:25], instr_alu[14:12]})
|
||||
// RV32I ALU operations
|
||||
{6'b00_0000, 3'b000}: alu_operator_o = ALU_ADD; // Add
|
||||
|
@ -816,8 +885,18 @@ module ibex_decoder #(
|
|||
// RV32B ALU Operations
|
||||
{6'b01_0000, 3'b001}: if (RV32B) alu_operator_o = ALU_SLO; // Shift Left Ones
|
||||
{6'b01_0000, 3'b101}: if (RV32B) alu_operator_o = ALU_SRO; // Shift Right Ones
|
||||
{6'b11_0000, 3'b001}: if (RV32B) alu_operator_o = ALU_ROL; // Rotate Left
|
||||
{6'b11_0000, 3'b101}: if (RV32B) alu_operator_o = ALU_ROR; // Rotate Right
|
||||
{6'b11_0000, 3'b001}: begin
|
||||
if (RV32B) begin
|
||||
alu_operator_o = ALU_ROL; // Rotate Left
|
||||
alu_multicycle_o = 1'b1;
|
||||
end
|
||||
end
|
||||
{6'b11_0000, 3'b101}: begin
|
||||
if (RV32B) begin
|
||||
alu_operator_o = ALU_ROR; // Rotate Right
|
||||
alu_multicycle_o = 1'b1;
|
||||
end
|
||||
end
|
||||
|
||||
{6'b00_0101, 3'b100}: if (RV32B) alu_operator_o = ALU_MIN; // Minimum
|
||||
{6'b00_0101, 3'b101}: if (RV32B) alu_operator_o = ALU_MAX; // Maximum
|
||||
|
|
|
@ -21,6 +21,7 @@ module ibex_ex_block #(
|
|||
input ibex_pkg::alu_op_e alu_operator_i,
|
||||
input logic [31:0] alu_operand_a_i,
|
||||
input logic [31:0] alu_operand_b_i,
|
||||
input logic alu_instr_first_cycle_i,
|
||||
|
||||
// Branch Target ALU
|
||||
// All of these signals are unusued when BranchTargetALU == 0
|
||||
|
@ -37,6 +38,11 @@ module ibex_ex_block #(
|
|||
input logic [31:0] multdiv_operand_b_i,
|
||||
input logic multdiv_ready_id_i,
|
||||
|
||||
// intermediate val reg
|
||||
output logic imd_val_we_o,
|
||||
output logic [33:0] imd_val_d_o,
|
||||
input logic [33:0] imd_val_q_i,
|
||||
|
||||
// Outputs
|
||||
output logic [31:0] alu_adder_result_ex_o, // to LSU
|
||||
output logic [31:0] result_ex_o,
|
||||
|
@ -55,6 +61,14 @@ module ibex_ex_block #(
|
|||
logic alu_cmp_result, alu_is_equal_result;
|
||||
logic multdiv_valid;
|
||||
logic multdiv_en;
|
||||
logic [31:0] alu_imd_val_d;
|
||||
logic alu_imd_val_we;
|
||||
logic [33:0] multdiv_imd_val_d;
|
||||
logic multdiv_imd_val_we;
|
||||
|
||||
// Intermediate Value Register Mux
|
||||
assign imd_val_d_o = multdiv_sel_i ? multdiv_imd_val_d : {2'b0, alu_imd_val_d};
|
||||
assign imd_val_we_o = multdiv_sel_i ? multdiv_imd_val_we : alu_imd_val_we;
|
||||
|
||||
/*
|
||||
The multdiv_i output is never selected if RV32M=0
|
||||
|
@ -95,19 +109,23 @@ module ibex_ex_block #(
|
|||
/////////
|
||||
|
||||
ibex_alu #(
|
||||
.RV32B( RV32B )
|
||||
) alu_i (
|
||||
.operator_i ( alu_operator_i ),
|
||||
.operand_a_i ( alu_operand_a_i ),
|
||||
.operand_b_i ( alu_operand_b_i ),
|
||||
.multdiv_operand_a_i ( multdiv_alu_operand_a ),
|
||||
.multdiv_operand_b_i ( multdiv_alu_operand_b ),
|
||||
.multdiv_sel_i ( multdiv_sel_i ),
|
||||
.adder_result_o ( alu_adder_result_ex_o ),
|
||||
.adder_result_ext_o ( alu_adder_result_ext ),
|
||||
.result_o ( alu_result ),
|
||||
.comparison_result_o ( alu_cmp_result ),
|
||||
.is_equal_result_o ( alu_is_equal_result )
|
||||
.RV32B(RV32B)
|
||||
) alu_i (
|
||||
.operator_i ( alu_operator_i ),
|
||||
.operand_a_i ( alu_operand_a_i ),
|
||||
.operand_b_i ( alu_operand_b_i ),
|
||||
.instr_first_cycle_i ( alu_instr_first_cycle_i ),
|
||||
.imd_val_q_i ( imd_val_q_i[31:0] ),
|
||||
.imd_val_we_o ( alu_imd_val_we ),
|
||||
.imd_val_d_o ( alu_imd_val_d ),
|
||||
.multdiv_operand_a_i ( multdiv_alu_operand_a ),
|
||||
.multdiv_operand_b_i ( multdiv_alu_operand_b ),
|
||||
.multdiv_sel_i ( multdiv_sel_i ),
|
||||
.adder_result_o ( alu_adder_result_ex_o ),
|
||||
.adder_result_ext_o ( alu_adder_result_ext ),
|
||||
.result_o ( alu_result ),
|
||||
.comparison_result_o ( alu_cmp_result ),
|
||||
.is_equal_result_o ( alu_is_equal_result )
|
||||
);
|
||||
|
||||
////////////////
|
||||
|
@ -134,50 +152,56 @@ module ibex_ex_block #(
|
|||
.multdiv_result_o ( multdiv_result )
|
||||
);
|
||||
end else if (MultiplierImplementation == "fast") begin : gen_multdiv_fast
|
||||
ibex_multdiv_fast #(
|
||||
.SingleCycleMultiply(0)
|
||||
) multdiv_i (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.mult_en_i ( mult_en_i ),
|
||||
.div_en_i ( div_en_i ),
|
||||
.operator_i ( multdiv_operator_i ),
|
||||
.signed_mode_i ( multdiv_signed_mode_i ),
|
||||
.op_a_i ( multdiv_operand_a_i ),
|
||||
.op_b_i ( multdiv_operand_b_i ),
|
||||
.alu_operand_a_o ( multdiv_alu_operand_a ),
|
||||
.alu_operand_b_o ( multdiv_alu_operand_b ),
|
||||
.alu_adder_ext_i ( alu_adder_result_ext ),
|
||||
.alu_adder_i ( alu_adder_result_ex_o ),
|
||||
.equal_to_zero ( alu_is_equal_result ),
|
||||
.multdiv_ready_id_i ( multdiv_ready_id_i ),
|
||||
.valid_o ( multdiv_valid ),
|
||||
.multdiv_result_o ( multdiv_result )
|
||||
ibex_multdiv_fast # (
|
||||
.SingleCycleMultiply (0)
|
||||
) multdiv_i (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.mult_en_i ( mult_en_i ),
|
||||
.div_en_i ( div_en_i ),
|
||||
.operator_i ( multdiv_operator_i ),
|
||||
.signed_mode_i ( multdiv_signed_mode_i ),
|
||||
.op_a_i ( multdiv_operand_a_i ),
|
||||
.op_b_i ( multdiv_operand_b_i ),
|
||||
.alu_operand_a_o ( multdiv_alu_operand_a ),
|
||||
.alu_operand_b_o ( multdiv_alu_operand_b ),
|
||||
.alu_adder_ext_i ( alu_adder_result_ext ),
|
||||
.alu_adder_i ( alu_adder_result_ex_o ),
|
||||
.equal_to_zero ( alu_is_equal_result ),
|
||||
.imd_val_q_i ( imd_val_q_i ),
|
||||
.imd_val_d_o ( multdiv_imd_val_d ),
|
||||
.imd_val_we_o ( multdiv_imd_val_we ),
|
||||
.multdiv_ready_id_i ( multdiv_ready_id_i ),
|
||||
.valid_o ( multdiv_valid ),
|
||||
.multdiv_result_o ( multdiv_result )
|
||||
);
|
||||
end else if (MultiplierImplementation == "single-cycle") begin: gen_multdiv_single_cycle
|
||||
ibex_multdiv_fast #(
|
||||
.SingleCycleMultiply(1)
|
||||
) multdiv_i (
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.mult_en_i ( mult_en_i ),
|
||||
.div_en_i ( div_en_i ),
|
||||
.operator_i ( multdiv_operator_i ),
|
||||
.signed_mode_i ( multdiv_signed_mode_i ),
|
||||
.op_a_i ( multdiv_operand_a_i ),
|
||||
.op_b_i ( multdiv_operand_b_i ),
|
||||
.alu_operand_a_o ( multdiv_alu_operand_a ),
|
||||
.alu_operand_b_o ( multdiv_alu_operand_b ),
|
||||
.alu_adder_ext_i ( alu_adder_result_ext ),
|
||||
.alu_adder_i ( alu_adder_result_ex_o ),
|
||||
.equal_to_zero ( alu_is_equal_result ),
|
||||
.multdiv_ready_id_i ( multdiv_ready_id_i ),
|
||||
.valid_o ( multdiv_valid ),
|
||||
.multdiv_result_o ( multdiv_result )
|
||||
.clk_i ( clk_i ),
|
||||
.rst_ni ( rst_ni ),
|
||||
.mult_en_i ( mult_en_i ),
|
||||
.div_en_i ( div_en_i ),
|
||||
.operator_i ( multdiv_operator_i ),
|
||||
.signed_mode_i ( multdiv_signed_mode_i ),
|
||||
.op_a_i ( multdiv_operand_a_i ),
|
||||
.op_b_i ( multdiv_operand_b_i ),
|
||||
.alu_operand_a_o ( multdiv_alu_operand_a ),
|
||||
.alu_operand_b_o ( multdiv_alu_operand_b ),
|
||||
.alu_adder_ext_i ( alu_adder_result_ext ),
|
||||
.alu_adder_i ( alu_adder_result_ex_o ),
|
||||
.equal_to_zero ( alu_is_equal_result ),
|
||||
.imd_val_q_i ( imd_val_q_i ),
|
||||
.imd_val_d_o ( multdiv_imd_val_d ),
|
||||
.imd_val_we_o ( multdiv_imd_val_we ),
|
||||
.multdiv_ready_id_i ( multdiv_ready_id_i ),
|
||||
.valid_o ( multdiv_valid ),
|
||||
.multdiv_result_o ( multdiv_result )
|
||||
);
|
||||
end
|
||||
|
||||
// ALU output valid in same cycle, multiplier/divider may require multiple cycles
|
||||
assign ex_valid_o = multdiv_en ? multdiv_valid : 1'b1;
|
||||
assign ex_valid_o = multdiv_en ? multdiv_valid : !alu_imd_val_we;
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -68,6 +68,11 @@ module ibex_id_stage #(
|
|||
output logic [31:0] alu_operand_a_ex_o,
|
||||
output logic [31:0] alu_operand_b_ex_o,
|
||||
|
||||
// Multicycle Operation Stage Register
|
||||
input logic imd_val_we_ex_i,
|
||||
input logic [33:0] imd_val_d_ex_i,
|
||||
output logic [33:0] imd_val_q_ex_o,
|
||||
|
||||
// Branch target ALU
|
||||
output logic [31:0] bt_a_operand_o,
|
||||
output logic [31:0] bt_b_operand_o,
|
||||
|
@ -227,6 +232,10 @@ module ibex_id_stage #(
|
|||
alu_op_e alu_operator;
|
||||
op_a_sel_e alu_op_a_mux_sel, alu_op_a_mux_sel_dec;
|
||||
op_b_sel_e alu_op_b_mux_sel, alu_op_b_mux_sel_dec;
|
||||
logic alu_multicycle_dec;
|
||||
logic stall_alu;
|
||||
|
||||
logic [33:0] imd_val_q;
|
||||
|
||||
op_a_sel_e bt_a_mux_sel;
|
||||
imm_b_sel_e bt_b_mux_sel;
|
||||
|
@ -341,6 +350,20 @@ module ibex_id_stage #(
|
|||
// ALU MUX for Operand B
|
||||
assign alu_operand_b = (alu_op_b_mux_sel == OP_B_IMM) ? imm_b : rf_rdata_b_fwd;
|
||||
|
||||
/////////////////////////////////////////
|
||||
// Multicycle Operation Stage Register //
|
||||
/////////////////////////////////////////
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin : intermediate_val_reg
|
||||
if (!rst_ni) begin
|
||||
imd_val_q <= '0;
|
||||
end else if (imd_val_we_ex_i) begin
|
||||
imd_val_q <= imd_val_d_ex_i;
|
||||
end
|
||||
end
|
||||
|
||||
assign imd_val_q_ex_o = imd_val_q;
|
||||
|
||||
///////////////////////
|
||||
// Register File MUX //
|
||||
///////////////////////
|
||||
|
@ -414,6 +437,7 @@ module ibex_id_stage #(
|
|||
.alu_operator_o ( alu_operator ),
|
||||
.alu_op_a_mux_sel_o ( alu_op_a_mux_sel_dec ),
|
||||
.alu_op_b_mux_sel_o ( alu_op_b_mux_sel_dec ),
|
||||
.alu_multicycle_o ( alu_multicycle_dec ),
|
||||
|
||||
// MULT & DIV
|
||||
.mult_en_o ( mult_en_dec ),
|
||||
|
@ -427,10 +451,10 @@ module ibex_id_stage #(
|
|||
.csr_op_o ( csr_op_o ),
|
||||
|
||||
// LSU
|
||||
.data_req_o ( lsu_req_dec ),
|
||||
.data_we_o ( lsu_we ),
|
||||
.data_type_o ( lsu_type ),
|
||||
.data_sign_extension_o ( lsu_sign_ext ),
|
||||
.data_req_o ( lsu_req_dec ),
|
||||
.data_we_o ( lsu_we ),
|
||||
.data_type_o ( lsu_type ),
|
||||
.data_sign_extension_o ( lsu_sign_ext ),
|
||||
|
||||
// jump/branches
|
||||
.jump_in_dec_o ( jump_in_dec ),
|
||||
|
@ -666,6 +690,7 @@ module ibex_id_stage #(
|
|||
stall_multdiv = 1'b0;
|
||||
stall_jump = 1'b0;
|
||||
stall_branch = 1'b0;
|
||||
stall_alu = 1'b0;
|
||||
branch_set_d = 1'b0;
|
||||
perf_branch_o = 1'b0;
|
||||
|
||||
|
@ -709,6 +734,11 @@ module ibex_id_stage #(
|
|||
id_fsm_d = BranchTargetALU ? FIRST_CYCLE : MULTI_CYCLE;
|
||||
stall_jump = ~BranchTargetALU;
|
||||
end
|
||||
alu_multicycle_dec: begin
|
||||
stall_alu = 1'b1;
|
||||
id_fsm_d = MULTI_CYCLE;
|
||||
rf_we_raw = 1'b0;
|
||||
end
|
||||
default: begin
|
||||
id_fsm_d = FIRST_CYCLE;
|
||||
end
|
||||
|
@ -742,7 +772,8 @@ module ibex_id_stage #(
|
|||
`ASSERT(StallIDIfMulticycle, (id_fsm_q == FIRST_CYCLE) & (id_fsm_d == MULTI_CYCLE) |-> stall_id)
|
||||
|
||||
// Stall ID/EX stage for reason that relates to instruction in ID/EX
|
||||
assign stall_id = stall_ld_hz | stall_mem | stall_multdiv | stall_jump | stall_branch;
|
||||
assign stall_id = stall_ld_hz | stall_mem | stall_multdiv | stall_jump | stall_branch |
|
||||
stall_alu;
|
||||
|
||||
assign instr_done = ~stall_id & ~flush_id & instr_executing;
|
||||
|
||||
|
@ -756,6 +787,7 @@ module ibex_id_stage #(
|
|||
// first cycle if it is stalled.
|
||||
assign instr_first_cycle = instr_valid_i & (id_fsm_q == FIRST_CYCLE);
|
||||
// Used by RVFI to know when to capture register read data
|
||||
// Used by ALU to access RS3 if ternary instruction.
|
||||
assign instr_first_cycle_id_o = instr_first_cycle;
|
||||
|
||||
if (WritebackStage) begin : gen_stall_mem
|
||||
|
|
|
@ -32,6 +32,10 @@ module ibex_multdiv_fast #(
|
|||
output logic [32:0] alu_operand_a_o,
|
||||
output logic [32:0] alu_operand_b_o,
|
||||
|
||||
input logic [33:0] imd_val_q_i,
|
||||
output logic [33:0] imd_val_d_o,
|
||||
output logic imd_val_we_o,
|
||||
|
||||
input logic multdiv_ready_id_i,
|
||||
|
||||
output logic [31:0] multdiv_result_o,
|
||||
|
@ -48,8 +52,6 @@ module ibex_multdiv_fast #(
|
|||
logic mult_valid;
|
||||
logic signed_mult;
|
||||
|
||||
// Flop used for intermediate value holding during div & mul calculation
|
||||
logic [33:0] intermediate_val_q, intermediate_val_d;
|
||||
// Results that become intermediate value depending on whether mul or div is being calculated
|
||||
logic [33:0] mac_res_d, op_remainder_d;
|
||||
// Raw output of MAC calculation
|
||||
|
@ -103,13 +105,6 @@ module ibex_multdiv_fast #(
|
|||
end
|
||||
end
|
||||
|
||||
always_ff @(posedge clk_i or negedge rst_ni) begin
|
||||
if (!rst_ni) begin
|
||||
intermediate_val_q <= '0;
|
||||
end else if (multdiv_en) begin
|
||||
intermediate_val_q <= intermediate_val_d;
|
||||
end
|
||||
end
|
||||
|
||||
`ASSERT_KNOWN(DivEnKnown, div_en_internal);
|
||||
`ASSERT_KNOWN(MultEnKnown, mult_en_internal);
|
||||
|
@ -117,10 +112,11 @@ module ibex_multdiv_fast #(
|
|||
|
||||
assign multdiv_en = mult_en_internal | div_en_internal;
|
||||
|
||||
assign intermediate_val_d = div_en_i ? op_remainder_d : mac_res_d;
|
||||
assign imd_val_d_o = div_en_i ? op_remainder_d : mac_res_d;
|
||||
assign imd_val_we_o = multdiv_en;
|
||||
|
||||
assign signed_mult = (signed_mode_i != 2'b00);
|
||||
assign multdiv_result_o = div_en_i ? intermediate_val_q[31:0] : mac_res_d[31:0];
|
||||
assign multdiv_result_o = div_en_i ? imd_val_q_i[31:0] : mac_res_d[31:0];
|
||||
|
||||
// The single cycle multiplier uses three 17 bit multipliers to compute MUL instructions in a
|
||||
// single cycle and MULH instructions in two cycles.
|
||||
|
@ -166,8 +162,8 @@ module ibex_multdiv_fast #(
|
|||
assign mult2_op_b = op_b_i[`OP_H];
|
||||
|
||||
// used in MULH
|
||||
assign accum[17:0] = intermediate_val_q[33:16];
|
||||
assign accum[33:18] = {16{signed_mult & intermediate_val_q[33]}};
|
||||
assign accum[17:0] = imd_val_q_i[33:16];
|
||||
assign accum[33:18] = {16{signed_mult & imd_val_q_i[33]}};
|
||||
|
||||
always_comb begin
|
||||
// Default values == MULL
|
||||
|
@ -264,7 +260,7 @@ module ibex_multdiv_fast #(
|
|||
mult_op_b = op_b_i[`OP_L];
|
||||
sign_a = 1'b0;
|
||||
sign_b = 1'b0;
|
||||
accum = intermediate_val_q;
|
||||
accum = imd_val_q_i;
|
||||
mac_res_d = mac_res;
|
||||
mult_state_d = mult_state_q;
|
||||
mult_valid = 1'b0;
|
||||
|
@ -289,10 +285,10 @@ module ibex_multdiv_fast #(
|
|||
mult_op_b = op_b_i[`OP_H];
|
||||
sign_a = 1'b0;
|
||||
sign_b = signed_mode_i[1] & op_b_i[31];
|
||||
// result of AL*BL (in intermediate_val_q) always unsigned with no carry, so carries_q always 00
|
||||
accum = {18'b0, intermediate_val_q[31:16]};
|
||||
// result of AL*BL (in imd_val_q_i) always unsigned with no carry, so carries_q always 00
|
||||
accum = {18'b0, imd_val_q_i[31:16]};
|
||||
if (operator_i == MD_OP_MULL) begin
|
||||
mac_res_d = {2'b0, mac_res[`OP_L], intermediate_val_q[`OP_L]};
|
||||
mac_res_d = {2'b0, mac_res[`OP_L], imd_val_q_i[`OP_L]};
|
||||
end else begin
|
||||
// MD_OP_MULH
|
||||
mac_res_d = mac_res;
|
||||
|
@ -307,15 +303,15 @@ module ibex_multdiv_fast #(
|
|||
sign_a = signed_mode_i[0] & op_a_i[31];
|
||||
sign_b = 1'b0;
|
||||
if (operator_i == MD_OP_MULL) begin
|
||||
accum = {18'b0, intermediate_val_q[31:16]};
|
||||
mac_res_d = {2'b0, mac_res[15:0], intermediate_val_q[15:0]};
|
||||
accum = {18'b0, imd_val_q_i[31:16]};
|
||||
mac_res_d = {2'b0, mac_res[15:0], imd_val_q_i[15:0]};
|
||||
mult_valid = 1'b1;
|
||||
|
||||
// Note no state transition will occur if mult_hold is set
|
||||
mult_state_d = ALBL;
|
||||
mult_hold = ~multdiv_ready_id_i;
|
||||
end else begin
|
||||
accum = intermediate_val_q;
|
||||
accum = imd_val_q_i;
|
||||
mac_res_d = mac_res;
|
||||
mult_state_d = AHBH;
|
||||
end
|
||||
|
@ -328,8 +324,8 @@ module ibex_multdiv_fast #(
|
|||
mult_op_b = op_b_i[`OP_H];
|
||||
sign_a = signed_mode_i[0] & op_a_i[31];
|
||||
sign_b = signed_mode_i[1] & op_b_i[31];
|
||||
accum[17: 0] = intermediate_val_q[33:16];
|
||||
accum[33:18] = {16{signed_mult & intermediate_val_q[33]}};
|
||||
accum[17: 0] = imd_val_q_i[33:16];
|
||||
accum[33:18] = {16{signed_mult & imd_val_q_i[33]}};
|
||||
// result of AH*BL is not signed only if signed_mode_i == 2'b00
|
||||
mac_res_d = mac_res;
|
||||
mult_valid = 1'b1;
|
||||
|
@ -362,7 +358,7 @@ module ibex_multdiv_fast #(
|
|||
// Divider
|
||||
assign res_adder_h = alu_adder_ext_i[33:1];
|
||||
|
||||
assign next_remainder = is_greater_equal ? res_adder_h[31:0] : intermediate_val_q[31:0];
|
||||
assign next_remainder = is_greater_equal ? res_adder_h[31:0] : imd_val_q_i[31:0];
|
||||
assign next_quotient = is_greater_equal ? {1'b0, op_quotient_q} | {1'b0, one_shift} :
|
||||
{1'b0, op_quotient_q};
|
||||
|
||||
|
@ -372,10 +368,10 @@ module ibex_multdiv_fast #(
|
|||
// Remainder - Divisor. If Remainder - Divisor >= 0, is_greater_equal is equal to 1,
|
||||
// the next Remainder is Remainder - Divisor contained in res_adder_h and the
|
||||
always_comb begin
|
||||
if ((intermediate_val_q[31] ^ op_denominator_q[31]) == 1'b0) begin
|
||||
if ((imd_val_q_i[31] ^ op_denominator_q[31]) == 1'b0) begin
|
||||
is_greater_equal = (res_adder_h[31] == 1'b0);
|
||||
end else begin
|
||||
is_greater_equal = intermediate_val_q[31];
|
||||
is_greater_equal = imd_val_q_i[31];
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -387,7 +383,7 @@ module ibex_multdiv_fast #(
|
|||
|
||||
always_comb begin
|
||||
div_counter_d = div_counter_q - 5'h1;
|
||||
op_remainder_d = intermediate_val_q;
|
||||
op_remainder_d = imd_val_q_i;
|
||||
op_quotient_d = op_quotient_q;
|
||||
md_state_d = md_state_q;
|
||||
op_numerator_d = op_numerator_q;
|
||||
|
@ -445,13 +441,13 @@ module ibex_multdiv_fast #(
|
|||
op_quotient_d = next_quotient[31:0];
|
||||
md_state_d = (div_counter_q == 5'd1) ? MD_LAST : MD_COMP;
|
||||
// Division
|
||||
alu_operand_a_o = {intermediate_val_q[31:0], 1'b1}; // it contains the remainder
|
||||
alu_operand_a_o = {imd_val_q_i[31:0], 1'b1}; // it contains the remainder
|
||||
alu_operand_b_o = {~op_denominator_q[31:0], 1'b1}; // -denominator two's compliment
|
||||
end
|
||||
|
||||
MD_LAST: begin
|
||||
if (operator_i == MD_OP_DIV) begin
|
||||
// this time we save the quotient in op_remainder_d (i.e. intermediate_val_q) since
|
||||
// this time we save the quotient in op_remainder_d (i.e. imd_val_q_i) since
|
||||
// we do not need anymore the remainder
|
||||
op_remainder_d = {1'b0, next_quotient};
|
||||
end else begin
|
||||
|
@ -459,7 +455,7 @@ module ibex_multdiv_fast #(
|
|||
op_remainder_d = {2'b0, next_remainder[31:0]};
|
||||
end
|
||||
// Division
|
||||
alu_operand_a_o = {intermediate_val_q[31:0], 1'b1}; // it contains the remainder
|
||||
alu_operand_a_o = {imd_val_q_i[31:0], 1'b1}; // it contains the remainder
|
||||
alu_operand_b_o = {~op_denominator_q[31:0], 1'b1}; // -denominator two's compliment
|
||||
|
||||
md_state_d = MD_CHANGE_SIGN;
|
||||
|
@ -468,13 +464,13 @@ module ibex_multdiv_fast #(
|
|||
MD_CHANGE_SIGN: begin
|
||||
md_state_d = MD_FINISH;
|
||||
if (operator_i == MD_OP_DIV) begin
|
||||
op_remainder_d = (div_change_sign) ? {2'h0, alu_adder_i} : intermediate_val_q;
|
||||
op_remainder_d = (div_change_sign) ? {2'h0, alu_adder_i} : imd_val_q_i;
|
||||
end else begin
|
||||
op_remainder_d = (rem_change_sign) ? {2'h0, alu_adder_i} : intermediate_val_q;
|
||||
op_remainder_d = (rem_change_sign) ? {2'h0, alu_adder_i} : imd_val_q_i;
|
||||
end
|
||||
// ABS(Quotient) = 0 - Quotient (or Remainder)
|
||||
alu_operand_a_o = {32'h0 , 1'b1};
|
||||
alu_operand_b_o = {~intermediate_val_q[31:0], 1'b1};
|
||||
alu_operand_b_o = {~imd_val_q_i[31:0], 1'b1};
|
||||
end
|
||||
|
||||
MD_FINISH: begin
|
||||
|
|
|
@ -86,7 +86,14 @@ typedef enum logic [5:0] {
|
|||
|
||||
// Set lower than
|
||||
ALU_SLT,
|
||||
ALU_SLTU
|
||||
ALU_SLTU,
|
||||
|
||||
// Ternary Bitmanip Operations
|
||||
// RV32B
|
||||
ALU_CMOV,
|
||||
ALU_CMIX,
|
||||
ALU_FSL,
|
||||
ALU_FSR
|
||||
} alu_op_e;
|
||||
|
||||
typedef enum logic [1:0] {
|
||||
|
|
|
@ -48,8 +48,10 @@ module ibex_tracer (
|
|||
input logic [ 1:0] rvfi_mode,
|
||||
input logic [ 4:0] rvfi_rs1_addr,
|
||||
input logic [ 4:0] rvfi_rs2_addr,
|
||||
input logic [ 4:0] rvfi_rs3_addr,
|
||||
input logic [31:0] rvfi_rs1_rdata,
|
||||
input logic [31:0] rvfi_rs2_rdata,
|
||||
input logic [31:0] rvfi_rs3_rdata,
|
||||
input logic [ 4:0] rvfi_rd_addr,
|
||||
input logic [31:0] rvfi_rd_wdata,
|
||||
input logic [31:0] rvfi_pc_rdata,
|
||||
|
@ -83,9 +85,10 @@ module ibex_tracer (
|
|||
// Data items accessed during this instruction
|
||||
localparam RS1 = (1 << 0);
|
||||
localparam RS2 = (1 << 1);
|
||||
localparam RD = (1 << 2);
|
||||
localparam MEM = (1 << 3);
|
||||
logic [3:0] data_accessed;
|
||||
localparam RS3 = (1 << 2);
|
||||
localparam RD = (1 << 3);
|
||||
localparam MEM = (1 << 4);
|
||||
logic [4:0] data_accessed;
|
||||
|
||||
function automatic void printbuffer_dumpline();
|
||||
string rvfi_insn_str;
|
||||
|
@ -116,6 +119,9 @@ module ibex_tracer (
|
|||
if ((data_accessed & RS2) != 0) begin
|
||||
$fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs2_addr), rvfi_rs2_rdata);
|
||||
end
|
||||
if ((data_accessed & RS3) != 0) begin
|
||||
$fwrite(file_handle, " %s:0x%08x", reg_addr_to_str(rvfi_rs3_addr), rvfi_rs3_rdata);
|
||||
end
|
||||
if ((data_accessed & RD) != 0) begin
|
||||
$fwrite(file_handle, " %s=0x%08x", reg_addr_to_str(rvfi_rd_addr), rvfi_rd_wdata);
|
||||
end
|
||||
|
@ -396,7 +402,8 @@ module ibex_tracer (
|
|||
|
||||
function automatic void decode_r_insn(input string mnemonic);
|
||||
data_accessed = RS1 | RS2 | RD;
|
||||
decoded_str = $sformatf("%s\tx%0d,x%0d,x%0d", mnemonic, rvfi_rd_addr, rvfi_rs1_addr, rvfi_rs2_addr);
|
||||
decoded_str = $sformatf("%s\tx%0d,x%0d,x%0d", mnemonic, rvfi_rd_addr, rvfi_rs1_addr,
|
||||
rvfi_rs2_addr);
|
||||
endfunction
|
||||
|
||||
function automatic void decode_r1_insn(input string mnemonic);
|
||||
|
@ -404,6 +411,18 @@ module ibex_tracer (
|
|||
decoded_str = $sformatf("%s\tx%0d,x%0d", mnemonic, rvfi_rd_addr, rvfi_rs1_addr);
|
||||
endfunction
|
||||
|
||||
function automatic void decode_r_cmixcmov_insn(input string mnemonic);
|
||||
data_accessed = RS1 | RS2 | RS3 | RD;
|
||||
decoded_str = $sformatf("%s\tx%0d,x%0d,x%0d,x%0d", mnemonic, rvfi_rd_addr, rvfi_rs2_addr,
|
||||
rvfi_rs1_addr, rvfi_rs3_addr);
|
||||
endfunction
|
||||
|
||||
function automatic void decode_r_funnelshift_insn(input string mnemonic);
|
||||
data_accessed = RS1 | RS2 | RS3 | RD;
|
||||
decoded_str = $sformatf("%s\tx%0d,x%0d,x%0d,x%0d", mnemonic, rvfi_rd_addr, rvfi_rs1_addr,
|
||||
rvfi_rs3_addr, rvfi_rs2_addr);
|
||||
endfunction
|
||||
|
||||
function automatic void decode_i_insn(input string mnemonic);
|
||||
data_accessed = RS1 | RD;
|
||||
decoded_str = $sformatf("%s\tx%0d,x%0d,%0d", mnemonic, rvfi_rd_addr, rvfi_rs1_addr,
|
||||
|
@ -418,6 +437,15 @@ module ibex_tracer (
|
|||
decoded_str = $sformatf("%s\tx%0d,x%0d,0x%0x", mnemonic, rvfi_rd_addr, rvfi_rs1_addr, shamt);
|
||||
endfunction
|
||||
|
||||
function automatic void decode_i_funnelshift_insn( input string mnemonic);
|
||||
// fsri
|
||||
logic [5:0] shamt;
|
||||
shamt = {rvfi_insn[25:20]};
|
||||
data_accessed = RS1 | RS3;
|
||||
decoded_str = $sformatf("%s\tx%0d,x%0d,x%0d,0x%0x", mnemonic, rvfi_rd_addr, rvfi_rs1_addr,
|
||||
rvfi_rs3_addr, shamt);
|
||||
endfunction
|
||||
|
||||
function automatic void decode_i_jalr_insn(input string mnemonic);
|
||||
// JALR
|
||||
data_accessed = RS1 | RD;
|
||||
|
@ -709,7 +737,7 @@ module ibex_tracer (
|
|||
|
||||
always_comb begin
|
||||
decoded_str = "";
|
||||
data_accessed = 4'h0;
|
||||
data_accessed = 5'h0;
|
||||
insn_is_compressed = 0;
|
||||
|
||||
// Check for compressed instructions
|
||||
|
@ -871,6 +899,12 @@ module ibex_tracer (
|
|||
INSN_PCNT: decode_r1_insn("pcnt");
|
||||
INSN_REV: decode_r1_insn("rev");
|
||||
INSN_REV8: decode_r1_insn("rev8");
|
||||
// TERNARY BITMABIP INSTR
|
||||
INSN_CMIX: decode_r_cmixcmov_insn("cmix");
|
||||
INSN_CMOV: decode_r_cmixcmov_insn("cmov");
|
||||
INSN_FSR: decode_r_funnelshift_insn("fsr");
|
||||
INSN_FSL: decode_r_funnelshift_insn("fsl");
|
||||
INSN_FSRI: decode_i_funnelshift_insn("fsri");
|
||||
|
||||
default: decode_mnemonic("INVALID");
|
||||
endcase
|
||||
|
|
|
@ -72,8 +72,8 @@ parameter logic [31:0] INSN_PMULHSU = { 7'b0000001, 10'b?, 3'b010, 5'b?, {OPCODE
|
|||
parameter logic [31:0] INSN_PMULHU = { 7'b0000001, 10'b?, 3'b011, 5'b?, {OPCODE_OP} };
|
||||
|
||||
// RV32B
|
||||
// ZBB
|
||||
// OPIMM
|
||||
// ZBB
|
||||
parameter logic [31:0] INSN_SLOI = { 7'b00100 , 10'b?, 3'b001, 5'b?, {OPCODE_OP_IMM} };
|
||||
parameter logic [31:0] INSN_SROI = { 7'b0010000 , 10'b?, 3'b101, 5'b?, {OPCODE_OP_IMM} };
|
||||
parameter logic [31:0] INSN_RORI = { 7'b0110000 , 10'b?, 3'b101, 5'b?, {OPCODE_OP_IMM} };
|
||||
|
@ -83,22 +83,30 @@ parameter logic [31:0] INSN_PCNT = { 12'b011000000010, 5'b? , 3'b001, 5'b?, {OPC
|
|||
parameter logic [31:0] INSN_REV = { 12'b011010011111, 5'b? , 3'b101, 5'b?, {OPCODE_OP_IMM} };
|
||||
parameter logic [31:0] INSN_REV8 = { 12'b011010011000, 5'b? , 3'b101, 5'b?, {OPCODE_OP_IMM} };
|
||||
parameter logic [31:0] INSN_ORCB = { 12'b001010000111, 5'b? , 3'b101, 5'b?, {OPCODE_OP_IMM} };
|
||||
// ZBT
|
||||
parameter logic [31:0] INSN_FSRI = { 5'b?, 1'b1, 11'b?, 3'b101, 5'b?, {OPCODE_OP_IMM} };
|
||||
|
||||
// OP
|
||||
parameter logic [31:0] INSN_SLO = { 7'b0010000, 10'b?, 3'b001, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_SRO = { 7'b0010000, 10'b?, 3'b101, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_ROL = { 7'b0110000, 10'b?, 3'b001, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_ROR = { 7'b0110000, 10'b?, 3'b101, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_MIN = { 7'b0000101, 10'b?, 3'b100, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_MAX = { 7'b0000101, 10'b?, 3'b101, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_MINU = { 7'b0000101, 10'b?, 3'b110, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_MAXU = { 7'b0000101, 10'b?, 3'b111, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_XNOR = { 7'b0100000, 10'b?, 3'b100, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_ORN = { 7'b0100000, 10'b?, 3'b110, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_ANDN = { 7'b0100000, 10'b?, 3'b111, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_PACK = { 7'b0000100, 10'b?, 3'b100, 5'b?, {OPCODE_OP} };
|
||||
// ZBB
|
||||
parameter logic [31:0] INSN_SLO = { 7'b0010000, 10'b?, 3'b001, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_SRO = { 7'b0010000, 10'b?, 3'b101, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_ROL = { 7'b0110000, 10'b?, 3'b001, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_ROR = { 7'b0110000, 10'b?, 3'b101, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_MIN = { 7'b0000101, 10'b?, 3'b100, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_MAX = { 7'b0000101, 10'b?, 3'b101, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_MINU = { 7'b0000101, 10'b?, 3'b110, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_MAXU = { 7'b0000101, 10'b?, 3'b111, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_XNOR = { 7'b0100000, 10'b?, 3'b100, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_ORN = { 7'b0100000, 10'b?, 3'b110, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_ANDN = { 7'b0100000, 10'b?, 3'b111, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_PACK = { 7'b0000100, 10'b?, 3'b100, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_PACKU = { 7'b0100100, 10'b?, 3'b100, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_PACKH = { 7'b0000100, 10'b?, 3'b111, 5'b?, {OPCODE_OP} };
|
||||
// ZBT
|
||||
parameter logic [31:0] INSN_CMIX = {5'b?, 2'b11, 10'b?, 3'b001, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_CMOV = {5'b?, 2'b11, 10'b?, 3'b101, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_FSL = {5'b?, 2'b10, 10'b?, 3'b001, 5'b?, {OPCODE_OP} };
|
||||
parameter logic [31:0] INSN_FSR = {5'b?, 2'b10, 10'b?, 3'b101, 5'b?, {OPCODE_OP} };
|
||||
|
||||
// LOAD & STORE
|
||||
parameter logic [31:0] INSN_LOAD = {25'b?, {OPCODE_LOAD } };
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue