Merge pull request #173 from davidharrishmc/dev

Test improvements including FPU coverage
This commit is contained in:
Ross Thompson 2023-03-29 13:00:25 -05:00 committed by GitHub
commit 289b1ac3f6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 175 additions and 75 deletions

View File

@ -75,44 +75,42 @@ module fctrl (
logic [1:0] FResSelD; // Select one of the results that finish in the memory stage logic [1:0] FResSelD; // Select one of the results that finish in the memory stage
logic [2:0] FrmD, FrmE; // FP rounding mode logic [2:0] FrmD, FrmE; // FP rounding mode
logic [`FMTBITS-1:0] FmtD; // FP format logic [`FMTBITS-1:0] FmtD; // FP format
logic [1:0] Fmt; // format - before possible reduction logic [1:0] Fmt, Fmt2; // format - before possible reduction
logic SupportedFmt; // is the format supported logic SupportedFmt; // is the format supported
logic SupportedFmt2; // is the source format supported for fp -> fp
logic FCvtIntD, FCvtIntM; // convert to integer opperation logic FCvtIntD, FCvtIntM; // convert to integer opperation
// FPU Instruction Decoder // FPU Instruction Decoder
assign Fmt = Funct7D[1:0]; assign Fmt = Funct7D[1:0];
assign Fmt2 = Rs2D[1:0]; // source format for fcvt fp->fp
// Note: only Fmt is checked; fcvt does not check destination format
assign SupportedFmt = (Fmt == 2'b00 | (Fmt == 2'b01 & `D_SUPPORTED) | assign SupportedFmt = (Fmt == 2'b00 | (Fmt == 2'b01 & `D_SUPPORTED) |
(Fmt == 2'b10 & `ZFH_SUPPORTED) | (Fmt == 2'b11 & `Q_SUPPORTED)); (Fmt == 2'b10 & `ZFH_SUPPORTED) | (Fmt == 2'b11 & `Q_SUPPORTED));
assign SupportedFmt2 = (Fmt2 == 2'b00 | (Fmt2 == 2'b01 & `D_SUPPORTED) |
(Fmt2 == 2'b10 & `ZFH_SUPPORTED) | (Fmt2 == 2'b11 & `Q_SUPPORTED));
// decode the instruction // decode the instruction
always_comb // ControlsD: FRegWrite_FWriteInt_FResSel_PostProcSel_FOpCtrl_FDivStart_IllegalFPUInstr_FCvtInt
always_comb
if (STATUS_FS == 2'b00) // FPU instructions are illegal when FPU is disabled if (STATUS_FS == 2'b00) // FPU instructions are illegal when FPU is disabled
ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0;
else if (OpD != 7'b0000111 & OpD != 7'b0100111 & ~SupportedFmt) else if (OpD != 7'b0000111 & OpD != 7'b0100111 & ~SupportedFmt)
ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // for anything other than loads and stores, check for supported format ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // for anything other than loads and stores, check for supported format
else case(OpD) else begin
// FRegWrite_FWriteInt_FResSel_PostProcSel_FOpCtrl_FDivStart_IllegalFPUInstr_FCvtInt ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // default: illegal FPU instruction
/* verilator lint_off CASEINCOMPLETE */ // default value above has priority so no other default needed
case(OpD)
7'b0000111: case(Funct3D) 7'b0000111: case(Funct3D)
3'b010: ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flw 3'b010: ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flw
3'b011: if (`D_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // fld 3'b011: if (`D_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // fld
else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // fld not supported
3'b100: if (`Q_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flq 3'b100: if (`Q_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flq
else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // flq not supported
3'b001: if (`ZFH_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flh 3'b001: if (`ZFH_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flh
else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // flh not supported
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction
endcase endcase
7'b0100111: case(Funct3D) 7'b0100111: case(Funct3D)
3'b010: ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsw 3'b010: ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsw
3'b011: if (`D_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsd 3'b011: if (`D_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsd
else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // fsd not supported
3'b100: if (`Q_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsq 3'b100: if (`Q_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsq
else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // fsq not supported
3'b001: if (`ZFH_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsh 3'b001: if (`ZFH_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsh
else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // fsh not supported
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction
endcase endcase
7'b1000011: ControlsD = `FCTRLW'b1_0_01_10_000_0_0_0; // fmadd 7'b1000011: ControlsD = `FCTRLW'b1_0_01_10_000_0_0_0; // fmadd
7'b1000111: ControlsD = `FCTRLW'b1_0_01_10_001_0_0_0; // fmsub 7'b1000111: ControlsD = `FCTRLW'b1_0_01_10_001_0_0_0; // fmsub
@ -128,56 +126,82 @@ module fctrl (
3'b000: ControlsD = `FCTRLW'b1_0_00_xx_000_0_0_0; // fsgnj 3'b000: ControlsD = `FCTRLW'b1_0_00_xx_000_0_0_0; // fsgnj
3'b001: ControlsD = `FCTRLW'b1_0_00_xx_001_0_0_0; // fsgnjn 3'b001: ControlsD = `FCTRLW'b1_0_00_xx_001_0_0_0; // fsgnjn
3'b010: ControlsD = `FCTRLW'b1_0_00_xx_010_0_0_0; // fsgnjx 3'b010: ControlsD = `FCTRLW'b1_0_00_xx_010_0_0_0; // fsgnjx
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction endcase
endcase
7'b00101??: case(Funct3D) 7'b00101??: case(Funct3D)
3'b000: ControlsD = `FCTRLW'b1_0_00_xx_110_0_0_0; // fmin 3'b000: ControlsD = `FCTRLW'b1_0_00_xx_110_0_0_0; // fmin
3'b001: ControlsD = `FCTRLW'b1_0_00_xx_101_0_0_0; // fmax 3'b001: ControlsD = `FCTRLW'b1_0_00_xx_101_0_0_0; // fmax
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction
endcase endcase
7'b10100??: case(Funct3D) 7'b10100??: case(Funct3D)
3'b010: ControlsD = `FCTRLW'b0_1_00_xx_010_0_0_0; // feq 3'b010: ControlsD = `FCTRLW'b0_1_00_xx_010_0_0_0; // feq
3'b001: ControlsD = `FCTRLW'b0_1_00_xx_001_0_0_0; // flt 3'b001: ControlsD = `FCTRLW'b0_1_00_xx_001_0_0_0; // flt
3'b000: ControlsD = `FCTRLW'b0_1_00_xx_011_0_0_0; // fle 3'b000: ControlsD = `FCTRLW'b0_1_00_xx_011_0_0_0; // fle
default: ControlsD = `FCTRLW'b0_0_00_xx_000__0_1_0; // non-implemented instruction
endcase endcase
7'b11100??: if (Funct3D == 3'b001 & Rs2D == 5'b00000) 7'b11100??: if (Funct3D == 3'b001 & Rs2D == 5'b00000)
ControlsD = `FCTRLW'b0_1_10_xx_000_0_0_0; // fclass ControlsD = `FCTRLW'b0_1_10_xx_000_0_0_0; // fclass
else if (Funct3D[1:0] == 2'b00) ControlsD = `FCTRLW'b0_1_11_xx_000_0_0_0; // fmv.x.w to int reg else if (Funct3D == 3'b000 & Rs2D == 5'b00000)
else if (Funct3D[1:0] == 2'b01) ControlsD = `FCTRLW'b0_1_11_xx_000_0_0_0; // fmv.x.d to int reg ControlsD = `FCTRLW'b0_1_11_xx_000_0_0_0; // fmv.x.w / fmv.x.d to int register
else ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction 7'b111100?: if (Funct3D == 3'b000 & Rs2D == 5'b00000)
7'b1101000: case(Rs2D[1:0]) ControlsD = `FCTRLW'b1_0_00_xx_011_0_0_0; // fmv.w.x / fmv.d.x to fp reg
2'b00: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.s.w w->s 7'b0100000: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b00)
2'b01: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.s.wu wu->s ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0; // fcvt.s.(d/q/h)
2'b10: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.s.l l->s 7'b0100001: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b01)
2'b11: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.s.lu lu->s ControlsD = `FCTRLW'b1_0_01_00_001_0_0_0; // fcvt.d.(s/h/q)
7'b0100010: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b10)
ControlsD = `FCTRLW'b1_0_01_00_010_0_0_0; // fcvt.h.(s/d/q)
7'b0100011: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b11)
ControlsD = `FCTRLW'b1_0_01_00_011_0_0_0; // fcvt.q.(s/h/d)
7'b1101000: case(Rs2D)
5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.s.w w->s
5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.s.wu wu->s
5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.s.l l->s
5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.s.lu lu->s
endcase endcase
7'b1100000: case(Rs2D[1:0]) 7'b1100000: case(Rs2D)
2'b00: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.s s->w 5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.s s->w
2'b01: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.s s->wu 5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.s s->wu
2'b10: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.s s->l 5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.s s->l
2'b11: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.s s->lu 5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.s s->lu
endcase endcase
7'b1111000: ControlsD = `FCTRLW'b1_0_00_xx_011_0_0_0; // fmv.w.x to fp reg 7'b1101001: case(Rs2D)
7'b0100000: ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0; // fcvt.s.d 5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.d.w w->d
7'b1101001: case(Rs2D[1:0]) 5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.d.wu wu->d
2'b00: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.d.w w->d 5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.d.l l->d
2'b01: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.d.wu wu->d 5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.d.lu lu->d
2'b10: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.d.l l->d
2'b11: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.d.lu lu->d
endcase endcase
7'b1100001: case(Rs2D[1:0]) 7'b1100001: case(Rs2D)
2'b00: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.d d->w 5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.d d->w
2'b01: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.d d->wu 5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.d d->wu
2'b10: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.d d->l 5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.d d->l
2'b11: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.d d->lu 5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.d d->lu
endcase
7'b1101010: case(Rs2D)
5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.h.w w->h
5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.h.wu wu->h
5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.h.l l->h
5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.h.lu lu->h
endcase
7'b1100010: case(Rs2D)
5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.h h->w
5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.h h->wu
5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.h h->l
5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.h h->lu
endcase
7'b1101011: case(Rs2D)
5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.q.w w->q
5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.q.wu wu->q
5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.q.l l->q
5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.q.lu lu->q
endcase
7'b1100011: case(Rs2D)
5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.q q->w
5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.q q->wu
5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.q q->l
5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.q q->lu
endcase endcase
7'b1111001: ControlsD = `FCTRLW'b1_0_00_xx_011_0_0_0; // fmv.d.x to fp reg
7'b0100001: ControlsD = `FCTRLW'b1_0_01_00_001_0_0_0; // fcvt.d.s
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction
endcase endcase
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction endcase
endcase /* verilator lint_off CASEINCOMPLETE */
end
// unswizzle control bits // unswizzle control bits
assign #1 {FRegWriteD, FWriteIntD, FResSelD, PostProcSelD, OpCtrlD, FDivStartD, IllegalFPUInstrD, FCvtIntD} = ControlsD; assign #1 {FRegWriteD, FWriteIntD, FResSelD, PostProcSelD, OpCtrlD, FDivStartD, IllegalFPUInstrD, FCvtIntD} = ControlsD;

View File

@ -55,7 +55,7 @@ module csr #(parameter
input logic [4:0] SetFflagsM, // Set floating point flag bits in FCSR input logic [4:0] SetFflagsM, // Set floating point flag bits in FCSR
input logic [1:0] NextPrivilegeModeM, // STATUS bits updated based on next privilege mode input logic [1:0] NextPrivilegeModeM, // STATUS bits updated based on next privilege mode
input logic [1:0] PrivilegeModeW, // current privilege mode input logic [1:0] PrivilegeModeW, // current privilege mode
input logic [`LOG_XLEN-1:0] CauseM, // Trap cause input logic [3:0] CauseM, // Trap cause
input logic SelHPTW, // hardware page table walker active, so base endianness on supervisor mode input logic SelHPTW, // hardware page table walker active, so base endianness on supervisor mode
// inputs for performance counters // inputs for performance counters
input logic LoadStallD, input logic LoadStallD,
@ -79,7 +79,7 @@ module csr #(parameter
// outputs from CSRs // outputs from CSRs
output logic [1:0] STATUS_MPP, output logic [1:0] STATUS_MPP,
output logic STATUS_SPP, STATUS_TSR, STATUS_TVM, output logic STATUS_SPP, STATUS_TSR, STATUS_TVM,
output logic [`XLEN-1:0] MEDELEG_REGW, output logic [15:0] MEDELEG_REGW,
output logic [`XLEN-1:0] SATP_REGW, output logic [`XLEN-1:0] SATP_REGW,
output logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, output logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW,
output logic STATUS_MIE, STATUS_SIE, output logic STATUS_MIE, STATUS_SIE,
@ -107,7 +107,8 @@ module csr #(parameter
logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM; logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM;
logic CSRMWriteM, CSRSWriteM, CSRUWriteM; logic CSRMWriteM, CSRSWriteM, CSRUWriteM;
logic WriteFRMM, WriteFFLAGSM; logic WriteFRMM, WriteFFLAGSM;
logic [`XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextCauseM, NextMtvalM; logic [`XLEN-1:0] UnalignedNextEPCM, NextEPCM, NextMtvalM;
logic [4:0] NextCauseM;
logic [11:0] CSRAdrM; logic [11:0] CSRAdrM;
logic IllegalCSRCAccessM, IllegalCSRMAccessM, IllegalCSRSAccessM, IllegalCSRUAccessM; logic IllegalCSRCAccessM, IllegalCSRMAccessM, IllegalCSRSAccessM, IllegalCSRUAccessM;
logic InsufficientCSRPrivilegeM; logic InsufficientCSRPrivilegeM;
@ -153,7 +154,7 @@ module csr #(parameter
logic VectoredM; logic VectoredM;
logic [`XLEN-1:0] TVecPlusCauseM; logic [`XLEN-1:0] TVecPlusCauseM;
assign VectoredM = InterruptM & (TVecM[1:0] == 2'b01); assign VectoredM = InterruptM & (TVecM[1:0] == 2'b01);
assign TVecPlusCauseM = {TVecAlignedM[`XLEN-1:6], CauseM[3:0], 2'b00}; // 64-byte alignment allows concatenation rather than addition assign TVecPlusCauseM = {TVecAlignedM[`XLEN-1:6], CauseM, 2'b00}; // 64-byte alignment allows concatenation rather than addition
mux2 #(`XLEN) trapvecmux(TVecAlignedM, TVecPlusCauseM, VectoredM, TrapVectorM); mux2 #(`XLEN) trapvecmux(TVecAlignedM, TVecPlusCauseM, VectoredM, TrapVectorM);
end else end else
assign TrapVectorM = TVecAlignedM; assign TrapVectorM = TVecAlignedM;
@ -196,7 +197,7 @@ module csr #(parameter
assign CSRAdrM = InstrM[31:20]; assign CSRAdrM = InstrM[31:20];
assign UnalignedNextEPCM = TrapM ? ((wfiM & IntPendingM) ? PCM+4 : PCM) : CSRWriteValM; assign UnalignedNextEPCM = TrapM ? ((wfiM & IntPendingM) ? PCM+4 : PCM) : CSRWriteValM;
assign NextEPCM = `C_SUPPORTED ? {UnalignedNextEPCM[`XLEN-1:1], 1'b0} : {UnalignedNextEPCM[`XLEN-1:2], 2'b00}; // 3.1.15 alignment assign NextEPCM = `C_SUPPORTED ? {UnalignedNextEPCM[`XLEN-1:1], 1'b0} : {UnalignedNextEPCM[`XLEN-1:2], 2'b00}; // 3.1.15 alignment
assign NextCauseM = TrapM ? {InterruptM, {(`XLEN-`LOG_XLEN-1){1'b0}}, CauseM}: CSRWriteValM; assign NextCauseM = TrapM ? {InterruptM, CauseM}: {CSRWriteValM[`XLEN-1], CSRWriteValM[3:0]};
assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValM; assign NextMtvalM = TrapM ? NextFaultMtvalM : CSRWriteValM;
assign CSRMWriteM = CSRWriteM & (PrivilegeModeW == `M_MODE); assign CSRMWriteM = CSRWriteM & (PrivilegeModeW == `M_MODE);
assign CSRSWriteM = CSRWriteM & (|PrivilegeModeW); assign CSRSWriteM = CSRWriteM & (|PrivilegeModeW);

View File

@ -69,20 +69,21 @@ module csrm #(parameter
DSCRATCH1 = 12'h7B3, DSCRATCH1 = 12'h7B3,
// Constants // Constants
ZERO = {(`XLEN){1'b0}}, ZERO = {(`XLEN){1'b0}},
MEDELEG_MASK = ~(ZERO | `XLEN'b1 << 11), MEDELEG_MASK = 16'hB3FF,
MIDELEG_MASK = 12'h222 // we choose to not make machine interrupts delegable MIDELEG_MASK = 12'h222 // we choose to not make machine interrupts delegable
) ( ) (
input logic clk, reset, input logic clk, reset,
input logic InstrValidNotFlushedM, input logic InstrValidNotFlushedM,
input logic CSRMWriteM, MTrapM, input logic CSRMWriteM, MTrapM,
input logic [11:0] CSRAdrM, input logic [11:0] CSRAdrM,
input logic [`XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, MSTATUS_REGW, MSTATUSH_REGW, input logic [`XLEN-1:0] NextEPCM, NextMtvalM, MSTATUS_REGW, MSTATUSH_REGW,
input logic [4:0] NextCauseM,
input logic [`XLEN-1:0] CSRWriteValM, input logic [`XLEN-1:0] CSRWriteValM,
input logic [11:0] MIP_REGW, MIE_REGW, input logic [11:0] MIP_REGW, MIE_REGW,
output logic [`XLEN-1:0] CSRMReadValM, MTVEC_REGW, output logic [`XLEN-1:0] CSRMReadValM, MTVEC_REGW,
output logic [`XLEN-1:0] MEPC_REGW, output logic [`XLEN-1:0] MEPC_REGW,
output logic [31:0] MCOUNTEREN_REGW, MCOUNTINHIBIT_REGW, output logic [31:0] MCOUNTEREN_REGW, MCOUNTINHIBIT_REGW,
output logic [`XLEN-1:0] MEDELEG_REGW, output logic [15:0] MEDELEG_REGW,
output logic [11:0] MIDELEG_REGW, output logic [11:0] MIDELEG_REGW,
output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0], output var logic [7:0] PMPCFG_ARRAY_REGW[`PMP_ENTRIES-1:0],
output var logic [`PA_BITS-3:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0], output var logic [`PA_BITS-3:0] PMPADDR_ARRAY_REGW [`PMP_ENTRIES-1:0],
@ -91,8 +92,8 @@ module csrm #(parameter
); );
logic [`XLEN-1:0] MISA_REGW, MHARTID_REGW; logic [`XLEN-1:0] MISA_REGW, MHARTID_REGW;
logic [`XLEN-1:0] MSCRATCH_REGW; logic [`XLEN-1:0] MSCRATCH_REGW, MTVAL_REGW;
logic [`XLEN-1:0] MCAUSE_REGW, MTVAL_REGW; logic [4:0] MCAUSE_REGW;
logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM; logic WriteMTVECM, WriteMEDELEGM, WriteMIDELEGM;
logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM; logic WriteMSCRATCHM, WriteMEPCM, WriteMCAUSEM, WriteMTVALM;
logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM; logic WriteMCOUNTERENM, WriteMCOUNTINHIBITM;
@ -150,13 +151,13 @@ module csrm #(parameter
// CSRs // CSRs
flopenr #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, MTVEC_REGW); flopenr #(`XLEN) MTVECreg(clk, reset, WriteMTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, MTVEC_REGW);
if (`S_SUPPORTED) begin:deleg // DELEG registers should exist if (`S_SUPPORTED) begin:deleg // DELEG registers should exist
flopenr #(`XLEN) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM & MEDELEG_MASK, MEDELEG_REGW); flopenr #(16) MEDELEGreg(clk, reset, WriteMEDELEGM, CSRWriteValM[15:0] & MEDELEG_MASK, MEDELEG_REGW);
flopenr #(12) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM[11:0] & MIDELEG_MASK, MIDELEG_REGW); flopenr #(12) MIDELEGreg(clk, reset, WriteMIDELEGM, CSRWriteValM[11:0] & MIDELEG_MASK, MIDELEG_REGW);
end else assign {MEDELEG_REGW, MIDELEG_REGW} = 0; end else assign {MEDELEG_REGW, MIDELEG_REGW} = 0;
flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW); flopenr #(`XLEN) MSCRATCHreg(clk, reset, WriteMSCRATCHM, CSRWriteValM, MSCRATCH_REGW);
flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW); flopenr #(`XLEN) MEPCreg(clk, reset, WriteMEPCM, NextEPCM, MEPC_REGW);
flopenr #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_REGW); flopenr #(5) MCAUSEreg(clk, reset, WriteMCAUSEM, NextCauseM, MCAUSE_REGW);
if(`QEMU) assign MTVAL_REGW = `XLEN'b0; // MTVAL tied to 0 in QEMU configuration if(`QEMU) assign MTVAL_REGW = `XLEN'b0; // MTVAL tied to 0 in QEMU configuration
else flopenr #(`XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW); else flopenr #(`XLEN) MTVALreg(clk, reset, WriteMTVALM, NextMtvalM, MTVAL_REGW);
flopenr #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], MCOUNTINHIBIT_REGW); flopenr #(32) MCOUNTINHIBITreg(clk, reset, WriteMCOUNTINHIBITM, CSRWriteValM[31:0], MCOUNTINHIBIT_REGW);
@ -192,13 +193,13 @@ module csrm #(parameter
MSTATUS: CSRMReadValM = MSTATUS_REGW; MSTATUS: CSRMReadValM = MSTATUS_REGW;
MSTATUSH: CSRMReadValM = MSTATUSH_REGW; MSTATUSH: CSRMReadValM = MSTATUSH_REGW;
MTVEC: CSRMReadValM = MTVEC_REGW; MTVEC: CSRMReadValM = MTVEC_REGW;
MEDELEG: CSRMReadValM = MEDELEG_REGW; MEDELEG: CSRMReadValM = {{(`XLEN-16){1'b0}}, MEDELEG_REGW};
MIDELEG: CSRMReadValM = {{(`XLEN-12){1'b0}}, MIDELEG_REGW}; MIDELEG: CSRMReadValM = {{(`XLEN-12){1'b0}}, MIDELEG_REGW};
MIP: CSRMReadValM = {{(`XLEN-12){1'b0}}, MIP_REGW}; MIP: CSRMReadValM = {{(`XLEN-12){1'b0}}, MIP_REGW};
MIE: CSRMReadValM = {{(`XLEN-12){1'b0}}, MIE_REGW}; MIE: CSRMReadValM = {{(`XLEN-12){1'b0}}, MIE_REGW};
MSCRATCH: CSRMReadValM = MSCRATCH_REGW; MSCRATCH: CSRMReadValM = MSCRATCH_REGW;
MEPC: CSRMReadValM = MEPC_REGW; MEPC: CSRMReadValM = MEPC_REGW;
MCAUSE: CSRMReadValM = MCAUSE_REGW; MCAUSE: CSRMReadValM = {MCAUSE_REGW[4], {(`XLEN-5){1'b0}}, MCAUSE_REGW[3:0]};
MTVAL: CSRMReadValM = MTVAL_REGW; MTVAL: CSRMReadValM = MTVAL_REGW;
MTINST: CSRMReadValM = 0; // implemented as trivial zero MTINST: CSRMReadValM = 0; // implemented as trivial zero
MCOUNTEREN:CSRMReadValM = {{(`XLEN-32){1'b0}}, MCOUNTEREN_REGW}; MCOUNTEREN:CSRMReadValM = {{(`XLEN-32){1'b0}}, MCOUNTEREN_REGW};

View File

@ -48,7 +48,8 @@ module csrs #(parameter
input logic InstrValidNotFlushedM, input logic InstrValidNotFlushedM,
input logic CSRSWriteM, STrapM, input logic CSRSWriteM, STrapM,
input logic [11:0] CSRAdrM, input logic [11:0] CSRAdrM,
input logic [`XLEN-1:0] NextEPCM, NextCauseM, NextMtvalM, SSTATUS_REGW, input logic [`XLEN-1:0] NextEPCM, NextMtvalM, SSTATUS_REGW,
input logic [4:0] NextCauseM,
input logic STATUS_TVM, input logic STATUS_TVM,
input logic MCOUNTEREN_TM, // TM bit (1) of MCOUNTEREN; cause illegal instruction when trying to access STIMECMP if clear input logic MCOUNTEREN_TM, // TM bit (1) of MCOUNTEREN; cause illegal instruction when trying to access STIMECMP if clear
input logic [`XLEN-1:0] CSRWriteValM, input logic [`XLEN-1:0] CSRWriteValM,
@ -73,7 +74,7 @@ module csrs #(parameter
logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM; logic WriteSCAUSEM, WriteSTVALM, WriteSATPM, WriteSCOUNTERENM;
logic WriteSTIMECMPM, WriteSTIMECMPHM; logic WriteSTIMECMPM, WriteSTIMECMPHM;
logic [`XLEN-1:0] SSCRATCH_REGW, STVAL_REGW; logic [`XLEN-1:0] SSCRATCH_REGW, STVAL_REGW;
logic [`XLEN-1:0] SCAUSE_REGW; logic [4:0] SCAUSE_REGW;
logic [63:0] STIMECMP_REGW; logic [63:0] STIMECMP_REGW;
// write enables // write enables
@ -93,7 +94,7 @@ module csrs #(parameter
flopenr #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW); flopenr #(`XLEN) STVECreg(clk, reset, WriteSTVECM, {CSRWriteValM[`XLEN-1:2], 1'b0, CSRWriteValM[0]}, STVEC_REGW);
flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW); flopenr #(`XLEN) SSCRATCHreg(clk, reset, WriteSSCRATCHM, CSRWriteValM, SSCRATCH_REGW);
flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW); flopenr #(`XLEN) SEPCreg(clk, reset, WriteSEPCM, NextEPCM, SEPC_REGW);
flopenr #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, SCAUSE_REGW); flopenr #(5) SCAUSEreg(clk, reset, WriteSCAUSEM, NextCauseM, SCAUSE_REGW);
flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW); flopenr #(`XLEN) STVALreg(clk, reset, WriteSTVALM, NextMtvalM, STVAL_REGW);
if (`VIRTMEM_SUPPORTED) if (`VIRTMEM_SUPPORTED)
flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW); flopenr #(`XLEN) SATPreg(clk, reset, WriteSATPM, CSRWriteValM, SATP_REGW);
@ -126,7 +127,7 @@ module csrs #(parameter
SIE: CSRSReadValM = {{(`XLEN-12){1'b0}}, MIE_REGW & 12'h222 & MIDELEG_REGW}; // only read supervisor fields SIE: CSRSReadValM = {{(`XLEN-12){1'b0}}, MIE_REGW & 12'h222 & MIDELEG_REGW}; // only read supervisor fields
SSCRATCH: CSRSReadValM = SSCRATCH_REGW; SSCRATCH: CSRSReadValM = SSCRATCH_REGW;
SEPC: CSRSReadValM = SEPC_REGW; SEPC: CSRSReadValM = SEPC_REGW;
SCAUSE: CSRSReadValM = SCAUSE_REGW; SCAUSE: CSRSReadValM = {SCAUSE_REGW[4], {(`XLEN-5){1'b0}}, SCAUSE_REGW[3:0]};
STVAL: CSRSReadValM = STVAL_REGW; STVAL: CSRSReadValM = STVAL_REGW;
SATP: if (`VIRTMEM_SUPPORTED & (PrivilegeModeW == `M_MODE | ~STATUS_TVM)) CSRSReadValM = SATP_REGW; SATP: if (`VIRTMEM_SUPPORTED & (PrivilegeModeW == `M_MODE | ~STATUS_TVM)) CSRSReadValM = SATP_REGW;
else begin else begin

View File

@ -96,8 +96,8 @@ module privileged (
output logic WFIStallM // Stall in Memory stage for WFI until interrupt or timeout output logic WFIStallM // Stall in Memory stage for WFI until interrupt or timeout
); );
logic [`LOG_XLEN-1:0] CauseM; // trap cause logic [3:0] CauseM; // trap cause
logic [`XLEN-1:0] MEDELEG_REGW; // exception delegation CSR logic [15:0] MEDELEG_REGW; // exception delegation CSR
logic [11:0] MIDELEG_REGW; // interrupt delegation CSR logic [11:0] MIDELEG_REGW; // interrupt delegation CSR
logic sretM, mretM; // supervisor / machine return instruction logic sretM, mretM; // supervisor / machine return instruction
logic IllegalCSRAccessM; // Illegal access to CSR logic IllegalCSRAccessM; // Illegal access to CSR

View File

@ -38,7 +38,7 @@ module trap (
input logic wfiM, // wait for interrupt instruction input logic wfiM, // wait for interrupt instruction
input logic [1:0] PrivilegeModeW, // current privilege mode input logic [1:0] PrivilegeModeW, // current privilege mode
input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, // interrupt pending, enabled, and delegate CSRs input logic [11:0] MIP_REGW, MIE_REGW, MIDELEG_REGW, // interrupt pending, enabled, and delegate CSRs
input logic [`XLEN-1:0] MEDELEG_REGW, // exception delegation SR input logic [15:0] MEDELEG_REGW, // exception delegation SR
input logic STATUS_MIE, STATUS_SIE, // machine/supervisor interrupt enables input logic STATUS_MIE, STATUS_SIE, // machine/supervisor interrupt enables
input logic InstrValidM, // current instruction is valid, not flushed input logic InstrValidM, // current instruction is valid, not flushed
input logic CommittedM, CommittedF, // LSU/IFU has committed to a bus operation that can't be interrupted input logic CommittedM, CommittedF, // LSU/IFU has committed to a bus operation that can't be interrupted
@ -49,7 +49,7 @@ module trap (
output logic IntPendingM, // Interrupt is pending, might occur if enabled output logic IntPendingM, // Interrupt is pending, might occur if enabled
output logic DelegateM, // Delegate trap to supervisor handler output logic DelegateM, // Delegate trap to supervisor handler
output logic WFIStallM, // Stall due to WFI instruction output logic WFIStallM, // Stall due to WFI instruction
output logic [`LOG_XLEN-1:0] CauseM // trap cause output logic [3:0] CauseM // trap cause
); );
logic MIntGlobalEnM, SIntGlobalEnM; // Global interupt enables logic MIntGlobalEnM, SIntGlobalEnM; // Global interupt enables
@ -72,7 +72,7 @@ module trap (
assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW); assign EnabledIntsM = ({12{MIntGlobalEnM}} & PendingIntsM & ~MIDELEG_REGW | {12{SIntGlobalEnM}} & PendingIntsM & MIDELEG_REGW);
assign ValidIntsM = {12{~Committed}} & EnabledIntsM; assign ValidIntsM = {12{~Committed}} & EnabledIntsM;
assign InterruptM = (|ValidIntsM) & InstrValidM; // suppress interrupt if the memory system has partially processed a request. assign InterruptM = (|ValidIntsM) & InstrValidM; // suppress interrupt if the memory system has partially processed a request.
assign DelegateM = `S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM[3:0]] : MEDELEG_REGW[CauseM]) & assign DelegateM = `S_SUPPORTED & (InterruptM ? MIDELEG_REGW[CauseM] : MEDELEG_REGW[CauseM]) &
(PrivilegeModeW == `U_MODE | PrivilegeModeW == `S_MODE); (PrivilegeModeW == `U_MODE | PrivilegeModeW == `S_MODE);
assign WFIStallM = wfiM & ~IntPendingM; assign WFIStallM = wfiM & ~IntPendingM;
@ -109,7 +109,7 @@ module trap (
else if (IllegalInstrFaultM) CauseM = 2; else if (IllegalInstrFaultM) CauseM = 2;
else if (InstrMisalignedFaultM) CauseM = 0; else if (InstrMisalignedFaultM) CauseM = 0;
else if (BreakpointFaultM) CauseM = 3; else if (BreakpointFaultM) CauseM = 3;
else if (EcallFaultM) CauseM = {{(`LOG_XLEN-4){1'b0}}, {2'b10}, PrivilegeModeW}; else if (EcallFaultM) CauseM = {2'b10, PrivilegeModeW};
else if (LoadMisalignedFaultM) CauseM = 4; else if (LoadMisalignedFaultM) CauseM = 4;
else if (StoreAmoMisalignedFaultM) CauseM = 6; else if (StoreAmoMisalignedFaultM) CauseM = 6;
else if (LoadPageFaultM) CauseM = 13; else if (LoadPageFaultM) CauseM = 13;

View File

@ -28,7 +28,7 @@
`include "wally-config.vh" `include "wally-config.vh"
`include "tests.vh" `include "tests.vh"
`define PrintHPMCounters 1 `define PrintHPMCounters 0
`define BPRED_LOGGER 0 `define BPRED_LOGGER 0
`define I_CACHE_ADDR_LOGGER 0 `define I_CACHE_ADDR_LOGGER 0
`define D_CACHE_ADDR_LOGGER 0 `define D_CACHE_ADDR_LOGGER 0

View File

@ -47,6 +47,7 @@ string tvpaths[] = '{
"ieu", "ieu",
"ebu", "ebu",
"csrwrites", "csrwrites",
"fpu",
"priv" "priv"
}; };

View File

@ -17,7 +17,7 @@ all: $(OBJECTS)
# Change many things if bit width isn't 64 # Change many things if bit width isn't 64
%.elf: $(SRCDIR)/%.$(SEXT) WALLY-init-lib.h Makefile %.elf: $(SRCDIR)/%.$(SEXT) WALLY-init-lib.h Makefile
riscv64-unknown-elf-gcc -g -o $@ -march=rv64gc_zba_zbb_zbc_zbs -mabi=lp64 -mcmodel=medany \ riscv64-unknown-elf-gcc -g -o $@ -march=rv64gqc_zba_zbb_zbc_zbs_zfh -mabi=lp64 -mcmodel=medany \
-nostartfiles -T../../examples/link/link.ld $< -nostartfiles -T../../examples/link/link.ld $<
riscv64-unknown-elf-objdump -S $@ > $@.objdump riscv64-unknown-elf-objdump -S $@ > $@.objdump
riscv64-unknown-elf-elf2hex --bit-width 64 --input $@ --output $@.memfile riscv64-unknown-elf-elf2hex --bit-width 64 --input $@ --output $@.memfile

72
tests/coverage/fpu.S Normal file
View File

@ -0,0 +1,72 @@
///////////////////////////////////////////
// fpu.S
//
// Written: David_Harris@hmc.edu 28 March 2023
//
// Purpose: Test coverage for FPU
//
// A component of the CORE-V-WALLY configurable RISC-V project.
//
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
//
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
//
// Licensed under the Solderpad Hardware License v 2.1 (the License); you may not use this file
// except in compliance with the License, or, at your option, the Apache License version 2.0. You
// may obtain a copy of the License at
//
// https://solderpad.org/licenses/SHL-2.1/
//
// Unless required by applicable law or agreed to in writing, any work distributed under the
// License is distributed on an AS IS BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
// either express or implied. See the License for the specific language governing permissions
// and limitations under the License.
////////////////////////////////////////////////////////////////////////////////////////////////
// load code to initalize stack, handle interrupts, terminate
#include "WALLY-init-lib.h"
main:
bseti t0, zero, 14 # turn on FPU
csrs mstatus, t0
# Test legal instructions not covered elsewhere
flq ft0, 0(a0)
flh ft0, 8(a0)
fsq ft0, 0(a0)
fsh ft0, 8(a0)
fcvt.h.s ft1, ft0
fcvt.q.s ft2, ft0
fcvt.h.w ft3, a0
fcvt.h.wu ft3, a0
fcvt.h.l ft3, a0
fcvt.h.lu ft3, a0
fcvt.w.h a0, ft3
fcvt.wu.h a0, ft3
fcvt.l.h a0, ft3
fcvt.lu.h a0, ft3
fcvt.q.w ft3, a0
fcvt.q.wu ft3, a0
fcvt.q.l ft3, a0
fcvt.q.lu ft3, a0
fcvt.w.q a0, ft3
fcvt.wu.q a0, ft3
fcvt.l.q a0, ft3
fcvt.lu.q a0, ft3
# Test illegal instructions are detected
.word 0x00000007 // illegal floating-point load (bad Funct3)
.word 0x00000027 // illegal floating-point store (bad Funct3)
.word 0x58F00053 // illegal fsqrt (bad Rs2D)
.word 0x20007053 // illegal fsgnj (bad Funct3)
.word 0x28007053 // illegal fmin/max (bad Funct3)
.word 0xA0007053 // illegal fcmp (bad Funct3)
.word 0xE0007053 // illegal fclass/fmv (bad Funct3)
.word 0xF0007053 // illegal fmv (bad Funct3)
.word 0x43007053 // illegal fcvt.d.* (bad Rs2D)
.word 0x42207053 // illegal fcvt.d.* (bad Rs2D[1])
j done