Added support for dot product

This commit is contained in:
Andreas Traber 2016-03-24 17:55:20 +01:00
parent aa28fac157
commit 68afee79a6
8 changed files with 363 additions and 98 deletions

View file

@ -62,11 +62,13 @@ module riscv_decoder
output logic [1:0] regc_mux_o, // register c selection: S3, RD or 0
// MUL related control signals
output logic mult_en_o, // perform multiplication
output logic mult_mac_en_o, // accumulate multiplication result
output logic [1:0] mult_sel_subword_o, // Select subwords for 16x16 bit of multiplier
output logic [1:0] mult_signed_mode_o, // Multiplication in signed mode
output logic mult_vec_mode_o, // selects between 32 bit and 16 bit modes
output logic [2:0] mult_operator_o, // Multiplication operation selection
output logic mult_int_en_o, // perform integer multiplication
output logic mult_dot_en_o, // perform dot multiplication
output logic [0:0] mult_imm_mux_o, // Multiplication immediate mux selector
output logic mult_sel_subword_o, // Select subwords for 16x16 bit of multiplier
output logic mult_signed_mode_o, // Multiplication in signed mode
output logic [1:0] mult_dot_signed_o, // Dot product in signed mode
// register file related signals
output logic regfile_mem_we_o, // write enable for regfile
@ -110,8 +112,6 @@ module riscv_decoder
logic [1:0] jump_in_id;
logic mult_en;
logic mult_mac_en;
logic [1:0] csr_op;
@ -139,11 +139,13 @@ module riscv_decoder
imm_a_mux_sel_o = `IMMA_ZERO;
imm_b_mux_sel_o = `IMMB_I;
mult_en = 1'b0;
mult_signed_mode_o = 2'b00;
mult_sel_subword_o = 2'b00;
mult_mac_en = 1'b0;
mult_vec_mode_o = 1'b0;
mult_operator_o = `MUL_I;
mult_int_en_o = 1'b0;
mult_dot_en_o = 1'b0;
mult_imm_mux_o = `MIMM_ZERO;
mult_signed_mode_o = 1'b0;
mult_sel_subword_o = 1'b0;
mult_dot_signed_o = 2'b00;
regfile_mem_we = 1'b0;
regfile_alu_we = 1'b0;
@ -479,12 +481,22 @@ module riscv_decoder
{6'b10_0000, 3'b101}: alu_operator_o = `ALU_SRA; // Shift Right Arithmetic
// supported RV32M instructions
{6'b00_0001, 3'b000}: mult_en = 1'b1; // Multiplication
{6'b00_0001, 3'b001}: begin // MAC
regc_used_o = 1'b1;
regc_mux_o = `REGC_RD;
mult_en = 1'b1;
mult_mac_en = 1'b1;
{6'b00_0001, 3'b000}: begin // p.mul
mult_int_en_o = 1'b1;
mult_operator_o = `MUL_MAC32;
regc_mux_o = `REGC_ZERO;
end
{6'b00_0001, 3'b001}: begin // p.mac
regc_used_o = 1'b1;
regc_mux_o = `REGC_RD;
mult_int_en_o = 1'b1;
mult_operator_o = `MUL_MAC32;
end
{6'b00_0001, 3'b010}: begin // p.msu
regc_used_o = 1'b1;
regc_mux_o = `REGC_RD;
mult_int_en_o = 1'b1;
mult_operator_o = `MUL_MSU32;
end
{6'b00_0001, 3'b100}: begin // div
alu_op_a_mux_sel_o = `OP_A_REGB_OR_FWD;
@ -573,22 +585,32 @@ module riscv_decoder
case (instr_rdata_i[13:12])
2'b00: begin // multiply with subword selection
mult_vec_mode_o = 1'b1;
mult_sel_subword_o = {2{instr_rdata_i[30]}};
mult_signed_mode_o = {2{instr_rdata_i[31]}};
mult_sel_subword_o = instr_rdata_i[30];
mult_signed_mode_o = instr_rdata_i[31];
mult_en = 1'b1;
mult_imm_mux_o = `MIMM_S3;
regc_mux_o = `REGC_ZERO;
mult_int_en_o = 1'b1;
if (instr_rdata_i[14])
mult_operator_o = `MUL_IR;
else
mult_operator_o = `MUL_I;
end
2'b01: begin // MAC with subword selection
regc_used_o = 1'b1;
regc_mux_o = `REGC_RD;
mult_vec_mode_o = 1'b1;
mult_sel_subword_o = {2{instr_rdata_i[30]}};
mult_signed_mode_o = {2{instr_rdata_i[31]}};
mult_sel_subword_o = instr_rdata_i[30];
mult_signed_mode_o = instr_rdata_i[31];
mult_en = 1'b1;
mult_mac_en = 1'b1;
regc_used_o = 1'b1;
regc_mux_o = `REGC_RD;
mult_imm_mux_o = `MIMM_S3;
mult_int_en_o = 1'b1;
if (instr_rdata_i[14])
mult_operator_o = `MUL_IR;
else
mult_operator_o = `MUL_I;
end
2'b10: begin // add with normalization and rounding
@ -632,10 +654,13 @@ module riscv_decoder
imm_b_mux_sel_o = `IMMB_VS;
// vector size
if (instr_rdata_i[12])
alu_vec_mode_o = `VEC_MODE8;
else
if (instr_rdata_i[12]) begin
alu_vec_mode_o = `VEC_MODE8;
mult_operator_o = `MUL_DOT8;
end else begin
alu_vec_mode_o = `VEC_MODE16;
mult_operator_o = `MUL_DOT16;
end
// distinguish normal vector, sc and sci modes
if (instr_rdata_i[14]) begin
@ -723,6 +748,37 @@ module riscv_decoder
regc_mux_o = `REGC_RD;
end
6'b10010_0: begin // pv.dotsp
mult_dot_en_o = 1'b1;
mult_dot_signed_o = 2'b11;
end
6'b10011_0: begin // pv.dotup
mult_dot_en_o = 1'b1;
mult_dot_signed_o = 2'b00;
end
6'b10100_0: begin // pv.dotusp
mult_dot_en_o = 1'b1;
mult_dot_signed_o = 2'b01;
end
6'b10101_0: begin // pv.sdotsp
mult_dot_en_o = 1'b1;
mult_dot_signed_o = 2'b11;
regc_used_o = 1'b1;
regc_mux_o = `REGC_RD;
end
6'b10110_0: begin // pv.sdotup
mult_dot_en_o = 1'b1;
mult_dot_signed_o = 2'b00;
regc_used_o = 1'b1;
regc_mux_o = `REGC_RD;
end
6'b10111_0: begin // pv.sdotusp
mult_dot_en_o = 1'b1;
mult_dot_signed_o = 2'b01;
regc_used_o = 1'b1;
regc_mux_o = `REGC_RD;
end
// comparisons, always have bit 26 set
6'b00000_1: begin alu_operator_o = `ALU_EQ; imm_b_mux_sel_o = `IMMB_VS; end // pv.cmpeq
6'b00001_1: begin alu_operator_o = `ALU_NE; imm_b_mux_sel_o = `IMMB_VS; end // pv.cmpne
@ -907,8 +963,6 @@ module riscv_decoder
assign regfile_mem_we_o = (deassert_we_i) ? 1'b0 : regfile_mem_we;
assign regfile_alu_we_o = (deassert_we_i) ? 1'b0 : regfile_alu_we;
assign data_req_o = (deassert_we_i) ? 1'b0 : data_req;
assign mult_en_o = (deassert_we_i) ? 1'b0 : mult_en;
assign mult_mac_en_o = (deassert_we_i) ? 1'b0 : mult_mac_en;
assign hwloop_we_o = (deassert_we_i) ? 3'b0 : hwloop_we;
assign csr_op_o = (deassert_we_i) ? `CSR_OP_NONE : csr_op;
assign jump_in_id_o = (deassert_we_i) ? `BRANCH_NONE : jump_in_id;

