forked from Github_Repos/cvw
Merge branch 'openhwgroup:main' into cachesim
This commit is contained in:
commit
37f4443012
38
src/cache/cache.sv
vendored
38
src/cache/cache.sv
vendored
@ -96,8 +96,7 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE
|
|||||||
logic [LINELEN-1:0] ReadDataLine, ReadDataLineCache;
|
logic [LINELEN-1:0] ReadDataLine, ReadDataLineCache;
|
||||||
logic SelFetchBuffer;
|
logic SelFetchBuffer;
|
||||||
logic CacheEn;
|
logic CacheEn;
|
||||||
logic [CACHEWORDSPERLINE-1:0] MemPAdrDecoded;
|
logic [LINELEN/8-1:0] LineByteMask;
|
||||||
logic [LINELEN/8-1:0] LineByteMask, DemuxedByteMask, FetchBufferByteSel;
|
|
||||||
logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1:0] WordOffsetAddr;
|
logic [$clog2(LINELEN/8) - $clog2(MUXINTERVAL/8) - 1:0] WordOffsetAddr;
|
||||||
|
|
||||||
genvar index;
|
genvar index;
|
||||||
@ -161,21 +160,30 @@ module cache #(parameter LINELEN, NUMLINES, NUMWAYS, LOGBWPL, WORDLEN, MUXINTE
|
|||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Write Path
|
// Write Path
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
if(!READ_ONLY_CACHE) begin:WriteSelLogic
|
||||||
|
logic [CACHEWORDSPERLINE-1:0] MemPAdrDecoded;
|
||||||
|
logic [LINELEN/8-1:0] DemuxedByteMask, FetchBufferByteSel;
|
||||||
|
|
||||||
// Adjust byte mask from word to cache line
|
// Adjust byte mask from word to cache line
|
||||||
onehotdecoder #(LOGCWPL) adrdec(.bin(PAdr[LOGCWPL+LOGLLENBYTES-1:LOGLLENBYTES]), .decoded(MemPAdrDecoded));
|
onehotdecoder #(LOGCWPL) adrdec(.bin(PAdr[LOGCWPL+LOGLLENBYTES-1:LOGLLENBYTES]), .decoded(MemPAdrDecoded));
|
||||||
for(index = 0; index < 2**LOGCWPL; index++) begin
|
for(index = 0; index < 2**LOGCWPL; index++) begin
|
||||||
assign DemuxedByteMask[(index+1)*(WORDLEN/8)-1:index*(WORDLEN/8)] = MemPAdrDecoded[index] ? ByteMask : '0;
|
assign DemuxedByteMask[(index+1)*(WORDLEN/8)-1:index*(WORDLEN/8)] = MemPAdrDecoded[index] ? ByteMask : '0;
|
||||||
|
end
|
||||||
|
assign FetchBufferByteSel = SetValid & ~SetDirty ? '1 : ~DemuxedByteMask; // If load miss set all muxes to 1.
|
||||||
|
|
||||||
|
// Merge write data into fetched cache line for store miss
|
||||||
|
for(index = 0; index < LINELEN/8; index++) begin
|
||||||
|
mux2 #(8) WriteDataMux(.d0(CacheWriteData[(8*index)%WORDLEN+7:(8*index)%WORDLEN]),
|
||||||
|
.d1(FetchBuffer[8*index+7:8*index]), .s(FetchBufferByteSel[index]), .y(LineWriteData[8*index+7:8*index]));
|
||||||
|
end
|
||||||
|
assign LineByteMask = SetValid ? '1 : SetDirty ? DemuxedByteMask : '0;
|
||||||
end
|
end
|
||||||
assign FetchBufferByteSel = SetValid & ~SetDirty ? '1 : ~DemuxedByteMask; // If load miss set all muxes to 1.
|
else
|
||||||
assign LineByteMask = SetValid ? '1 : SetDirty ? DemuxedByteMask : '0;
|
begin:WriteSelLogic
|
||||||
|
// No need for this mux if the cache does not handle writes.
|
||||||
// Merge write data into fetched cache line for store miss
|
assign LineWriteData = FetchBuffer;
|
||||||
for(index = 0; index < LINELEN/8; index++) begin
|
assign LineByteMask = '1;
|
||||||
mux2 #(8) WriteDataMux(.d0(CacheWriteData[(8*index)%WORDLEN+7:(8*index)%WORDLEN]),
|
end
|
||||||
.d1(FetchBuffer[8*index+7:8*index]), .s(FetchBufferByteSel[index]), .y(LineWriteData[8*index+7:8*index]));
|
|
||||||
end
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
// Flush logic
|
// Flush logic
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
8
src/cache/cacheLRU.sv
vendored
8
src/cache/cacheLRU.sv
vendored
@ -98,7 +98,9 @@ module cacheLRU
|
|||||||
assign LRUUpdate[t1] = LRUUpdate[s] & WayEncoded[r];
|
assign LRUUpdate[t1] = LRUUpdate[s] & WayEncoded[r];
|
||||||
end
|
end
|
||||||
|
|
||||||
mux2 #(1) LRUMuxes[NUMWAYS-2:0](CurrLRU, ~WayExpanded, LRUUpdate, NextLRU);
|
// The root node of the LRU tree will always be selected in LRUUpdate. No mux needed.
|
||||||
|
assign NextLRU[NUMWAYS-2] = ~WayExpanded[NUMWAYS-2];
|
||||||
|
mux2 #(1) LRUMuxes[NUMWAYS-3:0](CurrLRU[NUMWAYS-3:0], ~WayExpanded[NUMWAYS-3:0], LRUUpdate[NUMWAYS-3:0], NextLRU[NUMWAYS-3:0]);
|
||||||
|
|
||||||
// Compute next victim way.
|
// Compute next victim way.
|
||||||
for(s = NUMWAYS-2; s >= NUMWAYS/2; s--) begin
|
for(s = NUMWAYS-2; s >= NUMWAYS/2; s--) begin
|
||||||
@ -128,8 +130,8 @@ module cacheLRU
|
|||||||
always_ff @(posedge clk) begin
|
always_ff @(posedge clk) begin
|
||||||
if (reset) for (int set = 0; set < NUMLINES; set++) LRUMemory[set] <= '0;
|
if (reset) for (int set = 0; set < NUMLINES; set++) LRUMemory[set] <= '0;
|
||||||
if(CacheEn) begin
|
if(CacheEn) begin
|
||||||
if((InvalidateCache | FlushCache) & ~FlushStage) for (int set = 0; set < NUMLINES; set++) LRUMemory[set] <= '0;
|
// if((InvalidateCache | FlushCache) & ~FlushStage) for (int set = 0; set < NUMLINES; set++) LRUMemory[set] <= '0;
|
||||||
else if (LRUWriteEn & ~FlushStage) begin
|
if (LRUWriteEn & ~FlushStage) begin
|
||||||
LRUMemory[PAdr] <= NextLRU;
|
LRUMemory[PAdr] <= NextLRU;
|
||||||
end
|
end
|
||||||
if(LRUWriteEn & ~FlushStage & (PAdr == CacheSet))
|
if(LRUWriteEn & ~FlushStage & (PAdr == CacheSet))
|
||||||
|
208
src/fpu/fctrl.sv
208
src/fpu/fctrl.sv
@ -75,109 +75,139 @@ 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
|
||||||
|
// FRegWrite_FWriteInt_FResSel_PostProcSel_FOpCtrl_FDivStart_IllegalFPUInstr_FCvtInt
|
||||||
always_comb
|
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_000_0_1_0; // default: non-implemented instruction
|
||||||
7'b0000111: case(Funct3D)
|
/* verilator lint_off CASEINCOMPLETE */ // default value above has priority so no other default needed
|
||||||
3'b010: ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flw
|
case(OpD)
|
||||||
3'b011: if (`D_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // fld
|
7'b0000111: case(Funct3D)
|
||||||
else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // fld not supported
|
3'b010: ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flw
|
||||||
3'b100: if (`Q_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flq
|
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; // flq not supported
|
3'b100: if (`Q_SUPPORTED) ControlsD = `FCTRLW'b1_0_10_xx_0xx_0_0_0; // flq
|
||||||
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
|
endcase
|
||||||
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction
|
7'b0100111: case(Funct3D)
|
||||||
endcase
|
3'b010: ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsw
|
||||||
7'b0100111: case(Funct3D)
|
3'b011: if (`D_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsd
|
||||||
3'b010: ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsw
|
3'b100: if (`Q_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsq
|
||||||
3'b011: if (`D_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsd
|
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; // fsd not supported
|
endcase
|
||||||
3'b100: if (`Q_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsq
|
7'b1000011: ControlsD = `FCTRLW'b1_0_01_10_000_0_0_0; // fmadd
|
||||||
else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // fsq not supported
|
7'b1000111: ControlsD = `FCTRLW'b1_0_01_10_001_0_0_0; // fmsub
|
||||||
3'b001: if (`ZFH_SUPPORTED) ControlsD = `FCTRLW'b0_0_10_xx_0xx_0_0_0; // fsh
|
7'b1001011: ControlsD = `FCTRLW'b1_0_01_10_010_0_0_0; // fnmsub
|
||||||
else ControlsD = `FCTRLW'b0_0_00_xx_0xx_0_1_0; // fsh not supported
|
7'b1001111: ControlsD = `FCTRLW'b1_0_01_10_011_0_0_0; // fnmadd
|
||||||
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction
|
7'b1010011: casez(Funct7D)
|
||||||
endcase
|
7'b00000??: ControlsD = `FCTRLW'b1_0_01_10_110_0_0_0; // fadd
|
||||||
7'b1000011: ControlsD = `FCTRLW'b1_0_01_10_000_0_0_0; // fmadd
|
7'b00001??: ControlsD = `FCTRLW'b1_0_01_10_111_0_0_0; // fsub
|
||||||
7'b1000111: ControlsD = `FCTRLW'b1_0_01_10_001_0_0_0; // fmsub
|
7'b00010??: ControlsD = `FCTRLW'b1_0_01_10_100_0_0_0; // fmul
|
||||||
7'b1001011: ControlsD = `FCTRLW'b1_0_01_10_010_0_0_0; // fnmsub
|
7'b00011??: ControlsD = `FCTRLW'b1_0_01_01_xx0_1_0_0; // fdiv
|
||||||
7'b1001111: ControlsD = `FCTRLW'b1_0_01_10_011_0_0_0; // fnmadd
|
7'b01011??: if (Rs2D == 5'b0000) ControlsD = `FCTRLW'b1_0_01_01_xx1_1_0_0; // fsqrt
|
||||||
7'b1010011: casez(Funct7D)
|
7'b00100??: case(Funct3D)
|
||||||
7'b00000??: ControlsD = `FCTRLW'b1_0_01_10_110_0_0_0; // fadd
|
3'b000: ControlsD = `FCTRLW'b1_0_00_xx_000_0_0_0; // fsgnj
|
||||||
7'b00001??: ControlsD = `FCTRLW'b1_0_01_10_111_0_0_0; // fsub
|
3'b001: ControlsD = `FCTRLW'b1_0_00_xx_001_0_0_0; // fsgnjn
|
||||||
7'b00010??: ControlsD = `FCTRLW'b1_0_01_10_100_0_0_0; // fmul
|
3'b010: ControlsD = `FCTRLW'b1_0_00_xx_010_0_0_0; // fsgnjx
|
||||||
7'b00011??: ControlsD = `FCTRLW'b1_0_01_01_xx0_1_0_0; // fdiv
|
endcase
|
||||||
7'b01011??: if (Rs2D == 5'b0000) ControlsD = `FCTRLW'b1_0_01_01_xx1_1_0_0; // fsqrt
|
7'b00101??: case(Funct3D)
|
||||||
7'b00100??: case(Funct3D)
|
3'b000: ControlsD = `FCTRLW'b1_0_00_xx_110_0_0_0; // fmin
|
||||||
3'b000: ControlsD = `FCTRLW'b1_0_00_xx_000_0_0_0; // fsgnj
|
3'b001: ControlsD = `FCTRLW'b1_0_00_xx_101_0_0_0; // fmax
|
||||||
3'b001: ControlsD = `FCTRLW'b1_0_00_xx_001_0_0_0; // fsgnjn
|
endcase
|
||||||
3'b010: ControlsD = `FCTRLW'b1_0_00_xx_010_0_0_0; // fsgnjx
|
7'b10100??: case(Funct3D)
|
||||||
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction
|
3'b010: ControlsD = `FCTRLW'b0_1_00_xx_010_0_0_0; // feq
|
||||||
endcase
|
3'b001: ControlsD = `FCTRLW'b0_1_00_xx_001_0_0_0; // flt
|
||||||
7'b00101??: case(Funct3D)
|
3'b000: ControlsD = `FCTRLW'b0_1_00_xx_011_0_0_0; // fle
|
||||||
3'b000: ControlsD = `FCTRLW'b1_0_00_xx_110_0_0_0; // fmin
|
endcase
|
||||||
3'b001: ControlsD = `FCTRLW'b1_0_00_xx_101_0_0_0; // fmax
|
7'b11100??: if (Funct3D == 3'b001 & Rs2D == 5'b00000)
|
||||||
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction
|
ControlsD = `FCTRLW'b0_1_10_xx_000_0_0_0; // fclass
|
||||||
endcase
|
else if (Funct3D == 3'b000 & Rs2D == 5'b00000)
|
||||||
7'b10100??: case(Funct3D)
|
ControlsD = `FCTRLW'b0_1_11_xx_000_0_0_0; // fmv.x.w / fmv.x.d to int register
|
||||||
3'b010: ControlsD = `FCTRLW'b0_1_00_xx_010_0_0_0; // feq
|
7'b111100?: if (Funct3D == 3'b000 & Rs2D == 5'b00000)
|
||||||
3'b001: ControlsD = `FCTRLW'b0_1_00_xx_001_0_0_0; // flt
|
ControlsD = `FCTRLW'b1_0_00_xx_011_0_0_0; // fmv.w.x / fmv.d.x to fp reg
|
||||||
3'b000: ControlsD = `FCTRLW'b0_1_00_xx_011_0_0_0; // fle
|
7'b0100000: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b00)
|
||||||
default: ControlsD = `FCTRLW'b0_0_00_xx_000__0_1_0; // non-implemented instruction
|
ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0; // fcvt.s.(d/q/h)
|
||||||
endcase
|
7'b0100001: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b01)
|
||||||
7'b11100??: if (Funct3D == 3'b001 & Rs2D == 5'b00000)
|
ControlsD = `FCTRLW'b1_0_01_00_001_0_0_0; // fcvt.d.(s/h/q)
|
||||||
ControlsD = `FCTRLW'b0_1_10_xx_000_0_0_0; // fclass
|
// coverage off
|
||||||
else if (Funct3D[1:0] == 2'b00) ControlsD = `FCTRLW'b0_1_11_xx_000_0_0_0; // fmv.x.w to int reg
|
// Not covered in testing because rv64gc does not support half or quad precision
|
||||||
else if (Funct3D[1:0] == 2'b01) ControlsD = `FCTRLW'b0_1_11_xx_000_0_0_0; // fmv.x.d to int reg
|
7'b0100010: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b10)
|
||||||
else ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction
|
ControlsD = `FCTRLW'b1_0_01_00_010_0_0_0; // fcvt.h.(s/d/q)
|
||||||
7'b1101000: case(Rs2D[1:0])
|
7'b0100011: if (Rs2D[4:2] == 3'b000 & SupportedFmt2 & Rs2D[1:0] != 2'b11)
|
||||||
2'b00: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.s.w w->s
|
ControlsD = `FCTRLW'b1_0_01_00_011_0_0_0; // fcvt.q.(s/h/d)
|
||||||
2'b01: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.s.wu wu->s
|
// coverage on
|
||||||
2'b10: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.s.l l->s
|
7'b1101000: case(Rs2D)
|
||||||
2'b11: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.s.lu lu->s
|
5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.s.w w->s
|
||||||
endcase
|
5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.s.wu wu->s
|
||||||
7'b1100000: case(Rs2D[1:0])
|
5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.s.l l->s
|
||||||
2'b00: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.s s->w
|
5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.s.lu lu->s
|
||||||
2'b01: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.s s->wu
|
endcase
|
||||||
2'b10: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.s s->l
|
7'b1100000: case(Rs2D)
|
||||||
2'b11: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.s s->lu
|
5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.s s->w
|
||||||
endcase
|
5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.s s->wu
|
||||||
7'b1111000: ControlsD = `FCTRLW'b1_0_00_xx_011_0_0_0; // fmv.w.x to fp reg
|
5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.s s->l
|
||||||
7'b0100000: ControlsD = `FCTRLW'b1_0_01_00_000_0_0_0; // fcvt.s.d
|
5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.s s->lu
|
||||||
7'b1101001: case(Rs2D[1:0])
|
endcase
|
||||||
2'b00: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.d.w w->d
|
7'b1101001: case(Rs2D)
|
||||||
2'b01: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.d.wu wu->d
|
5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.d.w w->d
|
||||||
2'b10: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.d.l l->d
|
5'b00001: ControlsD = `FCTRLW'b1_0_01_00_100_0_0_0; // fcvt.d.wu wu->d
|
||||||
2'b11: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.d.lu lu->d
|
5'b00010: ControlsD = `FCTRLW'b1_0_01_00_111_0_0_0; // fcvt.d.l l->d
|
||||||
endcase
|
5'b00011: ControlsD = `FCTRLW'b1_0_01_00_110_0_0_0; // fcvt.d.lu lu->d
|
||||||
7'b1100001: case(Rs2D[1:0])
|
endcase
|
||||||
2'b00: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.d d->w
|
7'b1100001: case(Rs2D)
|
||||||
2'b01: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.d d->wu
|
5'b00000: ControlsD = `FCTRLW'b0_1_01_00_001_0_0_1; // fcvt.w.d d->w
|
||||||
2'b10: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.d d->l
|
5'b00001: ControlsD = `FCTRLW'b0_1_01_00_000_0_0_1; // fcvt.wu.d d->wu
|
||||||
2'b11: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.d d->lu
|
5'b00010: ControlsD = `FCTRLW'b0_1_01_00_011_0_0_1; // fcvt.l.d d->l
|
||||||
endcase
|
5'b00011: ControlsD = `FCTRLW'b0_1_01_00_010_0_0_1; // fcvt.lu.d d->lu
|
||||||
7'b1111001: ControlsD = `FCTRLW'b1_0_00_xx_011_0_0_0; // fmv.d.x to fp reg
|
endcase
|
||||||
7'b0100001: ControlsD = `FCTRLW'b1_0_01_00_001_0_0_0; // fcvt.d.s
|
// coverage off
|
||||||
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction
|
// Not covered in testing because rv64gc does not support half or quad precision
|
||||||
endcase
|
7'b1101010: case(Rs2D)
|
||||||
default: ControlsD = `FCTRLW'b0_0_00_xx_000_0_1_0; // non-implemented instruction
|
5'b00000: ControlsD = `FCTRLW'b1_0_01_00_101_0_0_0; // fcvt.h.w w->h
|
||||||
endcase
|
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
|
||||||
|
// coverage on
|
||||||
|
endcase
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
/* verilator lint_on CASEINCOMPLETE */
|
||||||
|
|
||||||
// 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;
|
||||||
@ -304,6 +334,4 @@ module fctrl (
|
|||||||
{FRegWriteM, FResSelM, FCvtIntM},
|
{FRegWriteM, FResSelM, FCvtIntM},
|
||||||
{FRegWriteW, FResSelW, FCvtIntW});
|
{FRegWriteW, FResSelW, FCvtIntW});
|
||||||
|
|
||||||
//assign FCvtIntW = (FResSelW == 2'b01);
|
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -37,14 +37,13 @@ module alu #(parameter WIDTH=32) (
|
|||||||
input logic [1:0] BSelect, // Binary encoding of if it's a ZBA_ZBB_ZBC_ZBS instruction
|
input logic [1:0] BSelect, // Binary encoding of if it's a ZBA_ZBB_ZBC_ZBS instruction
|
||||||
input logic [2:0] ZBBSelect, // ZBB mux select signal
|
input logic [2:0] ZBBSelect, // ZBB mux select signal
|
||||||
input logic [2:0] Funct3, // For BMU decoding
|
input logic [2:0] Funct3, // For BMU decoding
|
||||||
input logic [1:0] CompFlags, // Comparator flags
|
|
||||||
input logic [2:0] BALUControl, // ALU Control signals for B instructions in Execute Stage
|
input logic [2:0] BALUControl, // ALU Control signals for B instructions in Execute Stage
|
||||||
output logic [WIDTH-1:0] Result, // ALU result
|
output logic [WIDTH-1:0] ALUResult, // ALU result
|
||||||
output logic [WIDTH-1:0] Sum); // Sum of operands
|
output logic [WIDTH-1:0] Sum); // Sum of operands
|
||||||
|
|
||||||
// CondInvB = ~B when subtracting, B otherwise. Shift = shift result. SLT/U = result of a slt/u instruction.
|
// CondInvB = ~B when subtracting, B otherwise. Shift = shift result. SLT/U = result of a slt/u instruction.
|
||||||
// FullResult = ALU result before adjusting for a RV64 w-suffix instruction.
|
// FullResult = ALU result before adjusting for a RV64 w-suffix instruction.
|
||||||
logic [WIDTH-1:0] CondMaskInvB, Shift, FullResult, ALUResult; // Intermediate Signals
|
logic [WIDTH-1:0] CondMaskInvB, Shift, FullResult, PreALUResult; // Intermediate Signals
|
||||||
logic [WIDTH-1:0] CondMaskB; // Result of B mask select mux
|
logic [WIDTH-1:0] CondMaskB; // Result of B mask select mux
|
||||||
logic [WIDTH-1:0] CondShiftA; // Result of A shifted select mux
|
logic [WIDTH-1:0] CondShiftA; // Result of A shifted select mux
|
||||||
logic [WIDTH-1:0] CondExtA; // Result of Zero Extend A select mux
|
logic [WIDTH-1:0] CondExtA; // Result of Zero Extend A select mux
|
||||||
@ -84,16 +83,16 @@ module alu #(parameter WIDTH=32) (
|
|||||||
end
|
end
|
||||||
|
|
||||||
// Support RV64I W-type addw/subw/addiw/shifts that discard upper 32 bits and sign-extend 32-bit result to 64 bits
|
// Support RV64I W-type addw/subw/addiw/shifts that discard upper 32 bits and sign-extend 32-bit result to 64 bits
|
||||||
if (WIDTH == 64) assign ALUResult = W64 ? {{32{FullResult[31]}}, FullResult[31:0]} : FullResult;
|
if (WIDTH == 64) assign PreALUResult = W64 ? {{32{FullResult[31]}}, FullResult[31:0]} : FullResult;
|
||||||
else assign ALUResult = FullResult;
|
else assign PreALUResult = FullResult;
|
||||||
|
|
||||||
// Final Result B instruction select mux
|
// Final Result B instruction select mux
|
||||||
if (`ZBC_SUPPORTED | `ZBS_SUPPORTED | `ZBA_SUPPORTED | `ZBB_SUPPORTED) begin : bitmanipalu
|
if (`ZBC_SUPPORTED | `ZBS_SUPPORTED | `ZBA_SUPPORTED | `ZBB_SUPPORTED) begin : bitmanipalu
|
||||||
bitmanipalu #(WIDTH) balu(.A, .B, .W64, .BSelect, .ZBBSelect,
|
bitmanipalu #(WIDTH) balu(.A, .B, .W64, .BSelect, .ZBBSelect,
|
||||||
.Funct3, .CompFlags, .BALUControl, .ALUResult, .FullResult,
|
.Funct3, .LT,.LTU, .BALUControl, .PreALUResult, .FullResult,
|
||||||
.CondMaskB, .CondShiftA, .Result);
|
.CondMaskB, .CondShiftA, .ALUResult);
|
||||||
end else begin
|
end else begin
|
||||||
assign Result = ALUResult;
|
assign ALUResult = PreALUResult;
|
||||||
assign CondMaskB = B;
|
assign CondMaskB = B;
|
||||||
assign CondShiftA = A;
|
assign CondShiftA = A;
|
||||||
end
|
end
|
||||||
|
@ -35,12 +35,13 @@ module bitmanipalu #(parameter WIDTH=32) (
|
|||||||
input logic [1:0] BSelect, // Binary encoding of if it's a ZBA_ZBB_ZBC_ZBS instruction
|
input logic [1:0] BSelect, // Binary encoding of if it's a ZBA_ZBB_ZBC_ZBS instruction
|
||||||
input logic [2:0] ZBBSelect, // ZBB mux select signal
|
input logic [2:0] ZBBSelect, // ZBB mux select signal
|
||||||
input logic [2:0] Funct3, // Funct3 field of opcode indicates operation to perform
|
input logic [2:0] Funct3, // Funct3 field of opcode indicates operation to perform
|
||||||
input logic [1:0] CompFlags, // Comparator flags
|
input logic LT, // less than flag
|
||||||
|
input logic LTU, // less than unsigned flag
|
||||||
input logic [2:0] BALUControl, // ALU Control signals for B instructions in Execute Stage
|
input logic [2:0] BALUControl, // ALU Control signals for B instructions in Execute Stage
|
||||||
input logic [WIDTH-1:0] ALUResult, FullResult, // ALUResult, FullResult signals
|
input logic [WIDTH-1:0] PreALUResult, FullResult,// PreALUResult, FullResult signals
|
||||||
output logic [WIDTH-1:0] CondMaskB, // B is conditionally masked for ZBS instructions
|
output logic [WIDTH-1:0] CondMaskB, // B is conditionally masked for ZBS instructions
|
||||||
output logic [WIDTH-1:0] CondShiftA, // A is conditionally shifted for ShAdd instructions
|
output logic [WIDTH-1:0] CondShiftA, // A is conditionally shifted for ShAdd instructions
|
||||||
output logic [WIDTH-1:0] Result); // Result
|
output logic [WIDTH-1:0] ALUResult); // Result
|
||||||
|
|
||||||
logic [WIDTH-1:0] ZBBResult, ZBCResult; // ZBB, ZBC Result
|
logic [WIDTH-1:0] ZBBResult, ZBCResult; // ZBB, ZBC Result
|
||||||
logic [WIDTH-1:0] MaskB; // BitMask of B
|
logic [WIDTH-1:0] MaskB; // BitMask of B
|
||||||
@ -84,16 +85,16 @@ module bitmanipalu #(parameter WIDTH=32) (
|
|||||||
|
|
||||||
// ZBB Unit
|
// ZBB Unit
|
||||||
if (`ZBB_SUPPORTED) begin: zbb
|
if (`ZBB_SUPPORTED) begin: zbb
|
||||||
zbb #(WIDTH) ZBB(.A, .RevA, .B, .ALUResult, .W64, .lt(CompFlags[0]), .ZBBSelect, .ZBBResult);
|
zbb #(WIDTH) ZBB(.A, .RevA, .B, .W64, .LT, .LTU, .BUnsigned(Funct3[0]), .ZBBSelect, .ZBBResult);
|
||||||
end else assign ZBBResult = 0;
|
end else assign ZBBResult = 0;
|
||||||
|
|
||||||
// Result Select Mux
|
// Result Select Mux
|
||||||
always_comb
|
always_comb
|
||||||
case (BSelect)
|
case (BSelect)
|
||||||
// 00: ALU, 01: ZBA/ZBS, 10: ZBB, 11: ZBC
|
// 00: ALU, 01: ZBA/ZBS, 10: ZBB, 11: ZBC
|
||||||
2'b00: Result = ALUResult;
|
2'b00: ALUResult = PreALUResult;
|
||||||
2'b01: Result = FullResult; // NOTE: We don't use ALUResult because ZBA/ZBS instructions don't sign extend the MSB of the right-hand word.
|
2'b01: ALUResult = FullResult; // NOTE: We don't use ALUResult because ZBA/ZBS instructions don't sign extend the MSB of the right-hand word.
|
||||||
2'b10: Result = ZBBResult;
|
2'b10: ALUResult = ZBBResult;
|
||||||
2'b11: Result = ZBCResult;
|
2'b11: ALUResult = ZBCResult;
|
||||||
endcase
|
endcase
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -48,7 +48,6 @@ module bmuctrl(
|
|||||||
output logic [1:0] BSelectE, // Indicates if ZBA_ZBB_ZBC_ZBS instruction in one-hot encoding
|
output logic [1:0] BSelectE, // Indicates if ZBA_ZBB_ZBC_ZBS instruction in one-hot encoding
|
||||||
output logic [2:0] ZBBSelectE, // ZBB mux select signal
|
output logic [2:0] ZBBSelectE, // ZBB mux select signal
|
||||||
output logic BRegWriteE, // Indicates if it is a R type B instruction in Execute
|
output logic BRegWriteE, // Indicates if it is a R type B instruction in Execute
|
||||||
output logic BComparatorSignedE, // Indicates if comparator signed in Execute Stage
|
|
||||||
output logic [2:0] BALUControlE // ALU Control signals for B instructions in Execute Stage
|
output logic [2:0] BALUControlE // ALU Control signals for B instructions in Execute Stage
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -56,7 +55,6 @@ module bmuctrl(
|
|||||||
logic [2:0] Funct3D; // Funct3 field in Decode stage
|
logic [2:0] Funct3D; // Funct3 field in Decode stage
|
||||||
logic [6:0] Funct7D; // Funct7 field in Decode stage
|
logic [6:0] Funct7D; // Funct7 field in Decode stage
|
||||||
logic [4:0] Rs2D; // Rs2 source register in Decode stage
|
logic [4:0] Rs2D; // Rs2 source register in Decode stage
|
||||||
logic BComparatorSignedD; // Indicates if comparator signed (max, min instruction) in Decode Stage
|
|
||||||
logic RotateD; // Indicates if rotate instruction in Decode Stage
|
logic RotateD; // Indicates if rotate instruction in Decode Stage
|
||||||
logic MaskD; // Indicates if zbs instruction in Decode Stage
|
logic MaskD; // Indicates if zbs instruction in Decode Stage
|
||||||
logic PreShiftD; // Indicates if sh1add, sh2add, sh3add instruction in Decode Stage
|
logic PreShiftD; // Indicates if sh1add, sh2add, sh3add instruction in Decode Stage
|
||||||
@ -110,10 +108,10 @@ module bmuctrl(
|
|||||||
BMUControlsD = `BMUCTRLW'b000_10_010_1_1_0_1_0_0_0_0_0; // rev8
|
BMUControlsD = `BMUCTRLW'b000_10_010_1_1_0_1_0_0_0_0_0; // rev8
|
||||||
17'b0010011_0010100_101: if (Rs2D[4:0] == 5'b00111)
|
17'b0010011_0010100_101: if (Rs2D[4:0] == 5'b00111)
|
||||||
BMUControlsD = `BMUCTRLW'b000_10_010_1_1_0_1_0_0_0_0_0; // orc.b
|
BMUControlsD = `BMUCTRLW'b000_10_010_1_1_0_1_0_0_0_0_0; // orc.b
|
||||||
17'b0110011_0000101_110: BMUControlsD = `BMUCTRLW'b000_10_111_1_0_0_1_0_0_0_0_0; // max
|
17'b0110011_0000101_110: BMUControlsD = `BMUCTRLW'b000_10_111_1_0_0_1_1_0_0_0_0; // max
|
||||||
17'b0110011_0000101_111: BMUControlsD = `BMUCTRLW'b000_10_111_1_0_0_1_0_0_0_0_0; // maxu
|
17'b0110011_0000101_111: BMUControlsD = `BMUCTRLW'b000_10_111_1_0_0_1_1_0_0_0_0; // maxu
|
||||||
17'b0110011_0000101_100: BMUControlsD = `BMUCTRLW'b000_10_011_1_0_0_1_0_0_0_0_0; // min
|
17'b0110011_0000101_100: BMUControlsD = `BMUCTRLW'b000_10_011_1_0_0_1_1_0_0_0_0; // min
|
||||||
17'b0110011_0000101_101: BMUControlsD = `BMUCTRLW'b000_10_011_1_0_0_1_0_0_0_0_0; // minu
|
17'b0110011_0000101_101: BMUControlsD = `BMUCTRLW'b000_10_011_1_0_0_1_1_0_0_0_0; // minu
|
||||||
endcase
|
endcase
|
||||||
if (`XLEN==32)
|
if (`XLEN==32)
|
||||||
casez({OpD, Funct7D, Funct3D})
|
casez({OpD, Funct7D, Funct3D})
|
||||||
@ -172,12 +170,9 @@ module bmuctrl(
|
|||||||
// Pack BALUControl Signals
|
// Pack BALUControl Signals
|
||||||
assign BALUControlD = {RotateD, MaskD, PreShiftD};
|
assign BALUControlD = {RotateD, MaskD, PreShiftD};
|
||||||
|
|
||||||
// Comparator should perform signed comparison when min/max instruction. We have overlap in funct3 with some branch instructions so we use opcode to differentiate betwen min/max and branches
|
|
||||||
assign BComparatorSignedD = (Funct3D[2]^Funct3D[0]) & ~OpD[6];
|
|
||||||
|
|
||||||
// Choose ALUSelect brom BMU for BMU operations, Funct3 for IEU operations, or 0 for addition
|
// Choose ALUSelect brom BMU for BMU operations, Funct3 for IEU operations, or 0 for addition
|
||||||
assign ALUSelectD = BALUOpD ? BALUSelectD : (ALUOpD ? Funct3D : 3'b000);
|
assign ALUSelectD = BALUOpD ? BALUSelectD : (ALUOpD ? Funct3D : 3'b000);
|
||||||
|
|
||||||
// BMU Execute stage pipieline control register
|
// BMU Execute stage pipieline control register
|
||||||
flopenrc#(10) controlregBMU(clk, reset, FlushE, ~StallE, {BSelectD, ZBBSelectD, BRegWriteD, BComparatorSignedD, BALUControlD}, {BSelectE, ZBBSelectE, BRegWriteE, BComparatorSignedE, BALUControlE});
|
flopenrc#(9) controlregBMU(clk, reset, FlushE, ~StallE, {BSelectD, ZBBSelectD, BRegWriteD, BALUControlD}, {BSelectE, ZBBSelectE, BRegWriteE, BALUControlE});
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -30,20 +30,20 @@
|
|||||||
`include "wally-config.vh"
|
`include "wally-config.vh"
|
||||||
|
|
||||||
module clmul #(parameter WIDTH=32) (
|
module clmul #(parameter WIDTH=32) (
|
||||||
input logic [WIDTH-1:0] A, B, // Operands
|
input logic [WIDTH-1:0] X, Y, // Operands
|
||||||
output logic [WIDTH-1:0] ClmulResult); // ZBS result
|
output logic [WIDTH-1:0] ClmulResult); // ZBS result
|
||||||
|
|
||||||
logic [(WIDTH*WIDTH)-1:0] s; // intermediary signals for carry-less multiply
|
logic [(WIDTH*WIDTH)-1:0] S; // intermediary signals for carry-less multiply
|
||||||
|
|
||||||
integer i,j;
|
integer i,j;
|
||||||
|
|
||||||
always_comb begin
|
always_comb begin
|
||||||
for (i=0;i<WIDTH;i++) begin: outer
|
for (i=0;i<WIDTH;i++) begin: outer
|
||||||
s[WIDTH*i]=A[0]&B[i];
|
S[WIDTH*i] = X[0] & Y[i];
|
||||||
for (j=1;j<=i;j++) begin: inner
|
for (j=1;j<=i;j++) begin: inner
|
||||||
s[WIDTH*i+j] = (A[j]&B[i-j])^s[WIDTH*i+j-1];
|
S[WIDTH*i+j] = (X[j] & Y[i-j]) ^ S[WIDTH*i+j-1];
|
||||||
end
|
end
|
||||||
ClmulResult[i] = s[WIDTH*i+j-1];
|
ClmulResult[i] = S[WIDTH*i+j-1];
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
module cnt #(parameter WIDTH = 32) (
|
module cnt #(parameter WIDTH = 32) (
|
||||||
input logic [WIDTH-1:0] A, RevA, // Operands
|
input logic [WIDTH-1:0] A, RevA, // Operands
|
||||||
input logic [4:0] B, // Last 5 bits of immediate
|
input logic [1:0] B, // Last 2 bits of immediate
|
||||||
input logic W64, // Indicates word operation
|
input logic W64, // Indicates word operation
|
||||||
output logic [WIDTH-1:0] CntResult // count result
|
output logic [WIDTH-1:0] CntResult // count result
|
||||||
);
|
);
|
||||||
|
@ -32,23 +32,26 @@
|
|||||||
|
|
||||||
module zbb #(parameter WIDTH=32) (
|
module zbb #(parameter WIDTH=32) (
|
||||||
input logic [WIDTH-1:0] A, RevA, B, // Operands
|
input logic [WIDTH-1:0] A, RevA, B, // Operands
|
||||||
input logic [WIDTH-1:0] ALUResult, // ALU Result
|
|
||||||
input logic W64, // Indicates word operation
|
input logic W64, // Indicates word operation
|
||||||
input logic lt, // lt flag
|
input logic LT, // lt flag
|
||||||
input logic [2:0] ZBBSelect, // Indicates word operation
|
input logic LTU, // ltu flag
|
||||||
|
input logic BUnsigned, // max/min (signed) flag
|
||||||
|
input logic [2:0] ZBBSelect, // ZBB Result select signal
|
||||||
output logic [WIDTH-1:0] ZBBResult); // ZBB result
|
output logic [WIDTH-1:0] ZBBResult); // ZBB result
|
||||||
|
|
||||||
|
logic lt; // lt given signed/unsigned
|
||||||
logic [WIDTH-1:0] CntResult; // count result
|
logic [WIDTH-1:0] CntResult; // count result
|
||||||
logic [WIDTH-1:0] MinMaxResult; // min,max result
|
logic [WIDTH-1:0] MinMaxResult; // min, max result
|
||||||
logic [WIDTH-1:0] ByteResult; // byte results
|
logic [WIDTH-1:0] ByteResult; // byte results
|
||||||
logic [WIDTH-1:0] ExtResult; // sign/zero extend results
|
logic [WIDTH-1:0] ExtResult; // sign/zero extend results
|
||||||
|
|
||||||
cnt #(WIDTH) cnt(.A, .RevA, .B(B[4:0]), .W64, .CntResult);
|
mux2 #(1) ltmux(LT, LTU, BUnsigned , lt);
|
||||||
|
cnt #(WIDTH) cnt(.A, .RevA, .B(B[1:0]), .W64, .CntResult);
|
||||||
byteUnit #(WIDTH) bu(.A, .ByteSelect(B[0]), .ByteResult);
|
byteUnit #(WIDTH) bu(.A, .ByteSelect(B[0]), .ByteResult);
|
||||||
ext #(WIDTH) ext(.A, .ExtSelect({~B[2], {B[2] & B[0]}}), .ExtResult);
|
ext #(WIDTH) ext(.A, .ExtSelect({~B[2], {B[2] & B[0]}}), .ExtResult);
|
||||||
|
|
||||||
// ZBBSelect[2] differentiates between min(u) vs max(u) instruction
|
// ZBBSelect[2] differentiates between min(u) vs max(u) instruction
|
||||||
mux2 #(WIDTH) minmaxmux(B, A, lt^ZBBSelect[2], MinMaxResult);
|
mux2 #(WIDTH) minmaxmux(B, A, ZBBSelect[2]^lt, MinMaxResult);
|
||||||
|
|
||||||
// ZBB Result select mux
|
// ZBB Result select mux
|
||||||
mux4 #(WIDTH) zbbresultmux(CntResult, ExtResult, ByteResult, MinMaxResult, ZBBSelect[1:0], ZBBResult);
|
mux4 #(WIDTH) zbbresultmux(CntResult, ExtResult, ByteResult, MinMaxResult, ZBBSelect[1:0], ZBBResult);
|
||||||
|
@ -36,19 +36,16 @@ module zbc #(parameter WIDTH=32) (
|
|||||||
|
|
||||||
logic [WIDTH-1:0] ClmulResult, RevClmulResult;
|
logic [WIDTH-1:0] ClmulResult, RevClmulResult;
|
||||||
logic [WIDTH-1:0] RevB;
|
logic [WIDTH-1:0] RevB;
|
||||||
logic [WIDTH-1:0] x,y;
|
logic [WIDTH-1:0] X, Y;
|
||||||
logic [1:0] select;
|
|
||||||
|
|
||||||
assign select = ~Funct3[1:0];
|
bitreverse #(WIDTH) brB(B, RevB);
|
||||||
|
|
||||||
bitreverse #(WIDTH) brB(.A(B), .RevA(RevB));
|
mux3 #(WIDTH) xmux({RevA[WIDTH-2:0], {1'b0}}, RevA, A, ~Funct3[1:0], X);
|
||||||
|
mux3 #(WIDTH) ymux({{1'b0}, RevB[WIDTH-2:0]}, RevB, B, ~Funct3[1:0], Y);
|
||||||
|
|
||||||
mux3 #(WIDTH) xmux({RevA[WIDTH-2:0], {1'b0}}, RevA, A, select, x);
|
clmul #(WIDTH) clm(.X, .Y, .ClmulResult);
|
||||||
mux3 #(WIDTH) ymux({{1'b0},RevB[WIDTH-2:0]}, RevB, B, select, y);
|
|
||||||
|
|
||||||
clmul #(WIDTH) clm(.A(x), .B(y), .ClmulResult(ClmulResult));
|
bitreverse #(WIDTH) brClmulResult(ClmulResult, RevClmulResult);
|
||||||
|
|
||||||
bitreverse #(WIDTH) brClmulResult(.A(ClmulResult), .RevA(RevClmulResult));
|
|
||||||
|
|
||||||
mux2 #(WIDTH) zbcresultmux(ClmulResult, RevClmulResult, Funct3[1], ZBCResult);
|
mux2 #(WIDTH) zbcresultmux(ClmulResult, RevClmulResult, Funct3[1], ZBCResult);
|
||||||
endmodule
|
endmodule
|
@ -125,12 +125,12 @@ module controller(
|
|||||||
logic IntDivM; // Integer divide instruction
|
logic IntDivM; // Integer divide instruction
|
||||||
logic [1:0] BSelectD; // One-Hot encoding if it's ZBA_ZBB_ZBC_ZBS instruction in decode stage
|
logic [1:0] BSelectD; // One-Hot encoding if it's ZBA_ZBB_ZBC_ZBS instruction in decode stage
|
||||||
logic [2:0] ZBBSelectD; // ZBB Mux Select Signal
|
logic [2:0] ZBBSelectD; // ZBB Mux Select Signal
|
||||||
logic BComparatorSignedE; // Indicates if max, min (signed comarison) instruction in Execute Stage
|
|
||||||
logic IFunctD, RFunctD, MFunctD; // Detect I, R, and M-type RV32IM/Rv64IM instructions
|
logic IFunctD, RFunctD, MFunctD; // Detect I, R, and M-type RV32IM/Rv64IM instructions
|
||||||
logic LFunctD, SFunctD, BFunctD; // Detect load, store, branch instructions
|
logic LFunctD, SFunctD, BFunctD; // Detect load, store, branch instructions
|
||||||
logic JFunctD; // detect jalr instruction
|
logic JFunctD; // detect jalr instruction
|
||||||
logic FenceM; // Fence.I or sfence.VMA instruction in memory stage
|
logic FenceM; // Fence.I or sfence.VMA instruction in memory stage
|
||||||
logic [2:0] ALUSelectD; // ALU Output selection mux control
|
logic [2:0] ALUSelectD; // ALU Output selection mux control
|
||||||
|
logic IWValidFunct3D; // Detects if Funct3 is valid for IW instructions
|
||||||
|
|
||||||
// Extract fields
|
// Extract fields
|
||||||
assign OpD = InstrD[6:0];
|
assign OpD = InstrD[6:0];
|
||||||
@ -161,6 +161,7 @@ module controller(
|
|||||||
((`XLEN == 64) & (Funct3D == 3'b011));
|
((`XLEN == 64) & (Funct3D == 3'b011));
|
||||||
assign BFunctD = (Funct3D[2:1] != 2'b01); // legal branches
|
assign BFunctD = (Funct3D[2:1] != 2'b01); // legal branches
|
||||||
assign JFunctD = (Funct3D == 3'b000);
|
assign JFunctD = (Funct3D == 3'b000);
|
||||||
|
assign IWValidFunct3D = Funct3D == 3'b000 | Funct3D == 3'b001 | Funct3D == 3'b101;
|
||||||
end else begin:legalcheck2
|
end else begin:legalcheck2
|
||||||
assign IFunctD = 1; // Don't bother to separate out shift decoding
|
assign IFunctD = 1; // Don't bother to separate out shift decoding
|
||||||
assign RFunctD = ~Funct7D[0]; // Not a multiply
|
assign RFunctD = ~Funct7D[0]; // Not a multiply
|
||||||
@ -169,6 +170,7 @@ module controller(
|
|||||||
assign SFunctD = 1; // don't bother to check Funct3 for stores
|
assign SFunctD = 1; // don't bother to check Funct3 for stores
|
||||||
assign BFunctD = 1; // don't bother to check Funct3 for branches
|
assign BFunctD = 1; // don't bother to check Funct3 for branches
|
||||||
assign JFunctD = 1; // don't bother to check Funct3 for jumps
|
assign JFunctD = 1; // don't bother to check Funct3 for jumps
|
||||||
|
assign IWValidFunct3D = 1;
|
||||||
end
|
end
|
||||||
|
|
||||||
// Main Instruction Decoder
|
// Main Instruction Decoder
|
||||||
@ -187,7 +189,7 @@ module controller(
|
|||||||
7'b0010011: if (IFunctD)
|
7'b0010011: if (IFunctD)
|
||||||
ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_0_0_0_0_0_00_0; // I-type ALU
|
ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_0_0_0_0_0_00_0; // I-type ALU
|
||||||
7'b0010111: ControlsD = `CTRLW'b1_100_11_00_000_0_0_0_0_0_0_0_0_0_00_0; // auipc
|
7'b0010111: ControlsD = `CTRLW'b1_100_11_00_000_0_0_0_0_0_0_0_0_0_00_0; // auipc
|
||||||
7'b0011011: if (IFunctD & `XLEN == 64)
|
7'b0011011: if (IFunctD & IWValidFunct3D & `XLEN == 64)
|
||||||
ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_1_0_0_0_0_00_0; // IW-type ALU for RV64i
|
ControlsD = `CTRLW'b1_000_01_00_000_0_1_0_0_1_0_0_0_0_00_0; // IW-type ALU for RV64i
|
||||||
7'b0100011: if (SFunctD)
|
7'b0100011: if (SFunctD)
|
||||||
ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // stores
|
ControlsD = `CTRLW'b0_001_01_01_000_0_0_0_0_0_0_0_0_0_00_0; // stores
|
||||||
@ -254,7 +256,7 @@ module controller(
|
|||||||
|
|
||||||
bmuctrl bmuctrl(.clk, .reset, .StallD, .FlushD, .InstrD, .ALUOpD, .BSelectD, .ZBBSelectD,
|
bmuctrl bmuctrl(.clk, .reset, .StallD, .FlushD, .InstrD, .ALUOpD, .BSelectD, .ZBBSelectD,
|
||||||
.BRegWriteD, .BALUSrcBD, .BW64D, .BSubArithD, .IllegalBitmanipInstrD, .StallE, .FlushE,
|
.BRegWriteD, .BALUSrcBD, .BW64D, .BSubArithD, .IllegalBitmanipInstrD, .StallE, .FlushE,
|
||||||
.ALUSelectD, .BSelectE, .ZBBSelectE, .BRegWriteE, .BComparatorSignedE, .BALUControlE);
|
.ALUSelectD, .BSelectE, .ZBBSelectE, .BRegWriteE, .BALUControlE);
|
||||||
if (`ZBA_SUPPORTED) begin
|
if (`ZBA_SUPPORTED) begin
|
||||||
// ALU Decoding is more comprehensive when ZBA is supported. slt and slti conflicts with sh1add, sh1add.uw
|
// ALU Decoding is more comprehensive when ZBA is supported. slt and slti conflicts with sh1add, sh1add.uw
|
||||||
assign sltD = (Funct3D == 3'b010 & (~(Funct7D[4]) | ~OpD[5])) ;
|
assign sltD = (Funct3D == 3'b010 & (~(Funct7D[4]) | ~OpD[5])) ;
|
||||||
@ -280,7 +282,6 @@ module controller(
|
|||||||
assign BSelectE = 2'b00;
|
assign BSelectE = 2'b00;
|
||||||
assign BSelectD = 2'b00;
|
assign BSelectD = 2'b00;
|
||||||
assign ZBBSelectE = 3'b000;
|
assign ZBBSelectE = 3'b000;
|
||||||
assign BComparatorSignedE = 1'b0;
|
|
||||||
assign BALUControlE = 3'b0;
|
assign BALUControlE = 3'b0;
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -308,8 +309,7 @@ module controller(
|
|||||||
// Branch Logic
|
// Branch Logic
|
||||||
// The comparator handles both signed and unsigned branches using BranchSignedE
|
// The comparator handles both signed and unsigned branches using BranchSignedE
|
||||||
// Hence, only eq and lt flags are needed
|
// Hence, only eq and lt flags are needed
|
||||||
// We also want comparator to handle signed comparison on a max/min bitmanip instruction
|
assign BranchSignedE = (~(Funct3E[2:1] == 2'b11) & BranchE);
|
||||||
assign BranchSignedE = (~(Funct3E[2:1] == 2'b11) & BranchE) | BComparatorSignedE;
|
|
||||||
assign {eqE, ltE} = FlagsE;
|
assign {eqE, ltE} = FlagsE;
|
||||||
mux2 #(1) branchflagmux(eqE, ltE, Funct3E[2], BranchFlagE);
|
mux2 #(1) branchflagmux(eqE, ltE, Funct3E[2], BranchFlagE);
|
||||||
assign BranchTakenE = BranchFlagE ^ Funct3E[0];
|
assign BranchTakenE = BranchFlagE ^ Funct3E[0];
|
||||||
|
@ -114,7 +114,7 @@ module datapath (
|
|||||||
comparator #(`XLEN) comp(ForwardedSrcAE, ForwardedSrcBE, BranchSignedE, FlagsE);
|
comparator #(`XLEN) comp(ForwardedSrcAE, ForwardedSrcBE, BranchSignedE, FlagsE);
|
||||||
mux2 #(`XLEN) srcamux(ForwardedSrcAE, PCE, ALUSrcAE, SrcAE);
|
mux2 #(`XLEN) srcamux(ForwardedSrcAE, PCE, ALUSrcAE, SrcAE);
|
||||||
mux2 #(`XLEN) srcbmux(ForwardedSrcBE, ImmExtE, ALUSrcBE, SrcBE);
|
mux2 #(`XLEN) srcbmux(ForwardedSrcBE, ImmExtE, ALUSrcBE, SrcBE);
|
||||||
alu #(`XLEN) alu(SrcAE, SrcBE, W64E, SubArithE, ALUSelectE, BSelectE, ZBBSelectE, Funct3E, FlagsE, BALUControlE, ALUResultE, IEUAdrE);
|
alu #(`XLEN) alu(SrcAE, SrcBE, W64E, SubArithE, ALUSelectE, BSelectE, ZBBSelectE, Funct3E, BALUControlE, ALUResultE, IEUAdrE);
|
||||||
mux2 #(`XLEN) altresultmux(ImmExtE, PCLinkE, JumpE, AltResultE);
|
mux2 #(`XLEN) altresultmux(ImmExtE, PCLinkE, JumpE, AltResultE);
|
||||||
mux2 #(`XLEN) ieuresultmux(ALUResultE, AltResultE, ALUResultSrcE, IEUResultE);
|
mux2 #(`XLEN) ieuresultmux(ALUResultE, AltResultE, ALUResultSrcE, IEUResultE);
|
||||||
|
|
||||||
|
@ -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,
|
||||||
@ -106,8 +106,10 @@ module csr #(parameter
|
|||||||
logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW;
|
logic [31:0] MCOUNTINHIBIT_REGW, MCOUNTEREN_REGW, SCOUNTEREN_REGW;
|
||||||
logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM;
|
logic WriteMSTATUSM, WriteMSTATUSHM, WriteSSTATUSM;
|
||||||
logic CSRMWriteM, CSRSWriteM, CSRUWriteM;
|
logic CSRMWriteM, CSRSWriteM, CSRUWriteM;
|
||||||
|
logic UngatedCSRMWriteM;
|
||||||
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 +155,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,11 +198,12 @@ 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 UngatedCSRMWriteM = CSRWriteM & (PrivilegeModeW == `M_MODE);
|
||||||
assign CSRSWriteM = CSRWriteM & (|PrivilegeModeW);
|
assign CSRMWriteM = UngatedCSRMWriteM & InstrValidNotFlushedM;
|
||||||
assign CSRUWriteM = CSRWriteM;
|
assign CSRSWriteM = CSRWriteM & (|PrivilegeModeW) & InstrValidNotFlushedM;
|
||||||
|
assign CSRUWriteM = CSRWriteM & InstrValidNotFlushedM;
|
||||||
assign MTrapM = TrapM & (NextPrivilegeModeM == `M_MODE);
|
assign MTrapM = TrapM & (NextPrivilegeModeM == `M_MODE);
|
||||||
assign STrapM = TrapM & (NextPrivilegeModeM == `S_MODE) & `S_SUPPORTED;
|
assign STrapM = TrapM & (NextPrivilegeModeM == `S_MODE) & `S_SUPPORTED;
|
||||||
|
|
||||||
@ -208,7 +211,7 @@ module csr #(parameter
|
|||||||
// CSRs
|
// CSRs
|
||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
|
|
||||||
csri csri(.clk, .reset, .InstrValidNotFlushedM,
|
csri csri(.clk, .reset,
|
||||||
.CSRMWriteM, .CSRSWriteM, .CSRWriteValM, .CSRAdrM,
|
.CSRMWriteM, .CSRSWriteM, .CSRWriteValM, .CSRAdrM,
|
||||||
.MExtInt, .SExtInt, .MTimerInt, .STimerInt, .MSwInt,
|
.MExtInt, .SExtInt, .MTimerInt, .STimerInt, .MSwInt,
|
||||||
.MIDELEG_REGW, .MIP_REGW, .MIE_REGW, .MIP_REGW_writeable);
|
.MIDELEG_REGW, .MIP_REGW, .MIE_REGW, .MIP_REGW_writeable);
|
||||||
@ -222,8 +225,8 @@ module csr #(parameter
|
|||||||
.STATUS_MIE, .STATUS_SIE, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_TVM,
|
.STATUS_MIE, .STATUS_SIE, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_TVM,
|
||||||
.STATUS_FS, .BigEndianM);
|
.STATUS_FS, .BigEndianM);
|
||||||
|
|
||||||
csrm csrm(.clk, .reset, .InstrValidNotFlushedM,
|
csrm csrm(.clk, .reset,
|
||||||
.CSRMWriteM, .MTrapM, .CSRAdrM,
|
.UngatedCSRMWriteM, .CSRMWriteM, .MTrapM, .CSRAdrM,
|
||||||
.NextEPCM, .NextCauseM, .NextMtvalM, .MSTATUS_REGW, .MSTATUSH_REGW,
|
.NextEPCM, .NextCauseM, .NextMtvalM, .MSTATUS_REGW, .MSTATUSH_REGW,
|
||||||
.CSRWriteValM, .CSRMReadValM, .MTVEC_REGW,
|
.CSRWriteValM, .CSRMReadValM, .MTVEC_REGW,
|
||||||
.MEPC_REGW, .MCOUNTEREN_REGW, .MCOUNTINHIBIT_REGW,
|
.MEPC_REGW, .MCOUNTEREN_REGW, .MCOUNTINHIBIT_REGW,
|
||||||
@ -233,7 +236,7 @@ module csr #(parameter
|
|||||||
|
|
||||||
|
|
||||||
if (`S_SUPPORTED) begin:csrs
|
if (`S_SUPPORTED) begin:csrs
|
||||||
csrs csrs(.clk, .reset, .InstrValidNotFlushedM,
|
csrs csrs(.clk, .reset,
|
||||||
.CSRSWriteM, .STrapM, .CSRAdrM,
|
.CSRSWriteM, .STrapM, .CSRAdrM,
|
||||||
.NextEPCM, .NextCauseM, .NextMtvalM, .SSTATUS_REGW,
|
.NextEPCM, .NextCauseM, .NextMtvalM, .SSTATUS_REGW,
|
||||||
.STATUS_TVM, .MCOUNTEREN_TM(MCOUNTEREN_REGW[1]),
|
.STATUS_TVM, .MCOUNTEREN_TM(MCOUNTEREN_REGW[1]),
|
||||||
|
@ -35,7 +35,6 @@ module csri #(parameter
|
|||||||
SIE = 12'h104,
|
SIE = 12'h104,
|
||||||
SIP = 12'h144) (
|
SIP = 12'h144) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
input logic InstrValidNotFlushedM,
|
|
||||||
input logic CSRMWriteM, CSRSWriteM,
|
input logic CSRMWriteM, CSRSWriteM,
|
||||||
input logic [`XLEN-1:0] CSRWriteValM,
|
input logic [`XLEN-1:0] CSRWriteValM,
|
||||||
input logic [11:0] CSRAdrM,
|
input logic [11:0] CSRAdrM,
|
||||||
@ -50,10 +49,10 @@ module csri #(parameter
|
|||||||
logic STIP;
|
logic STIP;
|
||||||
|
|
||||||
// Interrupt Write Enables
|
// Interrupt Write Enables
|
||||||
assign WriteMIPM = CSRMWriteM & (CSRAdrM == MIP) & InstrValidNotFlushedM;
|
assign WriteMIPM = CSRMWriteM & (CSRAdrM == MIP);
|
||||||
assign WriteMIEM = CSRMWriteM & (CSRAdrM == MIE) & InstrValidNotFlushedM;
|
assign WriteMIEM = CSRMWriteM & (CSRAdrM == MIE);
|
||||||
assign WriteSIPM = CSRSWriteM & (CSRAdrM == SIP) & InstrValidNotFlushedM;
|
assign WriteSIPM = CSRSWriteM & (CSRAdrM == SIP);
|
||||||
assign WriteSIEM = CSRSWriteM & (CSRAdrM == SIE) & InstrValidNotFlushedM;
|
assign WriteSIEM = CSRSWriteM & (CSRAdrM == SIE);
|
||||||
|
|
||||||
// Interrupt Pending and Enable Registers
|
// Interrupt Pending and Enable Registers
|
||||||
// MEIP, MTIP, MSIP are read-only
|
// MEIP, MTIP, MSIP are read-only
|
||||||
|
@ -69,20 +69,20 @@ 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 UngatedCSRMWriteM, 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 +91,7 @@ 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, MCAUSE_REGW;
|
||||||
logic [`XLEN-1:0] MCAUSE_REGW, MTVAL_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;
|
||||||
@ -112,13 +111,13 @@ module csrm #(parameter
|
|||||||
else
|
else
|
||||||
assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7] | (PMPCFG_ARRAY_REGW[i+1][7] & PMPCFG_ARRAY_REGW[i+1][4:3] == 2'b01);
|
assign ADDRLocked[i] = PMPCFG_ARRAY_REGW[i][7] | (PMPCFG_ARRAY_REGW[i+1][7] & PMPCFG_ARRAY_REGW[i+1][4:3] == 2'b01);
|
||||||
|
|
||||||
assign WritePMPADDRM[i] = (CSRMWriteM & (CSRAdrM == (PMPADDR0+i))) & InstrValidNotFlushedM & ~ADDRLocked[i];
|
assign WritePMPADDRM[i] = (CSRMWriteM & (CSRAdrM == (PMPADDR0+i))) & ~ADDRLocked[i];
|
||||||
flopenr #(`PA_BITS-2) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM[`PA_BITS-3:0], PMPADDR_ARRAY_REGW[i]);
|
flopenr #(`PA_BITS-2) PMPADDRreg(clk, reset, WritePMPADDRM[i], CSRWriteValM[`PA_BITS-3:0], PMPADDR_ARRAY_REGW[i]);
|
||||||
if (`XLEN==64) begin
|
if (`XLEN==64) begin
|
||||||
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & InstrValidNotFlushedM & ~CFGLocked[i];
|
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+2*(i/8)))) & ~CFGLocked[i];
|
||||||
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i]);
|
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%8)*8+7:(i%8)*8], PMPCFG_ARRAY_REGW[i]);
|
||||||
end else begin
|
end else begin
|
||||||
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & InstrValidNotFlushedM & ~CFGLocked[i];
|
assign WritePMPCFGM[i] = (CSRMWriteM & (CSRAdrM == (PMPCFG0+i/4))) & ~CFGLocked[i];
|
||||||
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i]);
|
flopenr #(8) PMPCFGreg(clk, reset, WritePMPCFGM[i], CSRWriteValM[(i%4)*8+7:(i%4)*8], PMPCFG_ARRAY_REGW[i]);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -133,30 +132,30 @@ module csrm #(parameter
|
|||||||
assign MHARTID_REGW = 0;
|
assign MHARTID_REGW = 0;
|
||||||
|
|
||||||
// Write machine Mode CSRs
|
// Write machine Mode CSRs
|
||||||
assign WriteMSTATUSM = CSRMWriteM & (CSRAdrM == MSTATUS) & InstrValidNotFlushedM;
|
assign WriteMSTATUSM = CSRMWriteM & (CSRAdrM == MSTATUS);
|
||||||
assign WriteMSTATUSHM = CSRMWriteM & (CSRAdrM == MSTATUSH) & InstrValidNotFlushedM & (`XLEN==32);
|
assign WriteMSTATUSHM = CSRMWriteM & (CSRAdrM == MSTATUSH)& (`XLEN==32);
|
||||||
assign WriteMTVECM = CSRMWriteM & (CSRAdrM == MTVEC) & InstrValidNotFlushedM;
|
assign WriteMTVECM = CSRMWriteM & (CSRAdrM == MTVEC);
|
||||||
assign WriteMEDELEGM = CSRMWriteM & (CSRAdrM == MEDELEG) & InstrValidNotFlushedM;
|
assign WriteMEDELEGM = CSRMWriteM & (CSRAdrM == MEDELEG);
|
||||||
assign WriteMIDELEGM = CSRMWriteM & (CSRAdrM == MIDELEG) & InstrValidNotFlushedM;
|
assign WriteMIDELEGM = CSRMWriteM & (CSRAdrM == MIDELEG);
|
||||||
assign WriteMSCRATCHM = CSRMWriteM & (CSRAdrM == MSCRATCH) & InstrValidNotFlushedM;
|
assign WriteMSCRATCHM = CSRMWriteM & (CSRAdrM == MSCRATCH);
|
||||||
assign WriteMEPCM = MTrapM | (CSRMWriteM & (CSRAdrM == MEPC)) & InstrValidNotFlushedM;
|
assign WriteMEPCM = MTrapM | (CSRMWriteM & (CSRAdrM == MEPC));
|
||||||
assign WriteMCAUSEM = MTrapM | (CSRMWriteM & (CSRAdrM == MCAUSE)) & InstrValidNotFlushedM;
|
assign WriteMCAUSEM = MTrapM | (CSRMWriteM & (CSRAdrM == MCAUSE));
|
||||||
assign WriteMTVALM = MTrapM | (CSRMWriteM & (CSRAdrM == MTVAL)) & InstrValidNotFlushedM;
|
assign WriteMTVALM = MTrapM | (CSRMWriteM & (CSRAdrM == MTVAL));
|
||||||
assign WriteMCOUNTERENM = CSRMWriteM & (CSRAdrM == MCOUNTEREN) & InstrValidNotFlushedM;
|
assign WriteMCOUNTERENM = CSRMWriteM & (CSRAdrM == MCOUNTEREN);
|
||||||
assign WriteMCOUNTINHIBITM = CSRMWriteM & (CSRAdrM == MCOUNTINHIBIT) & InstrValidNotFlushedM;
|
assign WriteMCOUNTINHIBITM = CSRMWriteM & (CSRAdrM == MCOUNTINHIBIT);
|
||||||
|
|
||||||
assign IllegalCSRMWriteReadonlyM = CSRMWriteM & (CSRAdrM == MVENDORID | CSRAdrM == MARCHID | CSRAdrM == MIMPID | CSRAdrM == MHARTID);
|
assign IllegalCSRMWriteReadonlyM = UngatedCSRMWriteM & (CSRAdrM == MVENDORID | CSRAdrM == MARCHID | CSRAdrM == MIMPID | CSRAdrM == MHARTID);
|
||||||
|
|
||||||
// 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 #(`XLEN) MCAUSEreg(clk, reset, WriteMCAUSEM, {NextCauseM[4], {(`XLEN-5){1'b0}}, NextCauseM[3:0]}, 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,7 +191,7 @@ 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};
|
||||||
|
@ -45,10 +45,10 @@ module csrs #(parameter
|
|||||||
STIMECMPH = 12'h15D,
|
STIMECMPH = 12'h15D,
|
||||||
SATP = 12'h180) (
|
SATP = 12'h180) (
|
||||||
input logic clk, reset,
|
input logic clk, reset,
|
||||||
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,
|
||||||
@ -72,28 +72,26 @@ module csrs #(parameter
|
|||||||
logic WriteSSCRATCHM, WriteSEPCM;
|
logic WriteSSCRATCHM, WriteSEPCM;
|
||||||
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, SCAUSE_REGW;
|
||||||
logic [`XLEN-1:0] SCAUSE_REGW;
|
|
||||||
logic [63:0] STIMECMP_REGW;
|
logic [63:0] STIMECMP_REGW;
|
||||||
|
|
||||||
// write enables
|
// write enables
|
||||||
// *** can InstrValidNotFlushed be factored out of all these writes into CSRWriteM?
|
assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS);
|
||||||
assign WriteSSTATUSM = CSRSWriteM & (CSRAdrM == SSTATUS) & InstrValidNotFlushedM;
|
assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC);
|
||||||
assign WriteSTVECM = CSRSWriteM & (CSRAdrM == STVEC) & InstrValidNotFlushedM;
|
assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH);
|
||||||
assign WriteSSCRATCHM = CSRSWriteM & (CSRAdrM == SSCRATCH) & InstrValidNotFlushedM;
|
assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC));
|
||||||
assign WriteSEPCM = STrapM | (CSRSWriteM & (CSRAdrM == SEPC)) & InstrValidNotFlushedM;
|
assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE));
|
||||||
assign WriteSCAUSEM = STrapM | (CSRSWriteM & (CSRAdrM == SCAUSE)) & InstrValidNotFlushedM;
|
assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL));
|
||||||
assign WriteSTVALM = STrapM | (CSRSWriteM & (CSRAdrM == STVAL)) & InstrValidNotFlushedM;
|
assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == `M_MODE | ~STATUS_TVM);
|
||||||
assign WriteSATPM = CSRSWriteM & (CSRAdrM == SATP) & (PrivilegeModeW == `M_MODE | ~STATUS_TVM) & InstrValidNotFlushedM;
|
assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN);
|
||||||
assign WriteSCOUNTERENM = CSRSWriteM & (CSRAdrM == SCOUNTEREN) & InstrValidNotFlushedM;
|
assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & (PrivilegeModeW == `M_MODE | MCOUNTEREN_TM);
|
||||||
assign WriteSTIMECMPM = CSRSWriteM & (CSRAdrM == STIMECMP) & (PrivilegeModeW == `M_MODE | MCOUNTEREN_TM) & InstrValidNotFlushedM;
|
assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & (PrivilegeModeW == `M_MODE | MCOUNTEREN_TM) & (`XLEN == 32);
|
||||||
assign WriteSTIMECMPHM = CSRSWriteM & (CSRAdrM == STIMECMPH) & (PrivilegeModeW == `M_MODE | MCOUNTEREN_TM) & (`XLEN == 32) & InstrValidNotFlushedM;
|
|
||||||
|
|
||||||
// CSRs
|
// CSRs
|
||||||
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 #(`XLEN) SCAUSEreg(clk, reset, WriteSCAUSEM, {NextCauseM[4], {(`XLEN-5){1'b0}}, NextCauseM[3:0]}, 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);
|
||||||
|
@ -51,9 +51,8 @@ module csru #(parameter
|
|||||||
logic SetOrWriteFFLAGSM;
|
logic SetOrWriteFFLAGSM;
|
||||||
|
|
||||||
// Write enables
|
// Write enables
|
||||||
//assign WriteFCSRM = CSRUWriteM & (CSRAdrM == FCSR) & InstrValidNotFlushedM;
|
assign WriteFRMM = CSRUWriteM & (STATUS_FS != 2'b00) & (CSRAdrM == FRM | CSRAdrM == FCSR);
|
||||||
assign WriteFRMM = (CSRUWriteM & (STATUS_FS != 2'b00) & (CSRAdrM == FRM | CSRAdrM == FCSR)) & InstrValidNotFlushedM;
|
assign WriteFFLAGSM = CSRUWriteM & (STATUS_FS != 2'b00) & (CSRAdrM == FFLAGS | CSRAdrM == FCSR);
|
||||||
assign WriteFFLAGSM = (CSRUWriteM & (STATUS_FS != 2'b00) & (CSRAdrM == FFLAGS | CSRAdrM == FCSR)) & InstrValidNotFlushedM;
|
|
||||||
|
|
||||||
// Write Values
|
// Write Values
|
||||||
assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0];
|
assign NextFRMM = (CSRAdrM == FCSR) ? CSRWriteValM[7:5] : CSRWriteValM[2:0];
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
///////////////////////////////////////////
|
<///////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// Written: me@KatherineParry.com
|
// Written: me@KatherineParry.com
|
||||||
// Modified: 7/5/2022
|
// Modified: 7/5/2022
|
||||||
|
// Modified: 4/2/2023
|
||||||
//
|
//
|
||||||
// Purpose: Testbench for Testfloat
|
// Purpose: Testbench for Testfloat
|
||||||
//
|
//
|
||||||
@ -32,75 +33,74 @@
|
|||||||
module testbenchfp;
|
module testbenchfp;
|
||||||
parameter TEST="none";
|
parameter TEST="none";
|
||||||
|
|
||||||
string Tests[]; // list of tests to be run
|
string Tests[]; // list of tests to be run
|
||||||
logic [2:0] OpCtrl[]; // list of op controls
|
logic [2:0] OpCtrl[]; // list of op controls
|
||||||
logic [2:0] Unit[]; // list of units being tested
|
logic [2:0] Unit[]; // list of units being tested
|
||||||
logic WriteInt[]; // Is being written to integer resgiter
|
logic WriteInt[]; // Is being written to integer resgiter
|
||||||
logic [2:0] Frm[4:0] = {3'b100, 3'b010, 3'b011, 3'b001, 3'b000}; // rounding modes: rne-000, rz-001, ru-011, rd-010, rnm-100
|
logic [2:0] Frm[4:0] = {3'b100, 3'b010, 3'b011, 3'b001, 3'b000}; // rounding modes: rne-000, rz-001, ru-011, rd-010, rnm-100
|
||||||
logic [1:0] Fmt[]; // list of formats for the other units
|
logic [1:0] Fmt[]; // list of formats for the other units
|
||||||
|
|
||||||
|
logic clk=0;
|
||||||
|
logic [31:0] TestNum=0; // index for the test
|
||||||
|
logic [31:0] OpCtrlNum=0; // index for OpCtrl
|
||||||
|
logic [31:0] errors=0; // how many errors
|
||||||
|
logic [31:0] VectorNum=0; // index for test vector
|
||||||
|
logic [31:0] FrmNum=0; // index for rounding mode
|
||||||
|
logic [`FLEN*4+7:0] TestVectors[8388609:0]; // list of test vectors
|
||||||
|
|
||||||
logic clk=0;
|
logic [1:0] FmtVal; // value of the current Fmt
|
||||||
logic [31:0] TestNum=0; // index for the test
|
logic [2:0] UnitVal, OpCtrlVal, FrmVal; // value of the currnet Unit/OpCtrl/FrmVal
|
||||||
logic [31:0] OpCtrlNum=0; // index for OpCtrl
|
logic WriteIntVal; // value of the current WriteInt
|
||||||
logic [31:0] errors=0; // how many errors
|
logic [`FLEN-1:0] X, Y, Z; // inputs read from TestFloat
|
||||||
logic [31:0] VectorNum=0; // index for test vector
|
logic [`XLEN-1:0] SrcA; // integer input
|
||||||
logic [31:0] FrmNum=0; // index for rounding mode
|
logic [`FLEN-1:0] Ans; // correct answer from TestFloat
|
||||||
logic [`FLEN*4+7:0] TestVectors[8388609:0]; // list of test vectors
|
logic [`FLEN-1:0] Res; // result from other units
|
||||||
|
logic [4:0] AnsFlg; // correct flags read from testfloat
|
||||||
logic [1:0] FmtVal; // value of the current Fmt
|
logic [4:0] ResFlg, Flg; // Result flags
|
||||||
logic [2:0] UnitVal, OpCtrlVal, FrmVal; // value of the currnet Unit/OpCtrl/FrmVal
|
logic [`FMTBITS-1:0] ModFmt; // format - 10 = half, 00 = single, 01 = double, 11 = quad
|
||||||
logic WriteIntVal; // value of the current WriteInt
|
logic [`FLEN-1:0] FpRes, FpCmpRes; // Results from each unit
|
||||||
logic [`FLEN-1:0] X, Y, Z; // inputs read from TestFloat
|
logic [`XLEN-1:0] IntRes, CmpRes; // Results from each unit
|
||||||
logic [`XLEN-1:0] SrcA; // integer input
|
logic [4:0] FmaFlg, CvtFlg, DivFlg, CmpFlg; // Outputed flags
|
||||||
logic [`FLEN-1:0] Ans; // correct answer from TestFloat
|
logic AnsNaN, ResNaN, NaNGood;
|
||||||
logic [`FLEN-1:0] Res; // result from other units
|
logic Xs, Ys, Zs; // sign of the inputs
|
||||||
logic [4:0] AnsFlg; // correct flags read from testfloat
|
logic [`NE-1:0] Xe, Ye, Ze; // exponent of the inputs
|
||||||
logic [4:0] ResFlg, Flg; // Result flags
|
logic [`NF:0] Xm, Ym, Zm; // mantissas of the inputs
|
||||||
logic [`FMTBITS-1:0] ModFmt; // format - 10 = half, 00 = single, 01 = double, 11 = quad
|
logic XNaN, YNaN, ZNaN; // is the input NaN
|
||||||
logic [`FLEN-1:0] FpRes, FpCmpRes; // Results from each unit
|
logic XSNaN, YSNaN, ZSNaN; // is the input a signaling NaN
|
||||||
logic [`XLEN-1:0] IntRes, CmpRes; // Results from each unit
|
logic XSubnorm, ZSubnorm; // is the input denormalized
|
||||||
logic [4:0] FmaFlg, CvtFlg, DivFlg, CmpFlg; // Outputed flags
|
logic XInf, YInf, ZInf; // is the input infinity
|
||||||
logic AnsNaN, ResNaN, NaNGood;
|
logic XZero, YZero, ZZero; // is the input zero
|
||||||
logic Xs, Ys, Zs; // sign of the inputs
|
logic XExpMax, YExpMax, ZExpMax; // is the input's exponent all ones
|
||||||
logic [`NE-1:0] Xe, Ye, Ze; // exponent of the inputs
|
logic [`CVTLEN-1:0] CvtLzcInE; // input to the Leading Zero Counter (priority encoder)
|
||||||
logic [`NF:0] Xm, Ym, Zm; // mantissas of the inputs
|
logic IntZero;
|
||||||
logic XNaN, YNaN, ZNaN; // is the input NaN
|
logic CvtResSgnE;
|
||||||
logic XSNaN, YSNaN, ZSNaN; // is the input a signaling NaN
|
logic [`NE:0] CvtCalcExpE; // the calculated expoent
|
||||||
logic XSubnorm, ZSubnorm; // is the input denormalized
|
logic [`LOGCVTLEN-1:0] CvtShiftAmtE; // how much to shift by
|
||||||
logic XInf, YInf, ZInf; // is the input infinity
|
logic [`DIVb:0] Quot;
|
||||||
logic XZero, YZero, ZZero; // is the input zero
|
logic CvtResSubnormUfE;
|
||||||
logic XExpMax, YExpMax, ZExpMax; // is the input's exponent all ones
|
logic DivStart, FDivBusyE, OldFDivBusyE;
|
||||||
logic [`CVTLEN-1:0] CvtLzcInE; // input to the Leading Zero Counter (priority encoder)
|
logic reset = 1'b0;
|
||||||
logic IntZero;
|
logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt;
|
||||||
logic CvtResSgnE;
|
logic [`DURLEN-1:0] Dur;
|
||||||
logic [`NE:0] CvtCalcExpE; // the calculated expoent
|
|
||||||
logic [`LOGCVTLEN-1:0] CvtShiftAmtE; // how much to shift by
|
|
||||||
logic [`DIVb:0] Quot;
|
|
||||||
logic CvtResSubnormUfE;
|
|
||||||
logic DivStart, FDivBusyE, OldFDivBusyE;
|
|
||||||
logic reset = 1'b0;
|
|
||||||
logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt;
|
|
||||||
logic [`DURLEN-1:0] Dur;
|
|
||||||
|
|
||||||
// in-between FMA signals
|
// in-between FMA signals
|
||||||
logic Mult;
|
logic Mult;
|
||||||
logic Ss;
|
logic Ss;
|
||||||
logic [`NE+1:0] Pe;
|
logic [`NE+1:0] Pe;
|
||||||
logic [`NE+1:0] Se;
|
logic [`NE+1:0] Se;
|
||||||
logic ASticky;
|
logic ASticky;
|
||||||
logic KillProd;
|
logic KillProd;
|
||||||
logic [$clog2(3*`NF+5)-1:0] SCnt;
|
logic [$clog2(3*`NF+5)-1:0] SCnt;
|
||||||
logic [3*`NF+3:0] Sm;
|
logic [3*`NF+3:0] Sm;
|
||||||
logic InvA;
|
logic InvA;
|
||||||
logic NegSum;
|
logic NegSum;
|
||||||
logic As;
|
logic As;
|
||||||
logic Ps;
|
logic Ps;
|
||||||
logic DivSticky;
|
logic DivSticky;
|
||||||
logic DivDone;
|
logic DivDone;
|
||||||
logic DivNegSticky;
|
logic DivNegSticky;
|
||||||
logic [`NE+1:0] DivCalcExp;
|
logic [`NE+1:0] DivCalcExp;
|
||||||
logic divsqrtop;
|
logic divsqrtop;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
@ -126,28 +126,28 @@ module testbenchfp;
|
|||||||
$display("TEST is %s", TEST);
|
$display("TEST is %s", TEST);
|
||||||
if (`Q_SUPPORTED) begin // if Quad percision is supported
|
if (`Q_SUPPORTED) begin // if Quad percision is supported
|
||||||
if (TEST === "cvtint"| TEST === "all") begin // if testing integer conversion
|
if (TEST === "cvtint"| TEST === "all") begin // if testing integer conversion
|
||||||
// add the 128-bit cvtint tests to the to-be-tested list
|
// add the 128-bit cvtint tests to the to-be-tested list
|
||||||
Tests = {Tests, f128rv32cvtint};
|
Tests = {Tests, f128rv32cvtint};
|
||||||
// add the op-codes for these tests to the op-code list
|
// add the op-codes for these tests to the op-code list
|
||||||
OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL};
|
OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL};
|
||||||
WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1};
|
WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1};
|
||||||
// add what unit is used and the fmt to their lists (one for each test)
|
// add what unit is used and the fmt to their lists (one for each test)
|
||||||
for(int i = 0; i<20; i++) begin
|
for(int i = 0; i<20; i++) begin
|
||||||
Unit = {Unit, `CVTINTUNIT};
|
Unit = {Unit, `CVTINTUNIT};
|
||||||
Fmt = {Fmt, 2'b11};
|
Fmt = {Fmt, 2'b11};
|
||||||
end
|
end
|
||||||
if (`XLEN == 64) begin // if 64-bit integers are supported add their conversions
|
if (`XLEN == 64) begin // if 64-bit integers are supported add their conversions
|
||||||
Tests = {Tests, f128rv64cvtint};
|
Tests = {Tests, f128rv64cvtint};
|
||||||
// add the op-codes for these tests to the op-code list
|
// add the op-codes for these tests to the op-code list
|
||||||
OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL};
|
OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL};
|
||||||
WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1};
|
WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1};
|
||||||
// add what unit is used and the fmt to their lists (one for each test)
|
// add what unit is used and the fmt to their lists (one for each test)
|
||||||
for(int i = 0; i<20; i++) begin
|
for(int i = 0; i<20; i++) begin
|
||||||
Unit = {Unit, `CVTINTUNIT};
|
Unit = {Unit, `CVTINTUNIT};
|
||||||
Fmt = {Fmt, 2'b11};
|
Fmt = {Fmt, 2'b11};
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if (TEST === "cvtfp" | TEST === "all") begin // if the floating-point conversions are being tested
|
if (TEST === "cvtfp" | TEST === "all") begin // if the floating-point conversions are being tested
|
||||||
if(`D_SUPPORTED) begin // if double precision is supported
|
if(`D_SUPPORTED) begin // if double precision is supported
|
||||||
// add the 128 <-> 64 bit conversions to the to-be-tested list
|
// add the 128 <-> 64 bit conversions to the to-be-tested list
|
||||||
@ -270,27 +270,27 @@ module testbenchfp;
|
|||||||
end
|
end
|
||||||
if (`D_SUPPORTED) begin // if double precision is supported
|
if (`D_SUPPORTED) begin // if double precision is supported
|
||||||
if (TEST === "cvtint"| TEST === "all") begin // if integer conversion is being tested
|
if (TEST === "cvtint"| TEST === "all") begin // if integer conversion is being tested
|
||||||
Tests = {Tests, f64rv32cvtint};
|
Tests = {Tests, f64rv32cvtint};
|
||||||
// add the op-codes for these tests to the op-code list
|
// add the op-codes for these tests to the op-code list
|
||||||
OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL};
|
OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL};
|
||||||
WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1};
|
WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1};
|
||||||
// add what unit is used and the fmt to their lists (one for each test)
|
// add what unit is used and the fmt to their lists (one for each test)
|
||||||
for(int i = 0; i<20; i++) begin
|
for(int i = 0; i<20; i++) begin
|
||||||
Unit = {Unit, `CVTINTUNIT};
|
Unit = {Unit, `CVTINTUNIT};
|
||||||
Fmt = {Fmt, 2'b01};
|
Fmt = {Fmt, 2'b01};
|
||||||
end
|
end
|
||||||
if (`XLEN == 64) begin // if 64-bit integers are being supported
|
if (`XLEN == 64) begin // if 64-bit integers are being supported
|
||||||
Tests = {Tests, f64rv64cvtint};
|
Tests = {Tests, f64rv64cvtint};
|
||||||
// add the op-codes for these tests to the op-code list
|
// add the op-codes for these tests to the op-code list
|
||||||
OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL};
|
OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL};
|
||||||
WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1};
|
WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1};
|
||||||
// add what unit is used and the fmt to their lists (one for each test)
|
// add what unit is used and the fmt to their lists (one for each test)
|
||||||
for(int i = 0; i<20; i++) begin
|
for(int i = 0; i<20; i++) begin
|
||||||
Unit = {Unit, `CVTINTUNIT};
|
Unit = {Unit, `CVTINTUNIT};
|
||||||
Fmt = {Fmt, 2'b01};
|
Fmt = {Fmt, 2'b01};
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if (TEST === "cvtfp" | TEST === "all") begin // if floating point conversions are being tested
|
if (TEST === "cvtfp" | TEST === "all") begin // if floating point conversions are being tested
|
||||||
if(`F_SUPPORTED) begin // if single precision is supported
|
if(`F_SUPPORTED) begin // if single precision is supported
|
||||||
// add the 64 <-> 32 bit conversions to the to-be-tested list
|
// add the 64 <-> 32 bit conversions to the to-be-tested list
|
||||||
@ -397,27 +397,27 @@ module testbenchfp;
|
|||||||
end
|
end
|
||||||
if (`F_SUPPORTED) begin // if single precision being supported
|
if (`F_SUPPORTED) begin // if single precision being supported
|
||||||
if (TEST === "cvtint"| TEST === "all") begin // if integer conversion is being tested
|
if (TEST === "cvtint"| TEST === "all") begin // if integer conversion is being tested
|
||||||
Tests = {Tests, f32rv32cvtint};
|
Tests = {Tests, f32rv32cvtint};
|
||||||
// add the op-codes for these tests to the op-code list
|
// add the op-codes for these tests to the op-code list
|
||||||
OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL};
|
OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL};
|
||||||
WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1};
|
WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1};
|
||||||
// add what unit is used and the fmt to their lists (one for each test)
|
// add what unit is used and the fmt to their lists (one for each test)
|
||||||
for(int i = 0; i<20; i++) begin
|
for(int i = 0; i<20; i++) begin
|
||||||
Unit = {Unit, `CVTINTUNIT};
|
Unit = {Unit, `CVTINTUNIT};
|
||||||
Fmt = {Fmt, 2'b00};
|
Fmt = {Fmt, 2'b00};
|
||||||
end
|
end
|
||||||
if (`XLEN == 64) begin // if 64-bit integers are supported
|
if (`XLEN == 64) begin // if 64-bit integers are supported
|
||||||
Tests = {Tests, f32rv64cvtint};
|
Tests = {Tests, f32rv64cvtint};
|
||||||
// add the op-codes for these tests to the op-code list
|
// add the op-codes for these tests to the op-code list
|
||||||
OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL};
|
OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL};
|
||||||
WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1};
|
WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1};
|
||||||
// add what unit is used and the fmt to their lists (one for each test)
|
// add what unit is used and the fmt to their lists (one for each test)
|
||||||
for(int i = 0; i<20; i++) begin
|
for(int i = 0; i<20; i++) begin
|
||||||
Unit = {Unit, `CVTINTUNIT};
|
Unit = {Unit, `CVTINTUNIT};
|
||||||
Fmt = {Fmt, 2'b00};
|
Fmt = {Fmt, 2'b00};
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if (TEST === "cvtfp" | TEST === "all") begin // if floating point conversion is being tested
|
if (TEST === "cvtfp" | TEST === "all") begin // if floating point conversion is being tested
|
||||||
if(`ZFH_SUPPORTED) begin
|
if(`ZFH_SUPPORTED) begin
|
||||||
// add the 32 <-> 16 bit conversions to the to-be-tested list
|
// add the 32 <-> 16 bit conversions to the to-be-tested list
|
||||||
@ -508,27 +508,27 @@ module testbenchfp;
|
|||||||
end
|
end
|
||||||
if (`ZFH_SUPPORTED) begin // if half precision supported
|
if (`ZFH_SUPPORTED) begin // if half precision supported
|
||||||
if (TEST === "cvtint"| TEST === "all") begin // if in conversions are being tested
|
if (TEST === "cvtint"| TEST === "all") begin // if in conversions are being tested
|
||||||
Tests = {Tests, f16rv32cvtint};
|
Tests = {Tests, f16rv32cvtint};
|
||||||
// add the op-codes for these tests to the op-code list
|
// add the op-codes for these tests to the op-code list
|
||||||
OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL};
|
OpCtrl = {OpCtrl, `FROM_UI_OPCTRL, `FROM_I_OPCTRL, `TO_UI_OPCTRL, `TO_I_OPCTRL};
|
||||||
WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1};
|
WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1};
|
||||||
// add what unit is used and the fmt to their lists (one for each test)
|
// add what unit is used and the fmt to their lists (one for each test)
|
||||||
for(int i = 0; i<20; i++) begin
|
for(int i = 0; i<20; i++) begin
|
||||||
Unit = {Unit, `CVTINTUNIT};
|
Unit = {Unit, `CVTINTUNIT};
|
||||||
Fmt = {Fmt, 2'b10};
|
Fmt = {Fmt, 2'b10};
|
||||||
end
|
end
|
||||||
if (`XLEN == 64) begin // if 64-bit integers are supported
|
if (`XLEN == 64) begin // if 64-bit integers are supported
|
||||||
Tests = {Tests, f16rv64cvtint};
|
Tests = {Tests, f16rv64cvtint};
|
||||||
// add the op-codes for these tests to the op-code list
|
// add the op-codes for these tests to the op-code list
|
||||||
OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL};
|
OpCtrl = {OpCtrl, `FROM_UL_OPCTRL, `FROM_L_OPCTRL, `TO_UL_OPCTRL, `TO_L_OPCTRL};
|
||||||
WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1};
|
WriteInt = {WriteInt, 1'b0, 1'b0, 1'b1, 1'b1};
|
||||||
// add what unit is used and the fmt to their lists (one for each test)
|
// add what unit is used and the fmt to their lists (one for each test)
|
||||||
for(int i = 0; i<20; i++) begin
|
for(int i = 0; i<20; i++) begin
|
||||||
Unit = {Unit, `CVTINTUNIT};
|
Unit = {Unit, `CVTINTUNIT};
|
||||||
Fmt = {Fmt, 2'b10};
|
Fmt = {Fmt, 2'b10};
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if (TEST === "cmp" | TEST === "all") begin // if comparisions are being tested
|
if (TEST === "cmp" | TEST === "all") begin // if comparisions are being tested
|
||||||
// add the correct tests/op-ctrls/unit/fmt to their lists
|
// add the correct tests/op-ctrls/unit/fmt to their lists
|
||||||
Tests = {Tests, f16cmp};
|
Tests = {Tests, f16cmp};
|
||||||
@ -656,7 +656,8 @@ module testbenchfp;
|
|||||||
end
|
end
|
||||||
|
|
||||||
// extract the inputs (X, Y, Z, SrcA) and the output (Ans, AnsFlg) from the current test vector
|
// extract the inputs (X, Y, Z, SrcA) and the output (Ans, AnsFlg) from the current test vector
|
||||||
readvectors readvectors (.clk, .Fmt(FmtVal), .ModFmt, .TestVector(TestVectors[VectorNum]), .VectorNum, .Ans(Ans), .AnsFlg(AnsFlg), .SrcA,
|
readvectors readvectors (.clk, .Fmt(FmtVal), .ModFmt, .TestVector(TestVectors[VectorNum]),
|
||||||
|
.VectorNum, .Ans(Ans), .AnsFlg(AnsFlg), .SrcA,
|
||||||
.Xs, .Ys, .Zs, .Unit(UnitVal),
|
.Xs, .Ys, .Zs, .Unit(UnitVal),
|
||||||
.Xe, .Ye, .Ze, .TestNum, .OpCtrl(OpCtrlVal),
|
.Xe, .Ye, .Ze, .TestNum, .OpCtrl(OpCtrlVal),
|
||||||
.Xm, .Ym, .Zm, .DivStart,
|
.Xm, .Ym, .Zm, .DivStart,
|
||||||
@ -680,7 +681,7 @@ module testbenchfp;
|
|||||||
///////////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// instantiate devices under test
|
// instantiate devices under test
|
||||||
if (TEST === "fma"| TEST === "mul" | TEST === "add" | TEST === "all") begin : fma
|
if (TEST === "fma"| TEST === "mul" | TEST === "add" | TEST === "sub" | TEST === "all") begin : fma
|
||||||
fma fma(.Xs(Xs), .Ys(Ys), .Zs(Zs),
|
fma fma(.Xs(Xs), .Ys(Ys), .Zs(Zs),
|
||||||
.Xe(Xe), .Ye(Ye), .Ze(Ze),
|
.Xe(Xe), .Ye(Ye), .Ze(Ze),
|
||||||
.Xm(Xm), .Ym(Ym), .Zm(Zm),
|
.Xm(Xm), .Ym(Ym), .Zm(Zm),
|
||||||
|
@ -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
|
||||||
|
@ -47,7 +47,9 @@ string tvpaths[] = '{
|
|||||||
"ieu",
|
"ieu",
|
||||||
"ebu",
|
"ebu",
|
||||||
"csrwrites",
|
"csrwrites",
|
||||||
"priv"
|
"priv",
|
||||||
|
"ifu",
|
||||||
|
"fpu"
|
||||||
};
|
};
|
||||||
|
|
||||||
string coremark[] = '{
|
string coremark[] = '{
|
||||||
|
@ -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
|
||||||
|
73
tests/coverage/fpu.S
Normal file
73
tests/coverage/fpu.S
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
///////////////////////////////////////////
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
# Tests for fpu/fctrl.sv
|
||||||
|
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
|
||||||
|
|
40
tests/coverage/ifu.S
Normal file
40
tests/coverage/ifu.S
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
///////////////////////////////////////////
|
||||||
|
// ifu.S
|
||||||
|
//
|
||||||
|
// Written: sriley@g.hmc.edu 28 March 2023
|
||||||
|
//
|
||||||
|
// Purpose: Test coverage for IFU
|
||||||
|
//
|
||||||
|
// 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:
|
||||||
|
# turn floating point on
|
||||||
|
li t0, 0x2000
|
||||||
|
csrs mstatus, t0
|
||||||
|
|
||||||
|
# calling compressed floating point load double instruction
|
||||||
|
//.halfword 0x2000 // CL type compressed floating-point ld-->funct3,imm,rs1',imm,rd',op
|
||||||
|
// binary version 0000 0000 0000 0000 0010 0000 0000 0000
|
||||||
|
mv s0, sp
|
||||||
|
c.fld fs0, 0(s0)
|
||||||
|
|
||||||
|
j done
|
@ -36,4 +36,11 @@ main:
|
|||||||
addi t0, zero, 0
|
addi t0, zero, 0
|
||||||
csrr t0, stimecmp
|
csrr t0, stimecmp
|
||||||
|
|
||||||
|
# Test write to STVAL, SCAUSE, SEPC, and STIMECMP CSRs
|
||||||
|
li t0, 0
|
||||||
|
csrw stval, t0
|
||||||
|
csrw scause, t0
|
||||||
|
csrw sepc, t0
|
||||||
|
csrw stimecmp, t0
|
||||||
|
|
||||||
j done
|
j done
|
||||||
|
4
tests/fp/combined_IF_vectors/IF_vectors/README
Normal file
4
tests/fp/combined_IF_vectors/IF_vectors/README
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
This folder holds the archtest and testfloat vectors necessary fo evaluating performance
|
||||||
|
of standalone intdiv vs combined IFdivsqrt
|
||||||
|
|
||||||
|
to generate vectors, uncomment line 8 in create_all_vectors.sh
|
8
tests/fp/combined_IF_vectors/create_IF_vectors.sh
Executable file
8
tests/fp/combined_IF_vectors/create_IF_vectors.sh
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
# create test vectors for stand alone int
|
||||||
|
|
||||||
|
./extract_testfloat_vectors.py
|
||||||
|
./extract_arch_vectors.py
|
||||||
|
|
||||||
|
# to create tvs for evaluation of combined IFdivsqrt
|
||||||
|
#./combined_IF_vectors/create_IF_vectors.sh
|
251
tests/fp/combined_IF_vectors/extract_arch_vectors.py
Executable file
251
tests/fp/combined_IF_vectors/extract_arch_vectors.py
Executable file
@ -0,0 +1,251 @@
|
|||||||
|
#! /usr/bin/python3
|
||||||
|
|
||||||
|
# author: Alessandro Maiuolo
|
||||||
|
# contact: amaiuolo@g.hmc.edu
|
||||||
|
# date created: 3-29-2023
|
||||||
|
|
||||||
|
# extract all arch test vectors
|
||||||
|
import os
|
||||||
|
wally = os.popen('echo $WALLY').read().strip()
|
||||||
|
|
||||||
|
def ext_bits(my_string):
|
||||||
|
target_len = 32 # we want 128 bits, div by 4 bc hex notation
|
||||||
|
zeroes_to_add = target_len - len(my_string)
|
||||||
|
return zeroes_to_add*"0" + my_string
|
||||||
|
|
||||||
|
def twos_comp(b, x):
|
||||||
|
if b == 32:
|
||||||
|
return hex(0x100000000 - int(x,16))[2:]
|
||||||
|
elif b == 64:
|
||||||
|
return hex(0x10000000000000000 - int(x,16))[2:]
|
||||||
|
else:
|
||||||
|
return "UNEXPECTED_BITSIZE"
|
||||||
|
|
||||||
|
def unpack_rf(packed):
|
||||||
|
bin_u = bin(int(packed, 16))[2:].zfill(8) # translate to binary
|
||||||
|
flags = hex(int(bin_u[3:],2))[2:].zfill(2)
|
||||||
|
rounding_mode = hex(int(bin_u[:3],2))[2:]
|
||||||
|
return flags, rounding_mode
|
||||||
|
|
||||||
|
# rounding mode dictionary
|
||||||
|
round_dict = {
|
||||||
|
"rne":"0",
|
||||||
|
"rnm":"4",
|
||||||
|
"ru":"3",
|
||||||
|
"rz":"1",
|
||||||
|
"rd":"2",
|
||||||
|
"dyn":"7"
|
||||||
|
}
|
||||||
|
|
||||||
|
# fcsr dictionary
|
||||||
|
fcsr_dict = {
|
||||||
|
"0":"rne",
|
||||||
|
"128":"rnm",
|
||||||
|
"96":"ru",
|
||||||
|
"32":"rz",
|
||||||
|
"64":"rd",
|
||||||
|
"224":"dyn"
|
||||||
|
}
|
||||||
|
|
||||||
|
print("creating arch test vectors")
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
def __init__(self, bits, letter, op, filt, op_code):
|
||||||
|
self.bits = bits
|
||||||
|
self.letter = letter
|
||||||
|
self.op = op
|
||||||
|
self.filt = filt
|
||||||
|
self.op_code = op_code
|
||||||
|
|
||||||
|
def create_vectors(my_config):
|
||||||
|
suite_folder_num = my_config.bits
|
||||||
|
if my_config.bits == 64 and my_config.letter == "F": suite_folder_num = 32
|
||||||
|
source_dir1 = "{}/addins/riscv-arch-test/riscv-test-suite/rv{}i_m/{}/src/".format(wally, suite_folder_num, my_config.letter)
|
||||||
|
source_dir2 = "{}/tests/riscof/work/riscv-arch-test/rv{}i_m/{}/src/".format(wally, my_config.bits, my_config.letter)
|
||||||
|
dest_dir = "{}/tests/fp/combined_IF_vectors/IF_vectors/".format(wally)
|
||||||
|
all_vectors1 = os.listdir(source_dir1)
|
||||||
|
|
||||||
|
filt_vectors1 = [v for v in all_vectors1 if my_config.filt in v]
|
||||||
|
# print(filt_vectors1)
|
||||||
|
filt_vectors2 = [v + "/ref/Reference-sail_c_simulator.signature" for v in all_vectors1 if my_config.filt in v]
|
||||||
|
|
||||||
|
# iterate through all vectors
|
||||||
|
for i in range(len(filt_vectors1)):
|
||||||
|
vector1 = filt_vectors1[i]
|
||||||
|
vector2 = filt_vectors2[i]
|
||||||
|
operation = my_config.op_code
|
||||||
|
rounding_mode = "X"
|
||||||
|
flags = "XX"
|
||||||
|
# use name to create our new tv
|
||||||
|
dest_file = open("{}cvw_{}_{}.tv".format(dest_dir, my_config.bits, vector1[:-2]), 'a')
|
||||||
|
# open vectors
|
||||||
|
src_file1 = open(source_dir1 + vector1,'r')
|
||||||
|
src_file2 = open(source_dir2 + vector2,'r')
|
||||||
|
# for each test in the vector
|
||||||
|
reading = True
|
||||||
|
src_file2.readline() #skip first bc junk
|
||||||
|
# print(my_config.bits, my_config.letter)
|
||||||
|
if my_config.letter == "F" and my_config.bits == 64:
|
||||||
|
reading = True
|
||||||
|
# print("trigger 64F")
|
||||||
|
#skip first 2 lines bc junk
|
||||||
|
src_file2.readline()
|
||||||
|
while reading:
|
||||||
|
# get answer and flags from Ref...signature
|
||||||
|
# answers are before deadbeef (first line of 4)
|
||||||
|
# flags are after deadbeef (third line of 4)
|
||||||
|
answer = src_file2.readline().strip()
|
||||||
|
deadbeef = src_file2.readline().strip()
|
||||||
|
# print(answer)
|
||||||
|
if not (answer == "e7d4b281" and deadbeef == "6f5ca309"): # if there is still stuff to read
|
||||||
|
# get flags
|
||||||
|
packed = src_file2.readline().strip()[6:]
|
||||||
|
flags, rounding_mode = unpack_rf(packed)
|
||||||
|
# skip 00000000 buffer
|
||||||
|
src_file2.readline()
|
||||||
|
|
||||||
|
# parse through .S file
|
||||||
|
detected = False
|
||||||
|
done = False
|
||||||
|
op1val = "0"
|
||||||
|
op2val = "0"
|
||||||
|
while not (detected or done):
|
||||||
|
# print("det1")
|
||||||
|
line = src_file1.readline()
|
||||||
|
# print(line)
|
||||||
|
if "op1val" in line:
|
||||||
|
# print("det2")
|
||||||
|
# parse line
|
||||||
|
op1val = line.split("op1val")[1].split("x")[1].split(";")[0]
|
||||||
|
if my_config.op != "fsqrt": # sqrt doesn't have two input vals
|
||||||
|
op2val = line.split("op2val")[1].split("x")[1].strip()
|
||||||
|
if op2val[-1] == ";": op2val = op2val[:-1] # remove ; if it's there
|
||||||
|
else:
|
||||||
|
op2val = 32*"X"
|
||||||
|
# go to next test in vector
|
||||||
|
detected = True
|
||||||
|
elif "RVTEST_CODE_END" in line:
|
||||||
|
done = True
|
||||||
|
# put it all together
|
||||||
|
if not done:
|
||||||
|
translation = "{}_{}_{}_{}_{}_{}".format(operation, ext_bits(op1val), ext_bits(op2val), ext_bits(answer.strip()), flags, rounding_mode)
|
||||||
|
dest_file.write(translation + "\n")
|
||||||
|
else:
|
||||||
|
# print("read false")
|
||||||
|
reading = False
|
||||||
|
elif my_config.letter == "M" and my_config.bits == 64:
|
||||||
|
reading = True
|
||||||
|
#skip first 2 lines bc junk
|
||||||
|
src_file2.readline()
|
||||||
|
while reading:
|
||||||
|
# print("trigger 64M")
|
||||||
|
# get answer from Ref...signature
|
||||||
|
# answers span two lines and are reversed
|
||||||
|
answer2 = src_file2.readline().strip()
|
||||||
|
answer1 = src_file2.readline().strip()
|
||||||
|
answer = answer1 + answer2
|
||||||
|
# print(answer1,answer2)
|
||||||
|
if not (answer2 == "e7d4b281" and answer1 == "6f5ca309"): # if there is still stuff to read
|
||||||
|
# parse through .S file
|
||||||
|
detected = False
|
||||||
|
done = False
|
||||||
|
op1val = "0"
|
||||||
|
op2val = "0"
|
||||||
|
while not (detected or done):
|
||||||
|
# print("det1")
|
||||||
|
line = src_file1.readline()
|
||||||
|
# print(line)
|
||||||
|
if "op1val" in line:
|
||||||
|
# print("det2")
|
||||||
|
# parse line
|
||||||
|
op1val = line.split("op1val")[1].split("x")[1].split(";")[0]
|
||||||
|
if "-" in line.split("op1val")[1].split("x")[0]: # neg sign handling
|
||||||
|
op1val = twos_comp(my_config.bits, op1val)
|
||||||
|
if my_config.op != "fsqrt": # sqrt doesn't have two input vals, unnec here but keeping for later
|
||||||
|
op2val = line.split("op2val")[1].split("x")[1].strip()
|
||||||
|
if op2val[-1] == ";": op2val = op2val[:-1] # remove ; if it's there
|
||||||
|
if "-" in line.split("op2val")[1].split("x")[0]: # neg sign handling
|
||||||
|
op2val = twos_comp(my_config.bits, op2val)
|
||||||
|
# go to next test in vector
|
||||||
|
detected = True
|
||||||
|
elif "RVTEST_CODE_END" in line:
|
||||||
|
done = True
|
||||||
|
# ints don't have flags
|
||||||
|
flags = "XX"
|
||||||
|
# put it all together
|
||||||
|
if not done:
|
||||||
|
translation = "{}_{}_{}_{}_{}_{}".format(operation, ext_bits(op1val), ext_bits(op2val), ext_bits(answer.strip()), flags.strip(), rounding_mode)
|
||||||
|
dest_file.write(translation + "\n")
|
||||||
|
else:
|
||||||
|
# print("read false")
|
||||||
|
reading = False
|
||||||
|
else:
|
||||||
|
while reading:
|
||||||
|
# get answer and flags from Ref...signature
|
||||||
|
answer = src_file2.readline()
|
||||||
|
# print(answer)
|
||||||
|
packed = src_file2.readline()[6:]
|
||||||
|
# print(packed)
|
||||||
|
if len(packed.strip())>0: # if there is still stuff to read
|
||||||
|
# print("packed")
|
||||||
|
# parse through .S file
|
||||||
|
detected = False
|
||||||
|
done = False
|
||||||
|
op1val = "0"
|
||||||
|
op2val = "0"
|
||||||
|
while not (detected or done):
|
||||||
|
# print("det1")
|
||||||
|
line = src_file1.readline()
|
||||||
|
# print(line)
|
||||||
|
if "op1val" in line:
|
||||||
|
# print("det2")
|
||||||
|
# parse line
|
||||||
|
op1val = line.split("op1val")[1].split("x")[1].split(";")[0]
|
||||||
|
if "-" in line.split("op1val")[1].split("x")[0]: # neg sign handling
|
||||||
|
op1val = twos_comp(my_config.bits, op1val)
|
||||||
|
if my_config.op != "fsqrt": # sqrt doesn't have two input vals
|
||||||
|
op2val = line.split("op2val")[1].split("x")[1].strip()
|
||||||
|
if op2val[-1] == ";": op2val = op2val[:-1] # remove ; if it's there
|
||||||
|
if "-" in line.split("op2val")[1].split("x")[0]: # neg sign handling
|
||||||
|
op2val = twos_comp(my_config.bits, op2val)
|
||||||
|
# go to next test in vector
|
||||||
|
detected = True
|
||||||
|
elif "RVTEST_CODE_END" in line:
|
||||||
|
done = True
|
||||||
|
# rounding mode for float
|
||||||
|
if not done and (my_config.op == "fsqrt" or my_config.op == "fdiv"):
|
||||||
|
flags, rounding_mode = unpack_rf(packed)
|
||||||
|
|
||||||
|
# put it all together
|
||||||
|
if not done:
|
||||||
|
translation = "{}_{}_{}_{}_{}_{}".format(operation, ext_bits(op1val), ext_bits(op2val), ext_bits(answer.strip()), flags, rounding_mode)
|
||||||
|
dest_file.write(translation + "\n")
|
||||||
|
else:
|
||||||
|
# print("read false")
|
||||||
|
reading = False
|
||||||
|
print("out")
|
||||||
|
dest_file.close()
|
||||||
|
src_file1.close()
|
||||||
|
src_file2.close()
|
||||||
|
|
||||||
|
config_list = [
|
||||||
|
Config(32, "M", "div", "div_", 0),
|
||||||
|
Config(32, "F", "fdiv", "fdiv", 1),
|
||||||
|
Config(32, "F", "fsqrt", "fsqrt", 2),
|
||||||
|
Config(32, "M", "rem", "rem-", 3),
|
||||||
|
Config(32, "M", "divu", "divu-", 4),
|
||||||
|
Config(32, "M", "remu", "remu-", 5),
|
||||||
|
Config(64, "M", "div", "div-", 0),
|
||||||
|
Config(64, "F", "fdiv", "fdiv", 1),
|
||||||
|
Config(64, "F", "fsqrt", "fsqrt", 2),
|
||||||
|
Config(64, "M", "rem", "rem-", 3),
|
||||||
|
Config(64, "M", "divu", "divu-", 4),
|
||||||
|
Config(64, "M", "remu", "remu-", 5),
|
||||||
|
Config(64, "M", "divw", "divw-", 6),
|
||||||
|
Config(64, "M", "divuw", "divuw-", 7),
|
||||||
|
Config(64, "M", "remw", "remw-", 8),
|
||||||
|
Config(64, "M", "remuw", "remuw-", 9)
|
||||||
|
]
|
||||||
|
|
||||||
|
for c in config_list:
|
||||||
|
create_vectors(c)
|
79
tests/fp/combined_IF_vectors/extract_testfloat_vectors.py
Executable file
79
tests/fp/combined_IF_vectors/extract_testfloat_vectors.py
Executable file
@ -0,0 +1,79 @@
|
|||||||
|
#! /usr/bin/python3
|
||||||
|
# extract sqrt and float div testfloat vectors
|
||||||
|
|
||||||
|
# author: Alessandro Maiuolo
|
||||||
|
# contact: amaiuolo@g.hmc.edu
|
||||||
|
# date created: 3-29-2023
|
||||||
|
|
||||||
|
import os
|
||||||
|
wally = os.popen('echo $WALLY').read().strip()
|
||||||
|
# print(wally)
|
||||||
|
|
||||||
|
def ext_bits(my_string):
|
||||||
|
target_len = 32 # we want 128 bits, div by 4 bc hex notation
|
||||||
|
zeroes_to_add = target_len - len(my_string)
|
||||||
|
return zeroes_to_add*"0" + my_string
|
||||||
|
|
||||||
|
# rounding mode dictionary
|
||||||
|
round_dict = {
|
||||||
|
"rne":"0",
|
||||||
|
"rnm":"4",
|
||||||
|
"ru":"3",
|
||||||
|
"rz":"1",
|
||||||
|
"rd":"2",
|
||||||
|
"dyn":"7"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
print("creating testfloat div test vectors")
|
||||||
|
|
||||||
|
source_dir = "{}/tests/fp/vectors/".format(wally)
|
||||||
|
dest_dir = "{}/tests/fp/combined_IF_vectors/IF_vectors/".format(wally)
|
||||||
|
all_vectors = os.listdir(source_dir)
|
||||||
|
|
||||||
|
div_vectors = [v for v in all_vectors if "div" in v]
|
||||||
|
|
||||||
|
# iterate through all float div vectors
|
||||||
|
for vector in div_vectors:
|
||||||
|
# use name to determine configs
|
||||||
|
config_list = vector.split(".")[0].split("_")
|
||||||
|
operation = "1" #float div
|
||||||
|
rounding_mode = round_dict[str(config_list[2])]
|
||||||
|
# use name to create our new tv
|
||||||
|
dest_file = open(dest_dir + "cvw_" + vector, 'a')
|
||||||
|
# open vector
|
||||||
|
src_file = open(source_dir + vector,'r')
|
||||||
|
# for each test in the vector
|
||||||
|
for i in src_file.readlines():
|
||||||
|
translation = "" # this stores the test that we are currently working on
|
||||||
|
[input_1, input_2, answer, flags] = i.split("_") # separate inputs, answer, and flags
|
||||||
|
# put it all together, strip nec for removing \n on the end of the flags
|
||||||
|
translation = "{}_{}_{}_{}_{}_{}".format(operation, ext_bits(input_1), ext_bits(input_2), ext_bits(answer), flags.strip(), rounding_mode)
|
||||||
|
dest_file.write(translation + "\n")
|
||||||
|
dest_file.close()
|
||||||
|
src_file.close()
|
||||||
|
|
||||||
|
|
||||||
|
print("creating testfloat sqrt test vectors")
|
||||||
|
|
||||||
|
sqrt_vectors = [v for v in all_vectors if "sqrt" in v]
|
||||||
|
|
||||||
|
# iterate through all float div vectors
|
||||||
|
for vector in sqrt_vectors:
|
||||||
|
# use name to determine configs
|
||||||
|
config_list = vector.split(".")[0].split("_")
|
||||||
|
operation = "2" #sqrt
|
||||||
|
rounding_mode = round_dict[str(config_list[2])]
|
||||||
|
# use name to create our new tv
|
||||||
|
dest_file = open(dest_dir + "cvw_" + vector, 'a')
|
||||||
|
# open vector
|
||||||
|
src_file = open(source_dir + vector,'r')
|
||||||
|
# for each test in the vector
|
||||||
|
for i in src_file.readlines():
|
||||||
|
translation = "" # this stores the test that we are currently working on
|
||||||
|
[input_1, answer, flags] = i.split("_") # separate inputs, answer, and flags
|
||||||
|
# put it all together, strip nec for removing \n on the end of the flags
|
||||||
|
translation = "{}_{}_{}_{}_{}_{}".format(operation, ext_bits(input_1), "X"*32, ext_bits(answer), flags.strip(), rounding_mode)
|
||||||
|
dest_file.write(translation + "\n")
|
||||||
|
dest_file.close()
|
||||||
|
src_file.close()
|
@ -3,3 +3,6 @@
|
|||||||
mkdir -p vectors
|
mkdir -p vectors
|
||||||
./create_vectors.sh
|
./create_vectors.sh
|
||||||
./remove_spaces.sh
|
./remove_spaces.sh
|
||||||
|
|
||||||
|
# to create tvs for evaluation of combined IFdivsqrt
|
||||||
|
#./combined_IF_vectors/create_IF_vectors.sh
|
@ -53,7 +53,7 @@
|
|||||||
8000000b # mcause value from m ext interrupt
|
8000000b # mcause value from m ext interrupt
|
||||||
00000000 # mtval for mext interrupt (0x0)
|
00000000 # mtval for mext interrupt (0x0)
|
||||||
00001880 # masked out mstatus.MPP = 11, mstatus.MPIE = 1, and mstatus.MIE = 0
|
00001880 # masked out mstatus.MPP = 11, mstatus.MPIE = 1, and mstatus.MIE = 0
|
||||||
fffff7ff # medeleg after attempted write of all 1's (only some bits are writeable)
|
0000b3ff # medeleg after attempted write of all 1's (only some bits are writeable)
|
||||||
00000222 # mideleg after attempted write of all 1's (only some bits are writeable) # skipping instruction address fault since they're impossible with compressed instrs enabled
|
00000222 # mideleg after attempted write of all 1's (only some bits are writeable) # skipping instruction address fault since they're impossible with compressed instrs enabled
|
||||||
00000001 # mcause from an instruction access fault
|
00000001 # mcause from an instruction access fault
|
||||||
00000000 # mtval of faulting instruction address (0x0)
|
00000000 # mtval of faulting instruction address (0x0)
|
||||||
|
@ -48,7 +48,7 @@
|
|||||||
00000009 # scause from S mode ecall
|
00000009 # scause from S mode ecall
|
||||||
00000000 # stval of ecall (*** defined to be zero for now)
|
00000000 # stval of ecall (*** defined to be zero for now)
|
||||||
00000800 # masked out mstatus.mpp = 1, mstatus.MPIE = 0, and mstatus.MIE = 0
|
00000800 # masked out mstatus.mpp = 1, mstatus.MPIE = 0, and mstatus.MIE = 0
|
||||||
fffff7ff # medeleg after attempted write of all 1's (only some bits are writeable)
|
0000b3ff # medeleg after attempted write of all 1's (only some bits are writeable)
|
||||||
00000222 # mideleg after attempted write of all 1's (only some bits are writeable)
|
00000222 # mideleg after attempted write of all 1's (only some bits are writeable)
|
||||||
0000000b # scause from M mode ecall
|
0000000b # scause from M mode ecall
|
||||||
00000000 # stval of ecall (*** defined to be zero for now)
|
00000000 # stval of ecall (*** defined to be zero for now)
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
00000008 # scause from U mode ecall
|
00000008 # scause from U mode ecall
|
||||||
00000000 # stval of ecall (*** defined to be zero for now)
|
00000000 # stval of ecall (*** defined to be zero for now)
|
||||||
00000000 # masked out mstatus.mpp = 0, mstatus.MPIE = 0, and mstatus.MIE = 0
|
00000000 # masked out mstatus.mpp = 0, mstatus.MPIE = 0, and mstatus.MIE = 0
|
||||||
fffff7ff # medeleg after attempted write of all 1's (only some bits are writeable)
|
0000b3ff # medeleg after attempted write of all 1's (only some bits are writeable)
|
||||||
00000222 # mideleg after attempted write of all 1's (only some bits are writeable)
|
00000222 # mideleg after attempted write of all 1's (only some bits are writeable)
|
||||||
0000000b # scause from M mode ecall
|
0000000b # scause from M mode ecall
|
||||||
00000000 # stval of ecall (*** defined to be zero for now)
|
00000000 # stval of ecall (*** defined to be zero for now)
|
||||||
|
@ -108,8 +108,8 @@
|
|||||||
00000000
|
00000000
|
||||||
00001880 # masked out mstatus.MPP = 11, mstatus.MPIE = 1, and mstatus.MIE = 0
|
00001880 # masked out mstatus.MPP = 11, mstatus.MPIE = 1, and mstatus.MIE = 0
|
||||||
00000000
|
00000000
|
||||||
fffff7ff # medeleg after attempted write of all 1's (only some bits are writeable)
|
0000b3ff # medeleg after attempted write of all 1's (only some bits are writeable)
|
||||||
ffffffff
|
00000000
|
||||||
00000222 # mideleg after attempted write of all 1's (only some bits are writeable)
|
00000222 # mideleg after attempted write of all 1's (only some bits are writeable)
|
||||||
00000000 # skipping instruction address fault since they're impossible with compressed instrs enabled
|
00000000 # skipping instruction address fault since they're impossible with compressed instrs enabled
|
||||||
00000001 # mcause from an instruction access fault
|
00000001 # mcause from an instruction access fault
|
||||||
|
@ -98,8 +98,8 @@
|
|||||||
00000000
|
00000000
|
||||||
00000800 # masked out mstatus.mpp = 1, mstatus.MPIE = 0, and mstatus.MIE = 0
|
00000800 # masked out mstatus.mpp = 1, mstatus.MPIE = 0, and mstatus.MIE = 0
|
||||||
00000000
|
00000000
|
||||||
fffff7ff # medeleg after attempted write of all 1's (only some bits are writeable)
|
0000b3ff # medeleg after attempted write of all 1's (only some bits are writeable)
|
||||||
ffffffff
|
00000000
|
||||||
00000222 # mideleg after attempted write of all 1's (only some bits are writeable)
|
00000222 # mideleg after attempted write of all 1's (only some bits are writeable)
|
||||||
00000000
|
00000000
|
||||||
0000000b # scause from M mode ecall
|
0000000b # scause from M mode ecall
|
||||||
|
@ -92,8 +92,8 @@
|
|||||||
00000000
|
00000000
|
||||||
00000000 # masked out mstatus.mpp = 0, mstatus.MPIE = 0, and mstatus.MIE = 0
|
00000000 # masked out mstatus.mpp = 0, mstatus.MPIE = 0, and mstatus.MIE = 0
|
||||||
00000000
|
00000000
|
||||||
fffff7ff # medeleg after attempted write of all 1's (only some bits are writeable)
|
0000b3ff # medeleg after attempted write of all 1's (only some bits are writeable)
|
||||||
ffffffff
|
00000000
|
||||||
00000222 # mideleg after attempted write of all 1's (only some bits are writeable)
|
00000222 # mideleg after attempted write of all 1's (only some bits are writeable)
|
||||||
00000000
|
00000000
|
||||||
0000000b # scause from M mode ecall
|
0000000b # scause from M mode ecall
|
||||||
|
Loading…
Reference in New Issue
Block a user