Loading files
This file is pinned to the selected release. Download the original to open it in your design tool.
// Copyright 2019- RSD contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
//
// Micro op decoder
//
import BasicTypes::*;
import MicroOpTypes::*;
import OpFormatTypes::*;
function automatic void EmitInvalidOp(
output OpInfo op
);
op = '0;
op.valid = FALSE;
endfunction
//
// Modify micro op information.
//
function automatic OpInfo ModifyMicroOp(
input OpInfo src,
input MicroOpIndex mid,
input logic split,
input logic last
);
OpInfo op;
op = src;
op.mid = mid;
op.split = split;
op.last = last;
return op;
endfunction
//
// RISCV Instruction Decoder
//
//
// --- 即値整数演算, シフト含む
//
function automatic void RISCV_EmitOpImm(
output OpInfo opInfo,
input RISCV_ISF_Common isf,
input LScalarRegNumPath srcRegNumA,
input LScalarRegNumPath srcRegNumB,
input LScalarRegNumPath dstRegNum,
input logic unsupported
);
RISCV_ISF_I isfI;
RISCV_ISF_R isfR;
OpFunct3 opFunct3;
ShiftFunct7 shiftFunct7;
RISCV_IntOperandImmShift intOperandImmShift;
logic isShift;
IntALU_Code aluCode;
isfI = isf;
isfR = isf;
opFunct3 = OpFunct3'(isfR.funct3);
shiftFunct7 = ShiftFunct7'(isfR.funct7);
isShift = ( ( opFunct3 == OP_FUNCT3_SLL ) || ( opFunct3 == OP_FUNCT3_SRL_SRA ) );
// 論理レジスタ番号
`ifdef RSD_ENABLE_VECTOR_PATH
opInfo.operand.intOp.dstRegNum.isVector = FALSE;
opInfo.operand.intOp.srcRegNumA.isVector = FALSE;
opInfo.operand.intOp.srcRegNumB.isVector = FALSE;
`endif
opInfo.operand.intOp.dstRegNum.regNum = dstRegNum;
opInfo.operand.intOp.srcRegNumA.regNum = srcRegNumA;
opInfo.operand.intOp.srcRegNumB.regNum = srcRegNumB;
// 即値
opInfo.operand.intOp.shiftType = SOT_IMM_SHIFT ;
intOperandImmShift.shift = isShift ? isfR.rs2 : '0;
intOperandImmShift.shiftType = ( opFunct3 == OP_FUNCT3_SLL ) ? ST_LSL :
( ( opFunct3 == OP_FUNCT3_SRL_SRA ) && ( shiftFunct7 == SHIFT_FUNCT7_SRL ) ) ? ST_LSR :
( ( opFunct3 == OP_FUNCT3_SRL_SRA ) && ( shiftFunct7 == SHIFT_FUNCT7_SRA ) ) ? ST_ASR :
ST_ROR;
intOperandImmShift.isRegShift = FALSE;
intOperandImmShift.imm = isShift ? ShamtExtention( isfR ) : I_TypeImmExtention( isfI );
intOperandImmShift.immType = RISCV_IMM_I;
opInfo.operand.intOp.shiftIn = intOperandImmShift;
// ALU
RISCV_DecodeOpImmFunct3( aluCode, opFunct3 );
opInfo.operand.intOp.aluCode = aluCode;
// レジスタ書き込みを行うかどうか
// ゼロレジスタへの書き込みは書き込みフラグをFALSEとする
opInfo.writeReg = ( dstRegNum != ZERO_REGISTER ) ? TRUE : FALSE;
// 論理レジスタを読むかどうか
opInfo.opTypeA = OOT_REG;
opInfo.opTypeB = OOT_IMM;
// 命令の種類
opInfo.mopType = MOP_TYPE_INT;
opInfo.mopSubType.intType = isShift ? INT_MOP_TYPE_SHIFT : INT_MOP_TYPE_ALU;
// 条件コード
opInfo.cond = COND_AL;
// 未定義命令
opInfo.unsupported = unsupported;
opInfo.undefined = FALSE;
// Serialized
opInfo.serialized = FALSE;
// Control
opInfo.valid = TRUE; // Valid outputs
endfunction
function automatic void RISCV_DecodeOpImm(
output OpInfo [MICRO_OP_MAX_NUM-1:0] microOps,
output InsnInfo insnInfo,
input RISCV_ISF_Common isf
);
OpInfo intOp;
OpInfo shiftOp;
OpInfo rijOp;
OpInfo selectOp;
MicroOpIndex mid;
//RISCVでは複数micro opへの分割は基本的に必要ないはず
RISCV_EmitOpImm(
.opInfo( intOp ),
.isf( isf ),
.srcRegNumA( isf.rs1 ),
.srcRegNumB( 0 ),
.dstRegNum( isf.rd ),
.unsupported( FALSE )
);
mid = 0;
for(int i = 0; i < MICRO_OP_MAX_NUM; i++) begin
EmitInvalidOp(microOps[i]);
end
// --- 1
// It begins at 1 for aligning outputs to DecodeIntReg.
microOps[1] = ModifyMicroOp(intOp, mid, FALSE, TRUE);
mid += 1;
insnInfo.writePC = FALSE;
insnInfo.isCall = FALSE;
insnInfo.isReturn = FALSE;
insnInfo.isRelBranch = FALSE;
insnInfo.isSerialized = FALSE;
endfunction
//
// --- レジスタ整数演算, シフト含む
//
function automatic void RISCV_EmitOp(
output OpInfo opInfo,
input RISCV_ISF_Common isf,
input LScalarRegNumPath srcRegNumA,
input LScalarRegNumPath srcRegNumB,
input LScalarRegNumPath dstRegNum,
input logic unsupported
);
RISCV_ISF_R isfR;
OpFunct3 opFunct3;
OpFunct7 opFunct7;
ShiftFunct7 shiftFunct7;
RISCV_IntOperandImmShift intOperandImmShift;
logic isShift;
IntALU_Code aluCode;
isfR = isf;
opFunct3 = OpFunct3'(isfR.funct3);
opFunct7 = OpFunct7'(isfR.funct7);
shiftFunct7 = ShiftFunct7'(isfR.funct7);
isShift = ( ( opFunct3 == OP_FUNCT3_SLL ) || ( opFunct3 == OP_FUNCT3_SRL_SRA ) );
// 論理レジスタ番号
`ifdef RSD_ENABLE_VECTOR_PATH
opInfo.operand.intOp.dstRegNum.isVector = FALSE;
opInfo.operand.intOp.srcRegNumA.isVector = FALSE;
opInfo.operand.intOp.srcRegNumB.isVector = FALSE;
`endif
opInfo.operand.intOp.dstRegNum.regNum = dstRegNum;
opInfo.operand.intOp.srcRegNumA.regNum = srcRegNumA;
opInfo.operand.intOp.srcRegNumB.regNum = srcRegNumB;
// 即値
opInfo.operand.intOp.shiftType = SOT_REG_SHIFT ;
intOperandImmShift.shift = isShift ? isfR.rs2 : '0;
intOperandImmShift.shiftType = ( opFunct3 == OP_FUNCT3_SLL ) ? ST_LSL :
( ( opFunct3 == OP_FUNCT3_SRL_SRA ) && ( shiftFunct7 == SHIFT_FUNCT7_SRL ) ) ? ST_LSR :
( ( opFunct3 == OP_FUNCT3_SRL_SRA ) && ( shiftFunct7 == SHIFT_FUNCT7_SRA ) ) ? ST_ASR :
ST_ROR;
intOperandImmShift.isRegShift = TRUE;
intOperandImmShift.imm = '0;
intOperandImmShift.immType = RISCV_IMM_R;
opInfo.operand.intOp.shiftIn = intOperandImmShift;
// ALU
//RISCV_DecodeOpFunct3( isfR.funct3, isfR.funct7, opInfo.operand.intOp.aluCode);
RISCV_DecodeOpFunct3( aluCode, opFunct3, opFunct7 );
opInfo.operand.intOp.aluCode = aluCode;
// レジスタ書き込みを行うかどうか
// ゼロレジスタへの書き込みは書き込みフラグをFALSEとする
opInfo.writeReg = ( dstRegNum != ZERO_REGISTER ) ? TRUE : FALSE;
// 論理レジスタを読むかどうか
opInfo.opTypeA = OOT_REG;
opInfo.opTypeB = OOT_REG;
// 命令の種類
opInfo.mopType = MOP_TYPE_INT;
opInfo.mopSubType.intType = isShift ? INT_MOP_TYPE_SHIFT : INT_MOP_TYPE_ALU;
// 条件コード
opInfo.cond = COND_AL;
// 未定義命令
opInfo.unsupported = unsupported;
opInfo.undefined = FALSE;
// Serialized
opInfo.serialized = FALSE;
// Control
opInfo.valid = TRUE; // Valid outputs
endfunction
function automatic void RISCV_DecodeOp(
output OpInfo [MICRO_OP_MAX_NUM-1:0] microOps,
output InsnInfo insnInfo,
input RISCV_ISF_Common isf
);
OpInfo intOp;
OpInfo shiftOp;
OpInfo rijOp;
OpInfo selectOp;
MicroOpIndex mid;
//RISCVでは複数micro opへの分割は基本的に必要ないはず
RISCV_EmitOp(
.opInfo( intOp ),
.isf( isf ),
.srcRegNumA( isf.rs1 ),
.srcRegNumB( isf.rs2 ),
.dstRegNum( isf.rd ),
.unsupported( FALSE )
);
mid = 0;
for(int i = 0; i < MICRO_OP_MAX_NUM; i++) begin
EmitInvalidOp(microOps[i]);
end
// --- 1
// It begins at 1 for aligning outputs to DecodeIntReg.
microOps[1] = ModifyMicroOp(intOp, mid, FALSE, TRUE);
mid += 1;
insnInfo.writePC = FALSE;
insnInfo.isCall = FALSE;
insnInfo.isReturn = FALSE;
insnInfo.isRelBranch = FALSE;
insnInfo.isSerialized = FALSE;
endfunction
//
// --- RISCV LUI, AUIPC
//
function automatic void RISCV_EmitUTypeInst(
output OpInfo opInfo,
input RISCV_ISF_Common isf,
input LScalarRegNumPath srcRegNumA,
input LScalarRegNumPath srcRegNumB,
input LScalarRegNumPath dstRegNum,
input logic unsupported
);
RISCV_ISF_U isfU;
RISCV_IntOperandImmShift intOperandImmShift;
isfU = isf;
// 論理レジスタ番号
`ifdef RSD_ENABLE_VECTOR_PATH
opInfo.operand.intOp.dstRegNum.isVector = FALSE;
opInfo.operand.intOp.srcRegNumA.isVector = FALSE;
opInfo.operand.intOp.srcRegNumB.isVector = FALSE;
`endif
opInfo.operand.intOp.dstRegNum.regNum = dstRegNum;
opInfo.operand.intOp.srcRegNumA.regNum = srcRegNumA;
opInfo.operand.intOp.srcRegNumB.regNum = srcRegNumB;
// 即値
opInfo.operand.intOp.shiftType = SOT_REG_SHIFT ;
intOperandImmShift.shift = '0;
intOperandImmShift.shiftType = ST_ROR;
intOperandImmShift.isRegShift = TRUE;
intOperandImmShift.imm = isfU.imm;
intOperandImmShift.immType = RISCV_IMM_U;
opInfo.operand.intOp.shiftIn = intOperandImmShift;
// ALU
opInfo.operand.intOp.aluCode = AC_ADD;
// レジスタ書き込みを行うかどうか
// ゼロレジスタへの書き込みは書き込みフラグをFALSEとする
opInfo.writeReg = ( dstRegNum != ZERO_REGISTER ) ? TRUE : FALSE;
// 論理レジスタを読むかどうか
opInfo.opTypeA = isf.opCode == RISCV_AUIPC ? OOT_PC : OOT_REG;
opInfo.opTypeB = OOT_IMM;
// 命令の種類
opInfo.mopType = MOP_TYPE_INT;
opInfo.mopSubType.intType = INT_MOP_TYPE_ALU;
// 条件コード
opInfo.cond = COND_AL;
// 未定義命令
opInfo.unsupported = unsupported;
opInfo.undefined = FALSE;
// Serialized
opInfo.serialized = FALSE;
// Control
opInfo.valid = TRUE; // Valid outputs
endfunction
function automatic void RISCV_DecodeUTypeInst(
output OpInfo [MICRO_OP_MAX_NUM-1:0] microOps,
output InsnInfo insnInfo,
input RISCV_ISF_Common isf
);
OpInfo intOp;
MicroOpIndex mid;
//RISCVでは複数micro opへの分割は基本的に必要ないはず
RISCV_EmitUTypeInst(
.opInfo( intOp ),
.isf( isf ),
.srcRegNumA( 0 ),
.srcRegNumB( 0 ),
.dstRegNum( isf.rd ),
.unsupported( FALSE )
);
mid = 0;
for(int i = 0; i < MICRO_OP_MAX_NUM; i++) begin
EmitInvalidOp(microOps[i]);
end
// --- 1
// It begins at 1 for aligning outputs to DecodeIntReg.
microOps[1] = ModifyMicroOp(intOp, mid, FALSE, TRUE);
mid += 1;
insnInfo.writePC = FALSE;
insnInfo.isCall = FALSE;
insnInfo.isReturn = FALSE;
insnInfo.isRelBranch = FALSE;
insnInfo.isSerialized = FALSE;
endfunction
//
// --- RISCV JAL
//
function automatic void RISCV_EmitJAL(
output OpInfo opInfo,
input RISCV_ISF_Common isf
);
RISCV_ISF_U isfU;
isfU = isf;
// 論理レジスタ番号
`ifdef RSD_ENABLE_VECTOR_PATH
opInfo.operand.brOp.dstRegNum.isVector = FALSE;
opInfo.operand.brOp.srcRegNumA.isVector = FALSE;
opInfo.operand.brOp.srcRegNumB.isVector = FALSE;
`endif
opInfo.operand.brOp.dstRegNum.regNum = isfU.rd;
opInfo.operand.brOp.srcRegNumA.regNum = '0;
opInfo.operand.brOp.srcRegNumB.regNum = '0;
// レジスタ書き込みを行うかどうか
// 比較系の命令はレジスタに書き込みを行わない
// ゼロレジスタへの書き込みは書き込みフラグをFALSEとする
opInfo.writeReg = ( isfU.rd != ZERO_REGISTER ) ? TRUE : FALSE;
// 論理レジスタを読むかどうか
opInfo.opTypeA = OOT_PC;
opInfo.opTypeB = OOT_IMM;
// 命令の種類
opInfo.mopType = MOP_TYPE_INT;
opInfo.mopSubType.intType = INT_MOP_TYPE_BR;
// 条件コード
opInfo.cond = COND_AL;
// 分岐ターゲット
opInfo.operand.brOp.brDisp = GetJAL_Target( isf );
opInfo.operand.brOp.padding = 0;
// 未定義命令
opInfo.unsupported = FALSE;
opInfo.undefined = FALSE;
// Serialized
opInfo.serialized = FALSE;
// Control
opInfo.valid = TRUE; // Valid outputs
endfunction
function automatic void RISCV_DecodeJAL(
output OpInfo [MICRO_OP_MAX_NUM-1:0] microOps,
output InsnInfo insnInfo,
input RISCV_ISF_Common isf
);
OpInfo brOp;
MicroOpIndex mid;
//RISCVでは複数micro opへの分割は基本的に必要ないはず
RISCV_EmitJAL(
.opInfo( brOp ),
.isf( isf )
);
// Initizalize
mid = 0;
for(int i = 0; i < MICRO_OP_MAX_NUM; i++) begin
EmitInvalidOp(microOps[i]);
end
// --- 1
// It begins at 1 for aligning outputs to DecodeIntReg.
microOps[1] = ModifyMicroOp(brOp, mid, FALSE, TRUE);
insnInfo.writePC = TRUE;
insnInfo.isCall = ( brOp.writeReg && ( brOp.operand.brOp.dstRegNum.regNum == LINK_REGISTER ) ) ? TRUE : FALSE;
insnInfo.isReturn = FALSE;
insnInfo.isRelBranch = TRUE;
insnInfo.isSerialized = FALSE;
endfunction
//
// --- RISCV Decode JALR
//
function automatic void RISCV_EmitJALR(
output OpInfo opInfo,
input RISCV_ISF_Common isf
);
RISCV_ISF_I isfI;
isfI = isf;
// 論理レジスタ番号
`ifdef RSD_ENABLE_VECTOR_PATH
opInfo.operand.brOp.dstRegNum.isVector = FALSE;
opInfo.operand.brOp.srcRegNumA.isVector = FALSE;
opInfo.operand.brOp.srcRegNumB.isVector = FALSE;
`endif
opInfo.operand.brOp.dstRegNum.regNum = isfI.rd;
opInfo.operand.brOp.srcRegNumA.regNum = isfI.rs1;
opInfo.operand.brOp.srcRegNumB.regNum = 0;
// レジスタ書き込みを行うかどうか
// 比較系の命令はレジスタに書き込みを行わない
// ゼロレジスタへの書き込みは書き込みフラグをFALSEとする
opInfo.writeReg = ( isfI.rd != ZERO_REGISTER ) ? TRUE : FALSE;
// 論理レジスタを読むかどうか
opInfo.opTypeA = OOT_REG;
opInfo.opTypeB = OOT_IMM;
// 命令の種類
opInfo.mopType = MOP_TYPE_INT;
opInfo.mopSubType.intType = INT_MOP_TYPE_RIJ;
// 条件コード
opInfo.cond = COND_AL;
// 分岐ターゲット
opInfo.operand.brOp.brDisp = GetJALR_Target( isfI );
opInfo.operand.brOp.padding = '0;
// 未定義命令
opInfo.unsupported = FALSE;
opInfo.undefined = FALSE;
// Serialized
opInfo.serialized = FALSE;
// Control
opInfo.valid = TRUE; // Valid outputs
endfunction
function automatic void RISCV_DecodeJALR(
output OpInfo [MICRO_OP_MAX_NUM-1:0] microOps,
output InsnInfo insnInfo,
input RISCV_ISF_Common isf
);
OpInfo brOp;
MicroOpIndex mid;
//RISCVでは複数micro opへの分割は基本的に必要ないはず
RISCV_EmitJALR(
.opInfo( brOp ),
.isf( isf )
);
// Initizalize
mid = 0;
for(int i = 0; i < MICRO_OP_MAX_NUM; i++) begin
EmitInvalidOp(microOps[i]);
end
// --- 1
// It begins at 1 for aligning outputs to DecodeIntReg.
microOps[1] = ModifyMicroOp(brOp, mid, FALSE, TRUE);
insnInfo.writePC = TRUE;
insnInfo.isCall = ( brOp.writeReg && ( brOp.operand.brOp.dstRegNum.regNum == LINK_REGISTER ) ) ? TRUE : FALSE;
insnInfo.isReturn = ( ( brOp.operand.brOp.srcRegNumA.regNum == LINK_REGISTER )
&& ( brOp.operand.brOp.dstRegNum.regNum == ZERO_REGISTER ) ) ? TRUE : FALSE;
insnInfo.isRelBranch = FALSE;
insnInfo.isSerialized = FALSE;
endfunction
//
// --- RISCV BRANCH
//
function automatic void RISCV_EmitBranch(
output OpInfo opInfo,
input RISCV_ISF_Common isf
);
RISCV_ISF_R isfR;
BrFunct3 brFunct3;
CondCode condCode;
isfR = isf;
brFunct3 = BrFunct3'(isfR.funct3);
// 論理レジスタ番号
`ifdef RSD_ENABLE_VECTOR_PATH
opInfo.operand.brOp.dstRegNum.isVector = FALSE;
opInfo.operand.brOp.srcRegNumA.isVector = FALSE;
opInfo.operand.brOp.srcRegNumB.isVector = FALSE;
`endif
opInfo.operand.brOp.dstRegNum.regNum = 0;
opInfo.operand.brOp.srcRegNumA.regNum = isfR.rs1;
opInfo.operand.brOp.srcRegNumB.regNum = isfR.rs2;
// レジスタ書き込みを行うかどうか
// 比較系の命令はレジスタに書き込みを行わない
// ゼロレジスタへの書き込みは書き込みフラグをFALSEとする
opInfo.writeReg = FALSE;
// 論理レジスタを読むかどうか
opInfo.opTypeA = OOT_REG;
opInfo.opTypeB = OOT_REG;
// 命令の種類
opInfo.mopType = MOP_TYPE_INT;
opInfo.mopSubType.intType = INT_MOP_TYPE_BR;
// 条件コード
//RISCV_DecodeBrFunct3(isfR.funct3, opInfo.cond);
RISCV_DecodeBrFunct3( condCode, brFunct3 );
opInfo.cond = condCode;
// 分岐ターゲット
opInfo.operand.brOp.brDisp = GetBranchDisplacement( isfR );
opInfo.operand.brOp.padding = '0;
// 未定義命令
opInfo.unsupported = FALSE;
opInfo.undefined = FALSE;
// Serialized
opInfo.serialized = FALSE;
// Control
opInfo.valid = TRUE; // Valid outputs
endfunction
function automatic void RISCV_DecodeBranch(
output OpInfo [MICRO_OP_MAX_NUM-1:0] microOps,
output InsnInfo insnInfo,
input RISCV_ISF_Common isf
);
OpInfo brOp;
MicroOpIndex mid;
//RISCVでは複数micro opへの分割は基本的に必要ないはず
RISCV_EmitBranch(
.opInfo( brOp ),
.isf( isf )
);
// Initizalize
mid = 0;
for(int i = 0; i < MICRO_OP_MAX_NUM; i++) begin
EmitInvalidOp(microOps[i]);
end
// --- 1
// It begins at 1 for aligning outputs to DecodeIntReg.
microOps[1] = ModifyMicroOp(brOp, mid, FALSE, TRUE);
insnInfo.writePC = TRUE;
insnInfo.isCall = FALSE;
insnInfo.isReturn = FALSE;
insnInfo.isRelBranch = TRUE;
insnInfo.isSerialized = FALSE;
endfunction
//
// --- EISCV MEMORY OP
//
function automatic void RISCV_EmitMemOp(
output OpInfo opInfo,
input RISCV_ISF_Common isf
);
RISCV_ISF_S isfS;
RISCV_ISF_I isfI;
MemFunct3 memFunct3;
logic isLoad;
MemAccessMode memAccessMode;
isfS = isf;
isfI = isf;
memFunct3 = MemFunct3'(isfS.funct3);
isLoad = ( isfI.opCode == RISCV_LD );
// 論理レジスタ番号
`ifdef RSD_ENABLE_VECTOR_PATH
opInfo.operand.memOp.dstRegNum.isVector = FALSE;
opInfo.operand.memOp.srcRegNumA.isVector = FALSE;
opInfo.operand.memOp.srcRegNumB.isVector = FALSE;
`endif
opInfo.operand.memOp.dstRegNum.regNum = isLoad ? isfI.rd : '0;
opInfo.operand.memOp.srcRegNumA.regNum = isfI.rs1;
opInfo.operand.memOp.srcRegNumB.regNum = isLoad ? '0 : isfS.rs2;
opInfo.operand.memOp.csrCtrl = '0; // unused
opInfo.operand.memOp.padding = '0;
// レジスタ書き込みを行うかどうか
// ゼロレジスタへの書き込みは書き込みフラグをFALSEとする
opInfo.writeReg = ( isfI.rd != ZERO_REGISTER ) & isLoad;
// 論理レジスタを読むかどうか
// ストア時はBを読む
opInfo.opTypeA = OOT_REG;
opInfo.opTypeB = isLoad ? OOT_IMM : OOT_REG;
// 命令の種類
opInfo.mopType = MOP_TYPE_MEM;
opInfo.mopSubType.memType = isLoad ? MEM_MOP_TYPE_LOAD : MEM_MOP_TYPE_STORE;
// 条件コード
opInfo.cond = COND_AL;
// アドレッシング
opInfo.operand.memOp.addrIn = isLoad ? isfI.imm : {isfS.imm2, isfS.imm1};
opInfo.operand.memOp.isAddAddr = TRUE;
opInfo.operand.memOp.isRegAddr = TRUE;
RISCV_DecodeMemAccessMode( memAccessMode, memFunct3 );
opInfo.operand.memOp.memAccessMode = memAccessMode;
opInfo.valid = TRUE;
opInfo.unsupported = FALSE;
opInfo.undefined = FALSE;
// Serialized
opInfo.serialized = FALSE;
endfunction
function automatic void RISCV_DecodeMemOp(
output OpInfo [MICRO_OP_MAX_NUM-1:0] microOps,
output InsnInfo insnInfo,
input RISCV_ISF_Common isf
);
OpInfo memOp;
MicroOpIndex mid;
//RISCVでは複数micro opへの分割は基本的に必要ないはず
RISCV_EmitMemOp(
.opInfo( memOp ),
.isf( isf )
);
// Initizalize
mid = 0;
for(int i = 0; i < MICRO_OP_MAX_NUM; i++) begin
EmitInvalidOp(microOps[i]);
end
// --- 1
// It begins at 1 for aligning outputs to DecodeIntReg.
microOps[1] = ModifyMicroOp(memOp, mid, FALSE, TRUE);
insnInfo.writePC = FALSE;
insnInfo.isCall = FALSE;
insnInfo.isReturn = FALSE;
insnInfo.isRelBranch = FALSE;
insnInfo.isSerialized = FALSE;
endfunction
//
// --- Complex Op (RISC-VではRV32M)
//
function automatic void RISCV_EmitComplexOp(
output OpInfo opInfo,
input RISCV_ISF_Common isf,
input LScalarRegNumPath srcRegNumA,
input LScalarRegNumPath srcRegNumB,
input LScalarRegNumPath dstRegNum,
input logic unsupported
);
RISCV_ISF_R isfR;
OpFunct3 opFunct3;
OpFunct7 opFunct7;
RV32MFunct3 rv32mFunct3;
RV32MFunct7 rv32mFunct7;
logic isMul;
IntMUL_Code mulCode;
IntDIV_Code divCode;
isfR = isf;
opFunct3 = OpFunct3'(isfR.funct3);
opFunct7 = OpFunct7'(isfR.funct7);
rv32mFunct3 = RV32MFunct3'(isfR.funct3);
rv32mFunct7 = RV32MFunct7'(isfR.funct7);
isMul = ( rv32mFunct3 < RV32M_FUNCT3_DIV );
// 論理レジスタ番号
`ifdef RSD_ENABLE_VECTOR_PATH
opInfo.operand.complexOp.dstRegNum.isVector = FALSE;
opInfo.operand.complexOp.srcRegNumA.isVector = FALSE;
opInfo.operand.complexOp.srcRegNumB.isVector = FALSE;
`endif
opInfo.operand.complexOp.dstRegNum.regNum = dstRegNum;
opInfo.operand.complexOp.srcRegNumA.regNum = srcRegNumA;
opInfo.operand.complexOp.srcRegNumB.regNum = srcRegNumB;
// 乗算の有効な結果の位置
opInfo.operand.complexOp.mulGetUpper = ( rv32mFunct3 > RV32M_FUNCT3_MUL) ;
// ALU
RISCV_DecodeComplexOpFunct3( mulCode, divCode, rv32mFunct3 );
opInfo.operand.complexOp.mulCode = mulCode;
opInfo.operand.complexOp.divCode = divCode;
opInfo.operand.complexOp.padding = '0;
opInfo.operand.complexOp.riscv_padding = '0;
// レジスタ書き込みを行うかどうか
// ゼロレジスタへの書き込みは書き込みフラグをFALSEとする
opInfo.writeReg = ( dstRegNum != ZERO_REGISTER ) ? TRUE : FALSE;
// 論理レジスタを読むかどうか
opInfo.opTypeA = OOT_REG;
opInfo.opTypeB = OOT_REG;
// 命令の種類
`ifdef RSD_MARCH_UNIFIED_MULDIV_MEM_PIPE
// Mem pipe で処理
opInfo.mopType = MOP_TYPE_MEM;
opInfo.mopSubType.memType = isMul ? MEM_MOP_TYPE_MUL : MEM_MOP_TYPE_DIV;
`else
// 剰余は除算と演算器を共有するためCOMPLEX_MOP_TYPE_DIVとする
opInfo.mopType = MOP_TYPE_COMPLEX;
opInfo.mopSubType.complexType = isMul ? COMPLEX_MOP_TYPE_MUL : COMPLEX_MOP_TYPE_DIV;
`endif
// 条件コード
opInfo.cond = COND_AL;
// 未定義命令
opInfo.unsupported = unsupported;
opInfo.undefined = FALSE;
// Serialized
opInfo.serialized = FALSE;
// Control
opInfo.valid = TRUE; // Valid outputs
endfunction
function automatic void RISCV_DecodeComplexOp(
output OpInfo [MICRO_OP_MAX_NUM-1:0] microOps,
output InsnInfo insnInfo,
input RISCV_ISF_Common isf
);
OpInfo complexOp;
MicroOpIndex mid;
//RISCVでは複数micro opへの分割は基本的に必要ないはず
RISCV_EmitComplexOp(
.opInfo( complexOp ),
.isf( isf ),
.srcRegNumA( isf.rs1 ),
.srcRegNumB( isf.rs2 ),
.dstRegNum( isf.rd ),
.unsupported( FALSE )
);
mid = 0;
for(int i = 0; i < MICRO_OP_MAX_NUM; i++) begin
EmitInvalidOp(microOps[i]);
end
// --- 1
// It begins at 1 for aligning outputs to DecodeIntReg.
microOps[1] = ModifyMicroOp(complexOp, mid, FALSE, TRUE);
mid += 1;
insnInfo.writePC = FALSE;
insnInfo.isCall = FALSE;
insnInfo.isReturn = FALSE;
insnInfo.isRelBranch = FALSE;
insnInfo.isSerialized = FALSE;
endfunction
//
// --- Misc-Mem
//
function automatic void RISCV_EmitMiscMemOp(
output OpInfo opInfo,
input RISCV_ISF_Common isf
);
RISCV_ISF_MISC_MEM isfMiscMem;
MiscMemFunct3 opFunct3;
MiscMemMicroOpOperand miscMemOp;
isfMiscMem = isf;
opFunct3 = MiscMemFunct3'(isfMiscMem.funct3);
// 論理レジスタ番号
`ifdef RSD_ENABLE_VECTOR_PATH
miscMemOp.dstRegNum.isVector = FALSE;
miscMemOp.srcRegNumA.isVector = FALSE;
miscMemOp.srcRegNumB.isVector = FALSE;
`endif
miscMemOp.dstRegNum.regNum = '0;
miscMemOp.srcRegNumA.regNum = '0;
miscMemOp.srcRegNumB.regNum = '0;
miscMemOp.padding = '0;
miscMemOp.riscv_padding = '0;
if (opFunct3 == MISC_MEM_FUNCT3_FENCE) begin
miscMemOp.fence = TRUE;
miscMemOp.fenceI = FALSE;
end
else if (opFunct3 == MISC_MEM_FUNCT3_FENCE_I) begin
miscMemOp.fence = TRUE;
miscMemOp.fenceI = TRUE;
end
else begin
miscMemOp.fence = FALSE;
miscMemOp.fenceI = FALSE;
end
opInfo.operand.miscMemOp = miscMemOp;
// レジスタ書き込みを行うかどうか
// FENCE/FENCE.I Does not write any registers
opInfo.writeReg = FALSE;
// 論理レジスタを読むかどうか
opInfo.opTypeA = OOT_IMM;
opInfo.opTypeB = OOT_IMM;
// 命令の種類
opInfo.mopType = MOP_TYPE_MEM;
opInfo.mopSubType.memType = MEM_MOP_TYPE_FENCE;
// 条件コード
opInfo.cond = COND_AL;
opInfo.valid = TRUE;
opInfo.unsupported = FALSE;
if (miscMemOp.fence) begin
opInfo.undefined = FALSE;
end
else begin
// Unknown misc mem
opInfo.undefined = TRUE;
end
// Serialized
opInfo.serialized = TRUE;
endfunction
function automatic void RISCV_DecodeMiscMem(
output OpInfo [MICRO_OP_MAX_NUM-1:0] microOps,
output InsnInfo insnInfo,
input RISCV_ISF_Common isf
);
OpInfo miscMemOp;
MicroOpIndex mid;
//RISCVでは複数micro opへの分割は基本的に必要ないはず
RISCV_EmitMiscMemOp(
.opInfo(miscMemOp),
.isf(isf)
);
// Initizalize
mid = 0;
for (int i = 0; i < MICRO_OP_MAX_NUM; i++) begin
EmitInvalidOp(microOps[i]);
end
// --- 1
// It begins at 1 for aligning outputs to DecodeIntReg.
microOps[1] = ModifyMicroOp(miscMemOp, mid, FALSE, TRUE);
insnInfo.writePC = FALSE;
insnInfo.isCall = FALSE;
insnInfo.isReturn = FALSE;
insnInfo.isRelBranch = FALSE;
insnInfo.isSerialized = TRUE;
endfunction
//
// --- System
//
function automatic void RISCV_EmitCSR_Op(
output OpInfo opInfo,
input RISCV_ISF_Common isf
);
RISCV_ISF_SYSTEM isfSystem;
SystemFunct3 opFunct3;
MemMicroOpOperand memOp; // Decoded as a memory op
isfSystem = isf;
opFunct3 = SystemFunct3'(isfSystem.funct3);
// 論理レジスタ番号
`ifdef RSD_ENABLE_VECTOR_PATH
memOp.dstRegNum.isVector = FALSE;
memOp.srcRegNumA.isVector = FALSE;
memOp.srcRegNumB.isVector = FALSE;
`endif
memOp.dstRegNum.regNum = isfSystem.rd;
memOp.srcRegNumA.regNum = isfSystem.rs1;
memOp.srcRegNumB.regNum = '0;
memOp.padding = '0;
// Don't care
memOp.isAddAddr = FALSE;
memOp.isRegAddr = FALSE;
memOp.memAccessMode = '0;
// コードの設定
unique case (opFunct3)
default: begin // SYSTEM_FUNCT3_PRIV or unknown
memOp.csrCtrl.code = CSR_WRITE;
end
SYSTEM_FUNCT3_CSR_RW, SYSTEM_FUNCT3_CSR_RW_I: begin
memOp.csrCtrl.code = CSR_WRITE;
end
SYSTEM_FUNCT3_CSR_RS, SYSTEM_FUNCT3_CSR_RS_I: begin
memOp.csrCtrl.code = CSR_SET;
end
SYSTEM_FUNCT3_CSR_RC, SYSTEM_FUNCT3_CSR_RC_I: begin
memOp.csrCtrl.code = CSR_CLEAR;
end
endcase
// CSR number
memOp.addrIn = isfSystem.funct12;
// CSR 命令の即値だけは特殊なので REG にしておき,ユニット側で対処する
memOp.csrCtrl.isImm =
(opFunct3 == SYSTEM_FUNCT3_CSR_RW ||
opFunct3 ==SYSTEM_FUNCT3_CSR_RS ||
opFunct3 ==SYSTEM_FUNCT3_CSR_RC
) ? FALSE : TRUE;
memOp.csrCtrl.imm = isfSystem.rs1; // rs1 がちょうど即値になる
opInfo.operand.memOp = memOp;
// レジスタ書き込みを行うかどうか
// CSR 系は基本全て書き込む
// ゼロレジスタへの書き込みは書き込みフラグをFALSEとする
opInfo.writeReg = (isfSystem.rd != ZERO_REGISTER) ? TRUE : FALSE;
// 論理レジスタを読むかどうか
// CSR 命令の即値だけは特殊なので REG にしておき,ユニット側で対処する
opInfo.opTypeA = OOT_REG;
opInfo.opTypeB = OOT_IMM;
// 命令の種類
opInfo.mopType = MOP_TYPE_MEM;
opInfo.mopSubType.memType = MEM_MOP_TYPE_CSR;
// 条件コード
opInfo.cond = COND_AL;
opInfo.valid = TRUE;
opInfo.unsupported = FALSE;
opInfo.undefined =
opFunct3 == SYSTEM_FUNCT3_UNDEFINED ? TRUE : FALSE;
// Serialized
opInfo.serialized = TRUE;
endfunction
function automatic void RISCV_EmitSystemOp(
output OpInfo opInfo,
input RISCV_ISF_Common isf
);
RISCV_ISF_SYSTEM isfSystem;
SystemFunct3 opFunct3;
SystemFunct12 opFunct12;
SystemMicroOpOperand systemOp;
logic undefined;
isfSystem = isf;
opFunct3 = SystemFunct3'(isfSystem.funct3);
opFunct12 = SystemFunct12'(isfSystem.funct12);
// 論理レジスタ番号
`ifdef RSD_ENABLE_VECTOR_PATH
systemOp.dstRegNum.isVector = FALSE;
systemOp.srcRegNumA.isVector = FALSE;
systemOp.srcRegNumB.isVector = FALSE;
`endif
systemOp.dstRegNum.regNum = '0;
systemOp.srcRegNumA.regNum = '0;
systemOp.srcRegNumB.regNum = '0;
systemOp.isEnv = TRUE;
systemOp.padding = '0;
systemOp.imm = '0;
undefined = FALSE;
// コードの設定
if (opFunct12 == SYSTEM_FUNCT12_WFI) begin
// NOP 扱いにしておく
opInfo.mopType = MOP_TYPE_INT;
opInfo.mopSubType.intType = INT_MOP_TYPE_ALU;
systemOp.envCode = ENV_BREAK;
end
else begin
unique case(SystemFunct12'(isfSystem.funct12))
SYSTEM_FUNCT12_ECALL: systemOp.envCode = ENV_CALL;
SYSTEM_FUNCT12_EBREAK: systemOp.envCode = ENV_BREAK;
SYSTEM_FUNCT12_MRET: systemOp.envCode = ENV_MRET;
default: begin// Unknown
systemOp.envCode = ENV_BREAK;
undefined = TRUE;
end
endcase
// 命令の種類
opInfo.mopType = MOP_TYPE_MEM;
opInfo.mopSubType.memType = MEM_MOP_TYPE_ENV;
end
opInfo.operand.systemOp = systemOp;
// レジスタ書き込みを行うかどうか
opInfo.writeReg = FALSE;
// 論理レジスタを読むかどうか
opInfo.opTypeA = OOT_IMM;
opInfo.opTypeB = OOT_IMM;
// 条件コード
opInfo.cond = COND_AL;
opInfo.valid = TRUE;
opInfo.unsupported = FALSE;
opInfo.undefined = undefined;
// Serialized
opInfo.serialized = TRUE;
endfunction
function automatic void RISCV_DecodeSystem(
output OpInfo [MICRO_OP_MAX_NUM-1:0] microOps,
output InsnInfo insnInfo,
input RISCV_ISF_Common isf
);
OpInfo opInfo;
MicroOpIndex mid;
//RISCVでは複数micro opへの分割は基本的に必要ないはず
if (SystemFunct3'(isf.funct3) == SYSTEM_FUNCT3_PRIV) begin
RISCV_EmitSystemOp(.opInfo(opInfo), .isf(isf));
end
else begin
RISCV_EmitCSR_Op(.opInfo(opInfo), .isf(isf));
end
// Initizalize
mid = 0;
for (int i = 0; i < MICRO_OP_MAX_NUM; i++) begin
EmitInvalidOp(microOps[i]);
end
// --- 1
// It begins at 1 for aligning outputs to DecodeIntReg.
microOps[1] = ModifyMicroOp(opInfo, mid, FALSE, TRUE);
insnInfo.writePC = FALSE;
insnInfo.isCall = FALSE;
insnInfo.isReturn = FALSE;
insnInfo.isRelBranch = FALSE;
insnInfo.isSerialized = TRUE; // A system instruction must be serialized
endfunction
function automatic void RISCV_EmitIllegalOp(
output OpInfo opInfo,
input logic illegalPC
);
RISCV_ISF_SYSTEM isfSystem;
SystemFunct3 opFunct3;
SystemFunct12 opFunct12;
SystemMicroOpOperand systemOp;
logic undefined;
// 論理レジスタ番号
`ifdef RSD_ENABLE_VECTOR_PATH
systemOp.dstRegNum.isVector = FALSE;
systemOp.srcRegNumA.isVector = FALSE;
systemOp.srcRegNumB.isVector = FALSE;
`endif
systemOp.dstRegNum.regNum = '0;
systemOp.srcRegNumA.regNum = '0;
systemOp.srcRegNumB.regNum = '0;
systemOp.isEnv = TRUE;
systemOp.padding = '0;
systemOp.imm = '0;
undefined = FALSE;
// コードの設定
systemOp.envCode = illegalPC ? ENV_INSN_VIOLATION : ENV_INSN_ILLEGAL;
// 命令の種類
opInfo.mopType = MOP_TYPE_MEM;
opInfo.mopSubType.memType = MEM_MOP_TYPE_ENV;
opInfo.operand.systemOp = systemOp;
// レジスタ書き込みを行うかどうか
opInfo.writeReg = FALSE;
// 論理レジスタを読むかどうか
opInfo.opTypeA = OOT_IMM;
opInfo.opTypeB = OOT_IMM;
// 条件コード
opInfo.cond = COND_AL;
opInfo.valid = TRUE;
opInfo.unsupported = FALSE;
opInfo.undefined = undefined;
// Serialized
opInfo.serialized = TRUE;
endfunction
function automatic void RISCV_DecodeIllegal(
output OpInfo [MICRO_OP_MAX_NUM-1:0] microOps,
output InsnInfo insnInfo,
input RISCV_ISF_Common isf,
input illegalPC
);
OpInfo opInfo;
MicroOpIndex mid;
RISCV_EmitIllegalOp(opInfo, illegalPC);
// Initizalize
mid = 0;
for (int i = 0; i < MICRO_OP_MAX_NUM; i++) begin
EmitInvalidOp(microOps[i]);
end
// --- 1
// It begins at 1 for aligning outputs to DecodeIntReg.
microOps[1] = ModifyMicroOp(opInfo, mid, FALSE, TRUE);
insnInfo.writePC = FALSE;
insnInfo.isCall = FALSE;
insnInfo.isReturn = FALSE;
insnInfo.isRelBranch = FALSE;
insnInfo.isSerialized = TRUE; // A system instruction must be serialized
endfunction
//
// --- DecodeStageでインスタンシエートされるモジュール
//
module Decoder(
input
InsnPath insn, // Input instruction
logic illegalPC,
output
OpInfo [MICRO_OP_MAX_NUM-1:0] microOps, // Outputed micro ops
InsnInfo insnInfo // Whether this instruction is branch or not.
);
RISCV_ISF_Common isf;
RV32MFunct7 rv32mFunct7;
logic undefined;
always_comb begin
isf = insn;
rv32mFunct7 = RV32MFunct7'(isf.funct7);
insnInfo.writePC = FALSE;
insnInfo.isCall = FALSE;
insnInfo.isReturn = FALSE;
insnInfo.isRelBranch = FALSE;
insnInfo.isSerialized = FALSE;
case (isf.opCode)
// S: LOAD, STORE
RISCV_LD, RISCV_ST : begin
RISCV_DecodeMemOp(microOps, insnInfo, insn);
end
// B: BRANCH
RISCV_BR : begin
RISCV_DecodeBranch(microOps, insnInfo, insn);
end
// I: JALR
RISCV_JALR : begin
RISCV_DecodeJALR(microOps, insnInfo, insn);
end
// J: JAL
RISCV_JAL : begin
RISCV_DecodeJAL(microOps, insnInfo, insn);
end
// I: OP-IMM
RISCV_OP_IMM : begin
RISCV_DecodeOpImm(microOps, insnInfo, insn);
end
// R: OP
RISCV_OP : begin
if (rv32mFunct7 == RV32M_FUNCT7_ALL) begin
RISCV_DecodeComplexOp(microOps, insnInfo, insn);
end
else begin
RISCV_DecodeOp(microOps, insnInfo, insn);
end
end
// U: AUIPC, LUI
RISCV_AUIPC, RISCV_LUI : begin
RISCV_DecodeUTypeInst(microOps, insnInfo, insn);
end
// I: MISC-MEM (fence/fence.i)
RISCV_MISC_MEM : begin
RISCV_DecodeMiscMem(microOps, insnInfo, insn);
end
// I: SYSTEM (ebreak/ecall/csr)
RISCV_SYSTEM : begin
RISCV_DecodeSystem(microOps, insnInfo, insn);
end
default : begin
RISCV_DecodeIllegal(microOps, insnInfo, insn, illegalPC);
end
endcase
undefined = FALSE;
for(int i = 0; i < MICRO_OP_MAX_NUM; i++) begin
if(microOps[i].undefined || microOps[i].unsupported) begin
undefined = TRUE;
end
end
if (undefined || illegalPC) begin
RISCV_DecodeIllegal(microOps, insnInfo, insn, illegalPC);
end
end
endmodule : Decoder
10bd31ad3This file is pinned to the selected release. Download the original to open it in your design tool.