mirror of
https://github.com/openhwgroup/cve2.git
synced 2025-04-24 14:09:08 -04:00
Added support for dot product
This commit is contained in:
parent
aa28fac157
commit
68afee79a6
8 changed files with 363 additions and 98 deletions
122
decoder.sv
122
decoder.sv
|
@ -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;
|
||||
|
|
29
ex_stage.sv
29
ex_stage.sv
|
@ -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 )
|
||||
);
|
||||
|
|
72
id_stage.sv
72
id_stage.sv
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
150
mult.sv
|
@ -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
|
||||
|
|
|
@ -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 ),
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue