361 lines
9.8 KiB
Verilog
361 lines
9.8 KiB
Verilog
|
|
`include "VX_define.v"
|
|
|
|
module VX_decode(
|
|
// Fetch Inputs
|
|
VX_inst_meta_inter fd_inst_meta_de,
|
|
|
|
// Outputs
|
|
VX_frE_to_bckE_req_inter VX_frE_to_bckE_req,
|
|
VX_wstall_inter VX_wstall,
|
|
VX_join_inter VX_join,
|
|
|
|
output wire terminate_sim
|
|
|
|
);
|
|
|
|
wire[31:0] in_instruction = fd_inst_meta_de.instruction;
|
|
wire[31:0] in_curr_PC = fd_inst_meta_de.inst_pc;
|
|
wire[`NW_M1:0] in_warp_num = fd_inst_meta_de.warp_num;
|
|
|
|
assign VX_frE_to_bckE_req.curr_PC = in_curr_PC;
|
|
|
|
wire[`NT_M1:0] in_valid = fd_inst_meta_de.valid;
|
|
|
|
wire[6:0] curr_opcode;
|
|
|
|
wire is_itype;
|
|
wire is_rtype;
|
|
wire is_stype;
|
|
wire is_btype;
|
|
wire is_linst;
|
|
wire is_jal;
|
|
wire is_jalr;
|
|
wire is_lui;
|
|
wire is_auipc;
|
|
wire is_csr;
|
|
wire is_csr_immed;
|
|
wire is_e_inst;
|
|
|
|
wire is_gpgpu;
|
|
wire is_wspawn;
|
|
wire is_tmc;
|
|
wire is_split;
|
|
wire is_join;
|
|
wire is_barrier;
|
|
|
|
wire[2:0] func3;
|
|
wire[6:0] func7;
|
|
wire[11:0] u_12;
|
|
|
|
|
|
wire[7:0] jal_b_19_to_12;
|
|
wire jal_b_11;
|
|
wire[9:0] jal_b_10_to_1;
|
|
wire jal_b_20;
|
|
wire jal_b_0;
|
|
wire[20:0] jal_unsigned_offset;
|
|
wire[31:0] jal_1_offset;
|
|
|
|
wire[11:0] jalr_immed;
|
|
wire[31:0] jal_2_offset;
|
|
|
|
wire jal_sys_cond1;
|
|
wire jal_sys_cond2;
|
|
wire jal_sys_jal;
|
|
wire[31:0] jal_sys_off;
|
|
|
|
wire csr_cond1;
|
|
wire csr_cond2;
|
|
|
|
wire[11:0] alu_tempp;
|
|
wire alu_shift_i;
|
|
wire[11:0] alu_shift_i_immed;
|
|
|
|
wire[1:0] csr_type;
|
|
|
|
reg[4:0] csr_alu;
|
|
reg[4:0] alu_op;
|
|
reg[4:0] mul_alu;
|
|
reg[19:0] temp_upper_immed;
|
|
reg temp_jal;
|
|
reg[31:0] temp_jal_offset;
|
|
reg[31:0] temp_itype_immed;
|
|
reg[2:0] temp_branch_type;
|
|
reg temp_branch_stall;
|
|
|
|
// always @(posedge reset) begin
|
|
|
|
// end
|
|
|
|
assign VX_frE_to_bckE_req.valid = fd_inst_meta_de.valid;
|
|
|
|
assign VX_frE_to_bckE_req.warp_num = in_warp_num;
|
|
|
|
|
|
assign curr_opcode = in_instruction[6:0];
|
|
|
|
|
|
assign VX_frE_to_bckE_req.rd = in_instruction[11:7];
|
|
assign VX_frE_to_bckE_req.rs1 = in_instruction[19:15];
|
|
assign VX_frE_to_bckE_req.rs2 = in_instruction[24:20];
|
|
assign func3 = in_instruction[14:12];
|
|
assign func7 = in_instruction[31:25];
|
|
assign u_12 = in_instruction[31:20];
|
|
|
|
|
|
assign VX_frE_to_bckE_req.PC_next = in_curr_PC + 32'h4;
|
|
|
|
|
|
// Write Back sigal
|
|
assign is_rtype = (curr_opcode == `R_INST);
|
|
assign is_linst = (curr_opcode == `L_INST);
|
|
assign is_itype = (curr_opcode == `ALU_INST) || is_linst;
|
|
assign is_stype = (curr_opcode == `S_INST);
|
|
assign is_btype = (curr_opcode == `B_INST);
|
|
assign is_jal = (curr_opcode == `JAL_INST);
|
|
assign is_jalr = (curr_opcode == `JALR_INST);
|
|
assign is_lui = (curr_opcode == `LUI_INST);
|
|
assign is_auipc = (curr_opcode == `AUIPC_INST);
|
|
assign is_csr = (curr_opcode == `SYS_INST) && (func3 != 0);
|
|
assign is_csr_immed = (is_csr) && (func3[2] == 1);
|
|
assign is_e_inst = (curr_opcode == `SYS_INST) && (func3 == 0);
|
|
|
|
assign is_gpgpu = (curr_opcode == `GPGPU_INST);
|
|
|
|
assign is_tmc = is_gpgpu && (func3 == 0); // Goes to BE
|
|
assign is_wspawn = is_gpgpu && (func3 == 1); // Goes to BE
|
|
assign is_barrier = is_gpgpu && (func3 == 4); // Goes to BE
|
|
assign is_split = is_gpgpu && (func3 == 2); // Goes to BE
|
|
assign is_join = is_gpgpu && (func3 == 3); // Doesn't go to BE
|
|
|
|
|
|
assign VX_join.is_join = is_join;
|
|
assign VX_join.join_warp_num = in_warp_num;
|
|
|
|
|
|
assign VX_frE_to_bckE_req.is_wspawn = is_wspawn;
|
|
assign VX_frE_to_bckE_req.is_tmc = is_tmc;
|
|
assign VX_frE_to_bckE_req.is_split = is_split;
|
|
assign VX_frE_to_bckE_req.is_barrier = is_barrier;
|
|
|
|
|
|
|
|
assign VX_frE_to_bckE_req.csr_immed = is_csr_immed;
|
|
assign VX_frE_to_bckE_req.is_csr = is_csr;
|
|
|
|
|
|
assign VX_frE_to_bckE_req.wb = (is_jal || is_jalr || is_e_inst) ? `WB_JAL :
|
|
is_linst ? `WB_MEM :
|
|
(is_itype || is_rtype || is_lui || is_auipc || is_csr) ? `WB_ALU :
|
|
`NO_WB;
|
|
|
|
|
|
assign VX_frE_to_bckE_req.rs2_src = (is_itype || is_stype) ? `RS2_IMMED : `RS2_REG;
|
|
|
|
// MEM signals
|
|
assign VX_frE_to_bckE_req.mem_read = (is_linst) ? func3 : `NO_MEM_READ;
|
|
assign VX_frE_to_bckE_req.mem_write = (is_stype) ? func3 : `NO_MEM_WRITE;
|
|
|
|
// UPPER IMMEDIATE
|
|
always @(*) begin
|
|
case(curr_opcode)
|
|
`LUI_INST: temp_upper_immed = {func7, VX_frE_to_bckE_req.rs2, VX_frE_to_bckE_req.rs1, func3};
|
|
`AUIPC_INST: temp_upper_immed = {func7, VX_frE_to_bckE_req.rs2, VX_frE_to_bckE_req.rs1, func3};
|
|
default: temp_upper_immed = 20'h0;
|
|
endcase // curr_opcode
|
|
end
|
|
|
|
assign VX_frE_to_bckE_req.upper_immed = temp_upper_immed;
|
|
|
|
|
|
assign jal_b_19_to_12 = in_instruction[19:12];
|
|
assign jal_b_11 = in_instruction[20];
|
|
assign jal_b_10_to_1 = in_instruction[30:21];
|
|
assign jal_b_20 = in_instruction[31];
|
|
assign jal_b_0 = 1'b0;
|
|
assign jal_unsigned_offset = {jal_b_20, jal_b_19_to_12, jal_b_11, jal_b_10_to_1, jal_b_0};
|
|
assign jal_1_offset = {{11{jal_b_20}}, jal_unsigned_offset};
|
|
|
|
|
|
assign jalr_immed = {func7, VX_frE_to_bckE_req.rs2};
|
|
assign jal_2_offset = {{20{jalr_immed[11]}}, jalr_immed};
|
|
|
|
|
|
assign jal_sys_cond1 = func3 == 3'h0;
|
|
assign jal_sys_cond2 = u_12 < 12'h2;
|
|
|
|
assign jal_sys_jal = (jal_sys_cond1 && jal_sys_cond2) ? 1'b1 : 1'b0;
|
|
assign jal_sys_off = (jal_sys_cond1 && jal_sys_cond2) ? 32'hb0000000 : 32'hdeadbeef;
|
|
|
|
// JAL
|
|
always @(*) begin
|
|
case(curr_opcode)
|
|
`JAL_INST:
|
|
begin
|
|
temp_jal = 1'b1 && (|in_valid);
|
|
temp_jal_offset = jal_1_offset;
|
|
end
|
|
`JALR_INST:
|
|
begin
|
|
temp_jal = 1'b1 && (|in_valid);
|
|
temp_jal_offset = jal_2_offset;
|
|
end
|
|
`SYS_INST:
|
|
begin
|
|
// $display("SYS EBREAK %h", (jal_sys_jal && (|in_valid)) );
|
|
temp_jal = jal_sys_jal && (|in_valid);
|
|
temp_jal_offset = jal_sys_off;
|
|
end
|
|
default:
|
|
begin
|
|
temp_jal = 1'b0 && (|in_valid);
|
|
temp_jal_offset = 32'hdeadbeef;
|
|
end
|
|
endcase
|
|
end
|
|
|
|
assign VX_frE_to_bckE_req.jalQual = is_jal;
|
|
assign VX_frE_to_bckE_req.jal = temp_jal;
|
|
assign VX_frE_to_bckE_req.jal_offset = temp_jal_offset;
|
|
|
|
// wire is_ebreak;
|
|
|
|
|
|
// assign is_ebreak = is_e_inst;
|
|
wire ebreak = (curr_opcode == `SYS_INST) && (jal_sys_jal && (|in_valid));
|
|
assign VX_frE_to_bckE_req.ebreak = ebreak;
|
|
wire out_ebreak = ebreak;
|
|
assign terminate_sim = is_e_inst;
|
|
|
|
|
|
// CSR
|
|
|
|
assign csr_cond1 = func3 != 3'h0;
|
|
assign csr_cond2 = u_12 >= 12'h2;
|
|
|
|
assign VX_frE_to_bckE_req.csr_address = (csr_cond1 && csr_cond2) ? u_12 : 12'h55;
|
|
|
|
|
|
// ITYPE IMEED
|
|
assign alu_shift_i = (func3 == 3'h1) || (func3 == 3'h5);
|
|
assign alu_shift_i_immed = {{7{1'b0}}, VX_frE_to_bckE_req.rs2};
|
|
assign alu_tempp = alu_shift_i ? alu_shift_i_immed : u_12;
|
|
|
|
|
|
always @(*) begin
|
|
case(curr_opcode)
|
|
`ALU_INST: temp_itype_immed = {{20{alu_tempp[11]}}, alu_tempp};
|
|
`S_INST: temp_itype_immed = {{20{func7[6]}}, func7, VX_frE_to_bckE_req.rd};
|
|
`L_INST: temp_itype_immed = {{20{u_12[11]}}, u_12};
|
|
`B_INST: temp_itype_immed = {{20{in_instruction[31]}}, in_instruction[31], in_instruction[7], in_instruction[30:25], in_instruction[11:8]};
|
|
default: temp_itype_immed = 32'hdeadbeef;
|
|
endcase
|
|
end
|
|
|
|
assign VX_frE_to_bckE_req.itype_immed = temp_itype_immed;
|
|
|
|
|
|
|
|
always @(*) begin
|
|
case(curr_opcode)
|
|
`B_INST:
|
|
begin
|
|
// $display("BRANCH IN DECODE");
|
|
temp_branch_stall = 1'b1 && (|in_valid);
|
|
case(func3)
|
|
3'h0: temp_branch_type = `BEQ;
|
|
3'h1: temp_branch_type = `BNE;
|
|
3'h4: temp_branch_type = `BLT;
|
|
3'h5: temp_branch_type = `BGT;
|
|
3'h6: temp_branch_type = `BLTU;
|
|
3'h7: temp_branch_type = `BGTU;
|
|
default: temp_branch_type = `NO_BRANCH;
|
|
endcase
|
|
end
|
|
|
|
`JAL_INST:
|
|
begin
|
|
temp_branch_type = `NO_BRANCH;
|
|
temp_branch_stall = 1'b1 && (|in_valid);
|
|
end
|
|
`JALR_INST:
|
|
begin
|
|
temp_branch_type = `NO_BRANCH;
|
|
temp_branch_stall = 1'b1 && (|in_valid);
|
|
end
|
|
default:
|
|
begin
|
|
temp_branch_type = `NO_BRANCH;
|
|
temp_branch_stall = 1'b0 && (|in_valid);
|
|
end
|
|
endcase
|
|
end
|
|
|
|
assign VX_frE_to_bckE_req.branch_type = temp_branch_type;
|
|
|
|
assign VX_wstall.wstall = (temp_branch_stall || is_tmc || is_split || is_barrier) && (|in_valid);
|
|
assign VX_wstall.warp_num = in_warp_num;
|
|
|
|
always @(*) begin
|
|
// ALU OP
|
|
case(func3)
|
|
3'h0: alu_op = (curr_opcode == `ALU_INST) ? `ADD : (func7 == 7'h0 ? `ADD : `SUB);
|
|
3'h1: alu_op = `SLLA;
|
|
3'h2: alu_op = `SLT;
|
|
3'h3: alu_op = `SLTU;
|
|
3'h4: alu_op = `XOR;
|
|
3'h5: alu_op = (func7 == 7'h0) ? `SRL : `SRA;
|
|
3'h6: alu_op = `OR;
|
|
3'h7: alu_op = `AND;
|
|
default: alu_op = `NO_ALU;
|
|
endcase
|
|
end
|
|
|
|
always @(*) begin
|
|
// ALU OP
|
|
case(func3)
|
|
3'h0: mul_alu = `MUL;
|
|
3'h1: mul_alu = `MULH;
|
|
3'h2: mul_alu = `MULHSU;
|
|
3'h3: mul_alu = `MULHU;
|
|
3'h4: mul_alu = `DIV;
|
|
3'h5: mul_alu = `DIVU;
|
|
3'h6: mul_alu = `REM;
|
|
3'h7: mul_alu = `REMU;
|
|
default: mul_alu = `NO_ALU;
|
|
endcase
|
|
end
|
|
|
|
assign csr_type = func3[1:0];
|
|
|
|
always @(*) begin
|
|
case(csr_type)
|
|
2'h1: csr_alu = `CSR_ALU_RW;
|
|
2'h2: csr_alu = `CSR_ALU_RS;
|
|
2'h3: csr_alu = `CSR_ALU_RC;
|
|
default: csr_alu = `NO_ALU;
|
|
endcase
|
|
end
|
|
|
|
wire[4:0] temp_final_alu;
|
|
|
|
assign temp_final_alu = is_btype ? ((VX_frE_to_bckE_req.branch_type < `BLTU) ? `SUB : `SUBU) :
|
|
is_lui ? `LUI_ALU :
|
|
is_auipc ? `AUIPC_ALU :
|
|
is_csr ? csr_alu :
|
|
(is_stype || is_linst) ? `ADD :
|
|
alu_op;
|
|
|
|
assign VX_frE_to_bckE_req.alu_op = ((func7[0] == 1'b1) && is_rtype) ? mul_alu : temp_final_alu;
|
|
|
|
endmodule
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|