View file

@ -45,14 +45,19 @@ module riscv_ex_stage
input logic [ 1:0] alu_vec_mode_i,
// Multiplier signals
input logic [ 2:0] mult_operator_i,
input logic [31:0] mult_operand_a_i,
input logic [31:0] mult_operand_b_i,
input logic [31:0] mult_operand_c_i,
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 logic mult_vec_mode_i,
input logic mult_sel_subword_i,
input logic mult_signed_mode_i,
input logic [ 4:0] mult_imm_i,
input logic [31:0] mult_dot_op_a_i,
input logic [31:0] mult_dot_op_b_i,
input logic [31:0] mult_dot_op_c_i,
input logic [ 1:0] mult_dot_signed_i,
// input from ID stage
input logic branch_in_ex_i,
@ -155,14 +160,20 @@ module riscv_ex_stage
riscv_mult mult_i
(
.vector_mode_i ( mult_vec_mode_i ),
.sel_subword_i ( mult_sel_subword_i ),
.signed_mode_i ( mult_signed_mode_i ),
.mac_en_i ( mult_mac_en_i ),
.operator_i ( mult_operator_i ),
.short_subword_i ( mult_sel_subword_i ),
.short_signed_i ( mult_signed_mode_i ),
.op_a_i ( mult_operand_a_i ),
.op_b_i ( mult_operand_b_i ),
.mac_i ( mult_operand_c_i ),
.op_c_i ( mult_operand_c_i ),
.imm_i ( mult_imm_i ),
.dot_op_a_i ( mult_dot_op_a_i ),
.dot_op_b_i ( mult_dot_op_b_i ),
.dot_op_c_i ( mult_dot_op_c_i ),
.dot_signed_i ( mult_dot_signed_i ),
.result_o ( mult_result )
);

