blob: 868ba9851e8b03a8764fcf9acc8aa70bdbb9e186 [file] [log] [blame]
// description:
// 1. It will get uops from ALU Reservation station and execute this uop.
//
// feature list:
// 1. All are combinatorial logic.
// 2. All alu uop is executed and submit to ROB in 1 cycle.
// 3. Reuse arithmetic logic as much as possible.
// 4. Low-power design.
`include 'rvv.svh'
module rvv_alu_unit
(
alu_uop_valid,
alu_uop,
result_valid_ex2rob,
result_ex2rob
);
//
// interface signals
//
// ALU RS handshake signals
input logic alu_uop_valid;
input ALU_RS_t alu_uop;
// ALU send result signals to ROB
output logic result_valid_ex2rob;
output ALU2ROB_t result_ex2rob;
//
// internal signals
//
// ALU_RS_t struct signals
logic [`ROB_DEPTH_WIDTH-1:0] rob_entry;
FUNCT6_u uop_funct6
EXE_FUNCT3_e uop_funct3;
logic [`VSTART_WIDTH-1:0] vstart;
logic vm;
logic [`VCSR_VXRM-1:0] vxrm;
logic [`VLENB-1:0] v0_data;
logic [`VLEN-1:0] vd_data;
logic [`VLEN-1:0] vs1_data;
EEW_e vs1_eew;
logic vs1_data_valid;
ELE_TYPE_t vs1_type;
logic [`VLEN-1:0] vs2_data;
EEW_e vs2_eew;
logic vs2_data_valid;
ELE_TYPE_t vs2_type;
logic [`XLEN-1:0] rs1_data;
logic rs1_data_valid;
// execute
logic [`VLEN-1:0] src2_vdata_mask_logic;
logic [`VLEN-1:0] src1_vdata_mask_logic;
logic result_valid_mask_logic;
logic [`VLEN-1:0] result_vdata_mask_logic;
// ALU2ROB_t struct signals
logic [`VLEN-1:0] w_data; // when w_type=XRF, w_data[`XLEN-1:0] will store the scalar result
W_DATA_TYPE_t w_type;
logic w_valid;
logic [`VCSR_VXSAT-1:0] vxsat;
logic ignore_vta_vma;
//
integer i;
//
// prepare source data to calculate
//
// split ALU_RS_t struct
assign rob_entry = alu_uop.rob_entry;
assign uop_funct6 = alu_uop.uop_funct6;
assign uop_funct3 = alu_uop.uop_funct3;
assign vstart = alu_uop.vstart;
assign vm = alu_uop.vm;
assign vxrm = alu_uop.vxrm;
assign v0_data = alu_uop.vs3_data.v0_data;
assign vd_data = alu_uop.vs3_data.vd_data;
assign vs1 = alu_uop.vs1;
assign vs1_data = alu_uop.vs1_data;
assign vs1_eew = alu_uop.vs1_eew;
assign vs1_data_valid = alu_uop.vs1_data_valid;
assign vs1_type = alu_uop.vs1_type;
assign vs2_data = alu_uop.vs2_data;
assign vs2_eew = alu_uop.vs2_eew;
assign vs2_data_valid = alu_uop.vs2_data_valid;
assign vs2_type = alu_uop.vs2_type;
assign rs1_data = alu_uop.rs1_data;
assign rs1_data_valid = alu_uop.rs1_data_valid;
// prepare source data
always_comb begin
// initial the data
src2_vdata_mask_logic = 'b0;
src1_vdata_mask_logic = 'b0;
result_valid_mask_logic = 'b0;
// prepare source data
case({alu_uop_valid,uop_funct3})
{1'b1,OPIVV},
{1'b1,OPIVX},
{1'b1,OPIVI}: begin
case(uop_funct6.opi_funct)
default: begin
`ifdef ASSERT_ON
$error("Unsupported uop_funct6.opi_funct=%s, rob_entry=%d.\n",uop_funct6.opi_funct,rob_entry);
`endif
end
endcase
end
{1'b1,OPMVV},
{1'b1,OPMVX}: begin
case(uop_funct6.opm_funct)
VMANDN,
VMAND,
VMOR,
VMXOR,
VMORN,
VMNAND,
VMNOR,
VMXNOR: begin
if((vs1_data_valid&vs2_data_valid)&(vm==1'b1)) begin
src2_vdata_mask_logic = vs2_data;
src1_vdata_vmask_logic = vs1_data;
result_valid_vmask_logic = 1'b1;
end else begin
src2_vdata_mask_logic = 'b0;
src1_vdata_mask_logic = 'b0;
result_valid_mask_logic = 'b0;
`ifdef ASSERT_ON
`rvv_expect((vs1_data_valid&vs2_data_valid&vm)==1'b1)
else $error("%s uop: rob_entry=%d, unsupported vs1_data_valid&vs2_data_valid&vm.\n",uop_funct6.opm_funct,rob_entry);
`endif
end
end
default: begin
`ifdef ASSERT_ON
$error("Unsupported uop_funct6.opm_funct=%s, rob_entry=%d.\n",uop_funct6.opm_funct,rob_entry);
`endif
end
endcase
end
default: begin
`ifdef ASSERT_ON
`rvv_expect(alu_uop_valid==1'b0)
else $error("unsupported uop_funct3=%s, rob_entry=%d.\n",uop_funct3,rob_entry);
`endif
end
endcase
end
//
// calculate the result
//
always_comb begin
// initial the data
result_vdata_mask_logic = 'b0;
// calculate result data
case({alu_uop_valid,uop_funct3})
{1'b1,OPIVV},
{1'b1,OPIVX},
{1'b1,OPIVI}: begin
case(uop_funct6.opi_funct)
endcase
end
{1'b1,OPMVV},
{1'b1,OPMVX}: begin
case(uop_funct6.opm_funct)
VMANDN: begin
result_vdata_mask_logic = f_vmandn(src2_vdata_mask_logic,src1_vdata_maska_logic);
end
VMAND: begin
result_vdata_mask_logic = f_vmand(src2_vdata_mask_logic,src1_vdata_maska_logic);
end
VMOR: begin
result_vdata_mask_logic = f_vmor(src2_vdata_mask_logic,src1_vdata_maska_logic);
end
VMXOR: begin
result_vdata_mask_logic = f_vmxor(src2_vdata_mask_logic,src1_vdata_maska_logic);
end
VMORN: begin
result_vdata_mask_logic = f_vmorn(src2_vdata_mask_logic,src1_vdata_maska_logic);
end
VMNAND: begin
result_vdata_mask_logic = f_vmnand(src2_vdata_mask_logic,src1_vdata_maska_logic);
end
VMNOR: begin
result_vdata_mask_logic = f_vmnor(src2_vdata_mask_logic,src1_vdata_maska_logic);
end
VMXNOR: begin
result_vdata_mask_logic = f_vmxnor(src2_vdata_mask_logic,src1_vdata_maska_logic);
end
endcase
end
default: begin
end
endcase
end
//
// submit result to ROB
//
// assign ALU2ROB_t struct signals
assign result_ex2rob.rob_entry = rob_entry;
assign result_ex2rob.w_data = w_data;
assign result_ex2rob.w_type = w_type;
assign result_ex2rob.w_valid = w_valid;
assign result_ex2rob.vxsat = vxsat;
assign result_ex2rob.ignore_vta_vma = ignore_vta_vma;
// combine the signals to result_ex2rob struct and submit
always_comb begin
// initial
result_valid_ex2rob = 'b0;
w_data = 'b0;
w_tpye = 'b0;
w_valid = 'b0;
vxsat = 'b0;
ignore_vta_vma = 'b0;
// submit
case({alu_uop_valid,uop_funct3})
{1'b1,OPIVV},
{1'b1,OPIVX},
{1'b1,OPIVI}: begin
case(uop_funct6.opi_funct)
endcase
end
{1'b1,OPMVV},
{1'b1,OPMVX}: begin
case(uop_funct6.opm_funct)
VMANDN,
VMAND,
VMOR,
VMXOR,
VMORN,
VMNAND,
VMNOR,
VMXNOR: begin
for (i=0;i<`VLEN;i=i+1) begin
if (i<vstart)
w_data[i] = vd_data[i];
else
w_data[i] = result_vdata_mask_logic[i];
end
result_valid_ex2rob = result_valid_mask_logic;
w_type = VRF;
w_valid = 1'b1;
vxsat = 1'b0;
ignore_vta_vma = 1'b1;
end
endcase
end
default: begin
end
endcase
end
//
// function unit
//
// OPMVV-vmandn function unit
function [`VLEN-1:0] f_vmandn;
input logic [`VLEN-1:0] vs2_data;
input logic [`VLEN-1:0] vs1_data;
f_vmandn = vs2_data & (~vs1_data);
endfunction
// OPMVV-vmand function unit
function [`VLEN-1:0] f_vmand;
input logic [`VLEN-1:0] vs2_data;
input logic [`VLEN-1:0] vs1_data;
f_vmand = vs2_data & vs1_data;
endfunction
// OPMVV-vmor function unit
function [`VLEN-1:0] f_vmor;
input logic [`VLEN-1:0] vs2_data;
input logic [`VLEN-1:0] vs1_data;
f_vmor = vs2_data | vs1_data;
endfunction
// OPMVV-vmxor function unit
function [`VLEN-1:0] f_vmxor;
input logic [`VLEN-1:0] vs2_data;
input logic [`VLEN-1:0] vs1_data;
f_vmxor = vs2_data ^ vs1_data;
endfunction
// OPMVV-vmorn function unit
function [`VLEN-1:0] f_vmorn;
input logic [`VLEN-1:0] vs2_data;
input logic [`VLEN-1:0] vs1_data;
f_vmorn = vs2_data | (~vs1_data);
endfunction
// OPMVV-vmnand function unit
function [`VLEN-1:0] f_vmnand;
input logic [`VLEN-1:0] vs2_data;
input logic [`VLEN-1:0] vs1_data;
f_vmnand = ~(vs2_data & vs1_data);
endfunction
// OPMVV-vmnor function unit
function [`VLEN-1:0] f_vmnor;
input logic [`VLEN-1:0] vs2_data;
input logic [`VLEN-1:0] vs1_data;
f_vmnor = ~(vs2_data | vs1_data);
endfunction
// OPMVV-vmxnor function unit
function [`VLEN-1:0] f_vmxnor;
input logic [`VLEN-1:0] vs2_data;
input logic [`VLEN-1:0] vs1_data;
f_vmxnor = ~(vs2_data ^ vs1_data);
endfunction
endmodule