View file

@ -103,14 +103,19 @@ module riscv_id_stage
// MUL
output logic [ 2:0] mult_operator_ex_o,
output logic [31:0] mult_operand_a_ex_o,
output logic [31:0] mult_operand_b_ex_o,
output logic [31:0] mult_operand_c_ex_o,
output logic mult_en_ex_o,
output logic [1:0] mult_sel_subword_ex_o,
output logic [1:0] mult_signed_mode_ex_o,
output logic mult_mac_en_ex_o,
output logic mult_vec_mode_ex_o,
output logic mult_sel_subword_ex_o,
output logic mult_signed_mode_ex_o,
output logic [ 4:0] mult_imm_ex_o,
output logic [31:0] mult_dot_op_a_ex_o,
output logic [31:0] mult_dot_op_b_ex_o,
output logic [31:0] mult_dot_op_c_ex_o,
output logic [ 1:0] mult_dot_signed_ex_o,
// CSR ID/EX
output logic csr_access_ex_o,
@ -260,11 +265,13 @@ module riscv_id_stage
logic [1:0] jump_target_mux_sel;
// Multiplier Control
logic [2:0] mult_operator; // multiplication operation selection
logic mult_en; // multiplication is used instead of ALU
logic [1:0] mult_sel_subword; // Select a subword when doing multiplications
logic [1:0] mult_signed_mode; // Signed mode multiplication at the output of the controller, and before the pipe registers
logic mult_mac_en; // Enables the use of the accumulator
logic mult_vec_mode;
logic mult_int_en; // use integer multiplier
logic mult_sel_subword; // Select a subword when doing multiplications
logic mult_signed_mode; // Signed mode multiplication at the output of the controller, and before the pipe registers
logic mult_dot_en; // use dot product
logic [1:0] mult_dot_signed; // Signed mode dot products (can be mixed types)
// Register Write Control
logic regfile_we_id;
@ -315,10 +322,12 @@ module riscv_id_stage
// Immediates for ID
logic [0:0] bmask_a_mux;
logic [1:0] bmask_b_mux;
logic [0:0] mult_imm_mux;
logic [ 4:0] bmask_a_id;
logic [ 4:0] bmask_b_id;
logic [ 1:0] imm_vec_ext_id;
logic [ 4:0] mult_imm_id;
logic [ 1:0] alu_vec_mode;
logic scalar_replication;
@ -410,6 +419,8 @@ module riscv_id_stage
assign branch_taken_ex = branch_in_ex_o & branch_decision_i;
assign mult_en = mult_int_en | mult_dot_en;
///////////////////////////////////////////////
// _ ___ ___ ___ ___ ____ //
// | | | \ \ / / | / _ \ / _ \| _ \ //
@ -645,6 +656,16 @@ module riscv_id_stage
assign imm_vec_ext_id = imm_vu_type[1:0];
always_comb
begin
unique case (mult_imm_mux)
`MIMM_ZERO: mult_imm_id = '0;
`MIMM_S3: mult_imm_id = imm_s3_type[4:0];
default: mult_imm_id = '0;
endcase
end
/////////////////////////////////////////////////////////
// ____ _____ ____ ___ ____ _____ _____ ____ ____ //
// | _ \| ____/ ___|_ _/ ___|_ _| ____| _ \/ ___| //
@ -731,11 +752,13 @@ module riscv_id_stage
.regc_mux_o ( regc_mux ),
// MUL signals
.mult_en_o ( mult_en ),
.mult_operator_o ( mult_operator ),
.mult_int_en_o ( mult_int_en ),
.mult_sel_subword_o ( mult_sel_subword ),
.mult_signed_mode_o ( mult_signed_mode ),
.mult_mac_en_o ( mult_mac_en ),
.mult_vec_mode_o ( mult_vec_mode ),
.mult_imm_mux_o ( mult_imm_mux ),
.mult_dot_en_o ( mult_dot_en ),
.mult_dot_signed_o ( mult_dot_signed ),
// Register file control signals
.regfile_mem_we_o ( regfile_we_id ),
@ -993,14 +1016,19 @@ module riscv_id_stage
imm_vec_ext_ex_o <= '0;
alu_vec_mode_ex_o <= '0;
mult_operator_ex_o <= '0;
mult_operand_a_ex_o <= '0;
mult_operand_b_ex_o <= '0;
mult_operand_c_ex_o <= '0;
mult_en_ex_o <= 1'b0;
mult_sel_subword_ex_o <= 2'b0;
mult_signed_mode_ex_o <= 2'b0;
mult_mac_en_ex_o <= 1'b0;
mult_vec_mode_ex_o <= '0;
mult_sel_subword_ex_o <= 1'b0;
mult_signed_mode_ex_o <= 1'b0;
mult_imm_ex_o <= '0;
mult_dot_op_a_ex_o <= '0;
mult_dot_op_b_ex_o <= '0;
mult_dot_op_c_ex_o <= '0;
mult_dot_signed_ex_o <= '0;
regfile_waddr_ex_o <= 5'b0;
regfile_we_ex_o <= 1'b0;
@ -1063,15 +1091,21 @@ module riscv_id_stage
end
mult_en_ex_o <= mult_en;
if (mult_en)
begin // when we are multiplying we don't need the ALU
if (mult_int_en) begin // when we are multiplying we don't need the ALU
mult_operator_ex_o <= mult_operator;
mult_sel_subword_ex_o <= mult_sel_subword;
mult_signed_mode_ex_o <= mult_signed_mode;
mult_mac_en_ex_o <= mult_mac_en;
mult_operand_a_ex_o <= alu_operand_a;
mult_operand_b_ex_o <= alu_operand_b;
mult_operand_c_ex_o <= alu_operand_c;
mult_vec_mode_ex_o <= mult_vec_mode;
mult_imm_ex_o <= mult_imm_id;
end
if (mult_dot_en) begin
mult_operator_ex_o <= mult_operator;
mult_dot_signed_ex_o <= mult_dot_signed;
mult_dot_op_a_ex_o <= alu_operand_a;
mult_dot_op_b_ex_o <= alu_operand_b;
mult_dot_op_c_ex_o <= alu_operand_c;
end
regfile_we_ex_o <= regfile_we_id;

View file

@ -29,7 +29,7 @@
// no traces for synthesis, they are not synthesizable
`ifndef SYNTHESIS
`define TRACE_EXECUTION
//`define SIMCHECKER
`define SIMCHECKER
`endif
@ -173,6 +173,13 @@
`define ALU_PCKHI 6'b111001
`define MUL_MAC32 3'b000
`define MUL_MSU32 3'b001
`define MUL_I 3'b010
`define MUL_IR 3'b011
`define MUL_DOT8 3'b100
`define MUL_DOT16 3'b101
// vector modes
`define VEC_MODE32 2'b00
`define VEC_MODE16 2'b10
@ -257,6 +264,10 @@
`define BMASK_B_ZERO 2'b10
`define BMASK_B_ONE 2'b11
// multiplication immediates
`define MIMM_ZERO 1'b0
`define MIMM_S3 1'b1
// operand c selection
`define OP_C_REGC_OR_FWD 2'b00
`define OP_C_REGB_OR_FWD 2'b01

View file

@ -100,6 +100,8 @@
`define INSTR_REMU { 7'b0000001, 10'b?, 3'b111, 5'b?, `OPCODE_OP }
`define INSTR_PMAC { 7'b0000001, 10'b?, 3'b001, 5'b?, `OPCODE_OP }
`define INSTR_PMULRN { 2'b??, 5'b?,10'b?, 3'b?0?, 5'b?, `OPCODE_PULP_OP } // pulp specific
// PULP custom instructions
`define INSTR_MAC { 2'b00, 15'b?, 3'b000, 5'b?, `OPCODE_PULP_OP }

150
mult.sv
View file

@ -27,47 +27,143 @@
module riscv_mult
(
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 [ 2:0] operator_i,
// integer and short multiplier
input logic short_subword_i,
input logic short_signed_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_c_i,
input logic [ 4:0] imm_i,
// dot multiplier
input logic [ 1:0] dot_signed_i,
input logic [31:0] dot_op_a_i,
input logic [31:0] dot_op_b_i,
input logic [31:0] dot_op_c_i,
output logic [31:0] result_o
);
logic [31:0] op_a_sel;
logic [31:0] op_b_sel;
logic [31:0] mac_int;
//////////////////////////////////////////////////////////////
// ___ _ _ _____ ___ ___ ___ ___ __ __ _ _ _ _____ //
// |_ _| \| |_ _| __/ __| __| _ \ | \/ | | | | ||_ _| //
// | || .` | | | | _| (_ | _|| / | |\/| | |_| | |__| | //
// |___|_|\_| |_| |___\___|___|_|_\ |_| |_|\___/|____|_| //
// //
///////////////////////////////////////////////////////////////
logic [16:0] short_op_a;
logic [16:0] short_op_b;
logic [31:0] short_mac;
logic [31:0] short_round, short_round_tmp;
logic [31:0] short_result;
// prepare the rounding value
assign short_round_tmp = (32'h00000001) << imm_i;
assign short_round = (operator_i == `MUL_IR) ? {1'b0, short_round_tmp[31:1]} : '0;
// perform subword selection and sign extensions
assign short_op_a[15:0] = short_subword_i ? op_a_i[31:16] : op_a_i[15:0];
assign short_op_b[15:0] = short_subword_i ? op_b_i[31:16] : op_b_i[15:0];
assign short_op_a[16] = short_signed_i & short_op_a[15];
assign short_op_b[16] = short_signed_i & short_op_b[15];
assign short_mac = $signed(op_c_i) + $signed(short_op_a) * $signed(short_op_b) + $signed(short_round);
assign short_result = $signed({(short_signed_i & short_mac[31]), short_mac[31:0]}) >>> imm_i;
// 32x32 = 32-bit multiplier
logic [31:0] int_op_a_msu;
logic [31:0] int_op_b_msu;
logic [31:0] int_result;
logic int_is_msu;
assign int_is_msu = (operator_i == `MUL_MSU32); // TODO: think about using a separate signal here, could prevent some switching
assign int_op_a_msu = op_a_i ^ {32{int_is_msu}};
assign int_op_b_msu = op_b_i & {32{int_is_msu}};
assign int_result = $signed(op_c_i) + $signed(int_op_b_msu) + $signed(int_op_a_msu) * $signed(op_b_i);
///////////////////////////////////////////////
// ___ ___ _____ __ __ _ _ _ _____ //
// | \ / _ \_ _| | \/ | | | | ||_ _| //
// | |) | (_) || | | |\/| | |_| | |__| | //
// |___/ \___/ |_| |_| |_|\___/|____|_| //
// //
///////////////////////////////////////////////
logic [3:0][ 8:0] dot_char_op_a;
logic [3:0][ 8:0] dot_char_op_b;
logic [3:0][17:0] dot_char_mul;
logic [31:0] dot_char_result;
logic [1:0][16:0] dot_short_op_a;
logic [1:0][16:0] dot_short_op_b;
logic [1:0][31:0] dot_short_mul;
logic [31:0] dot_short_result;
assign dot_char_op_a[0] = {dot_signed_i[1] & dot_op_a_i[ 7], dot_op_a_i[ 7: 0]};
assign dot_char_op_a[1] = {dot_signed_i[1] & dot_op_a_i[15], dot_op_a_i[15: 8]};
assign dot_char_op_a[2] = {dot_signed_i[1] & dot_op_a_i[23], dot_op_a_i[23:16]};
assign dot_char_op_a[3] = {dot_signed_i[1] & dot_op_a_i[31], dot_op_a_i[31:24]};
assign dot_char_op_b[0] = {dot_signed_i[0] & dot_op_b_i[ 7], dot_op_b_i[ 7: 0]};
assign dot_char_op_b[1] = {dot_signed_i[0] & dot_op_b_i[15], dot_op_b_i[15: 8]};
assign dot_char_op_b[2] = {dot_signed_i[0] & dot_op_b_i[23], dot_op_b_i[23:16]};
assign dot_char_op_b[3] = {dot_signed_i[0] & dot_op_b_i[31], dot_op_b_i[31:24]};
assign dot_char_mul[0] = $signed(dot_char_op_a[0]) * $signed(dot_char_op_b[0]);
assign dot_char_mul[1] = $signed(dot_char_op_a[1]) * $signed(dot_char_op_b[1]);
assign dot_char_mul[2] = $signed(dot_char_op_a[2]) * $signed(dot_char_op_b[2]);
assign dot_char_mul[3] = $signed(dot_char_op_a[3]) * $signed(dot_char_op_b[3]);
assign dot_char_result = $signed(dot_char_mul[0]) + $signed(dot_char_mul[1]) + $signed(dot_char_mul[2]) + $signed(dot_char_mul[3]) + $signed(dot_op_c_i);
assign dot_short_op_a[0] = {dot_signed_i[1] & dot_op_a_i[15], dot_op_a_i[15: 0]};
assign dot_short_op_a[1] = {dot_signed_i[1] & dot_op_a_i[31], dot_op_a_i[31:16]};
assign dot_short_op_b[0] = {dot_signed_i[0] & dot_op_b_i[15], dot_op_b_i[15: 0]};
assign dot_short_op_b[1] = {dot_signed_i[0] & dot_op_b_i[31], dot_op_b_i[31:16]};
assign dot_short_mul[0] = $signed(dot_short_op_a[0]) * $signed(dot_short_op_b[0]);
assign dot_short_mul[1] = $signed(dot_short_op_a[1]) * $signed(dot_short_op_b[1]);
assign dot_short_result = $signed(dot_short_mul[0]) + $signed(dot_short_mul[1]) + $signed(dot_op_c_i);
////////////////////////////////////////////////////////
// ____ _ _ __ __ //
// | _ \ ___ ___ _ _| | |_ | \/ |_ ___ __ //
// | |_) / _ \/ __| | | | | __| | |\/| | | | \ \/ / //
// | _ < __/\__ \ |_| | | |_ | | | | |_| |> < //
// |_| \_\___||___/\__,_|_|\__| |_| |_|\__,_/_/\_\ //
// //
////////////////////////////////////////////////////////
always_comb
begin
op_a_sel = op_a_i;
op_b_sel = op_b_i;
result_o = 'x;
if(vector_mode_i)
begin
if(sel_subword_i[1] == 1'b1)
op_a_sel[15:0] = op_a_i[31:16];
else
op_a_sel[15:0] = op_a_i[15:0];
unique case (operator_i)
`MUL_MAC32, `MUL_MSU32: result_o = int_result;
if(sel_subword_i[0] == 1'b1)
op_b_sel[15:0] = op_b_i[31:16];
else
op_b_sel[15:0] = op_b_i[15:0];
`MUL_I, `MUL_IR: result_o = short_result;
op_a_sel[31:16] = {16{signed_mode_i[1] & op_a_sel[15]}};
op_b_sel[31:16] = {16{signed_mode_i[0] & op_b_sel[15]}};
end
`MUL_DOT8: result_o = dot_char_result;
`MUL_DOT16: result_o = dot_short_result;
default: ; // default case to suppress unique warning
endcase
end
assign mac_int = (mac_en_i == 1'b1) ? mac_i : 32'b0;
assign result_o = mac_int + op_a_sel * op_b_sel;
endmodule

View file

@ -134,14 +134,18 @@ module riscv_core
logic [ 1:0] alu_vec_mode_ex;
// Multiplier Control
logic [ 2:0] mult_operator_ex;
logic [31:0] mult_operand_a_ex;
logic [31:0] mult_operand_b_ex;
logic [31:0] mult_operand_c_ex;
logic mult_en_ex;
logic [1:0] mult_sel_subword_ex;
logic [1:0] mult_signed_mode_ex;
logic mult_mac_en_ex;
logic mult_vec_mode_ex;
logic mult_sel_subword_ex;
logic mult_signed_mode_ex;
logic [ 4:0] mult_imm_ex;
logic [31:0] mult_dot_op_a_ex;
logic [31:0] mult_dot_op_b_ex;
logic [31:0] mult_dot_op_c_ex;
logic [ 1:0] mult_dot_signed_ex;
// Register Write Control
logic [4:0] regfile_waddr_ex;
@ -399,14 +403,19 @@ module riscv_core
.regfile_alu_waddr_ex_o ( regfile_alu_waddr_ex ),
// MUL
.mult_operator_ex_o ( mult_operator_ex ), // from ID to EX stage
.mult_en_ex_o ( mult_en_ex ), // from ID to EX stage
.mult_sel_subword_ex_o ( mult_sel_subword_ex ), // from ID to EX stage
.mult_signed_mode_ex_o ( mult_signed_mode_ex ), // from ID to EX stage
.mult_mac_en_ex_o ( mult_mac_en_ex ), // from ID to EX stage
.mult_operand_a_ex_o ( mult_operand_a_ex ), // from ID to EX stage
.mult_operand_b_ex_o ( mult_operand_b_ex ), // from ID to EX stage
.mult_operand_c_ex_o ( mult_operand_c_ex ), // from ID to EX stage
.mult_vec_mode_ex_o ( mult_vec_mode_ex ), // from ID to EX stage
.mult_imm_ex_o ( mult_imm_ex ), // from ID to EX stage
.mult_dot_op_a_ex_o ( mult_dot_op_a_ex ), // from ID to EX stage
.mult_dot_op_b_ex_o ( mult_dot_op_b_ex ), // from ID to EX stage
.mult_dot_op_c_ex_o ( mult_dot_op_c_ex ), // from ID to EX stage
.mult_dot_signed_ex_o ( mult_dot_signed_ex ), // from ID to EX stage
// CSR ID/EX
.csr_access_ex_o ( csr_access_ex ),
@ -500,14 +509,18 @@ module riscv_core
.alu_vec_mode_i ( alu_vec_mode_ex ), // from ID/EX pipe registers
// Multipler
.mult_operator_i ( mult_operator_ex ), // from ID/EX pipe registers
.mult_operand_a_i ( mult_operand_a_ex ), // from ID/EX pipe registers
.mult_operand_b_i ( mult_operand_b_ex ), // from ID/EX pipe registers
.mult_operand_c_i ( mult_operand_c_ex ), // from ID/EX pipe registers
.mult_en_i ( mult_en_ex ), // from ID/EX pipe registers
.mult_sel_subword_i ( mult_sel_subword_ex ), // from ID/EX pipe registers
.mult_signed_mode_i ( mult_signed_mode_ex ), // from ID/EX pipe registers
.mult_mac_en_i ( mult_mac_en_ex ), // from ID/EX pipe registers
.mult_vec_mode_i ( mult_vec_mode_ex ), // from ID/EX pipe registers
.mult_imm_i ( mult_imm_ex ), // from ID/EX pipe registers
.mult_dot_op_a_i ( mult_dot_op_a_ex ), // from ID/EX pipe registers
.mult_dot_op_b_i ( mult_dot_op_b_ex ), // from ID/EX pipe registers
.mult_dot_op_c_i ( mult_dot_op_c_ex ), // from ID/EX pipe registers
.mult_dot_signed_i ( mult_dot_signed_ex ), // from ID/EX pipe registers
// interface with CSRs
.csr_access_i ( csr_access_ex ),

View file

@ -416,6 +416,49 @@ module riscv_tracer
end
endfunction
function void printMulInstr();
string mnemonic;
string str_suf;
string str_imm;
string str_asm;
begin
// always read rs1 and rs2 and write rd
regs_read.push_back({>> {rs1, rs1_value}});
regs_read.push_back({>> {rs2, rs2_value}});
regs_write.push_back({>> {rd, 'x}});
if (instr[12])
regs_read.push_back({>> {rd, rs3_value}});
case ({instr[31:30], instr[14]})
3'b000: str_suf = "u";
3'b001: str_suf = "uR";
3'b010: str_suf = "hhu";
3'b011: str_suf = "hhuR";
3'b100: str_suf = "s";
3'b101: str_suf = "sR";
3'b110: str_suf = "hhs";
3'b111: str_suf = "hhsR";
endcase
if (instr[12])
mnemonic = "p.mac";
else
mnemonic = "p.mul";
if (imm_s3_type[4:0] != 5'b00000)
str_asm = $sformatf("%s%sN", mnemonic, str_suf);
else
str_asm = $sformatf("%s%s", mnemonic, str_suf);
if (instr[29:25] != 5'b00000)
str = $sformatf("%-16s x%0d, x%0d, x%0d, %0d", str_asm, rd, rs1, rs2, $unsigned(imm_s3_type[4:0]));
else
str = $sformatf("%-16s x%0d, x%0d, x%0d", str_asm, rd, rs1, rs2);
end
endfunction
function void printVecInstr();
string mnemonic;
string str_asm;
@ -708,6 +751,7 @@ module riscv_tracer
{25'b?, `OPCODE_STORE_POST}: trace.printStoreInstr();
{25'b?, `OPCODE_HWLOOP}: trace.printHwloopInstr();
{25'b?, `OPCODE_VECOP}: trace.printVecInstr();
`INSTR_PMULRN: trace.printMulInstr();
default: trace.printMnemonic("INVALID");
endcase // unique case (instr)