Merge branch 'main' of https://github.com/openhwgroup/cvw into main

This commit is contained in:
Ross Thompson 2023-04-09 12:19:44 -05:00
commit 81074a822a
15 changed files with 354 additions and 66 deletions

View File

@ -54,47 +54,67 @@ module fdivsqrtpreproc (
logic [`DIVb:0] PreSqrtX; logic [`DIVb:0] PreSqrtX;
logic [`DIVb+3:0] DivX, DivXShifted, SqrtX, PreShiftX; // Variations of dividend, to be muxed logic [`DIVb+3:0] DivX, DivXShifted, SqrtX, PreShiftX; // Variations of dividend, to be muxed
logic [`NE+1:0] QeE; // Quotient Exponent (FP only) logic [`NE+1:0] QeE; // Quotient Exponent (FP only)
logic [`DIVb-1:0] IFNormLenX, IFNormLenD; // Correctly-sized inputs for iterator logic [`DIVb-1:0] IFX, IFD; // Correctly-sized inputs for iterator, selected from int or fp input
logic [`DIVBLEN:0] mE, ell; // Leading zeros of inputs logic [`DIVBLEN:0] mE, ell; // Leading zeros of inputs
logic NumerZeroE; // Numerator is zero (X or A) logic NumerZeroE; // Numerator is zero (X or A)
logic AZeroE, BZeroE; // A or B is Zero for integer division logic AZeroE, BZeroE; // A or B is Zero for integer division
logic signedDiv; // signed division
logic NegQuotE; // Integer quotient is negative
logic AsE, BsE; // Signs of integer inputs
logic [`XLEN-1:0] AE; // input A after W64 adjustment
if (`IDIV_ON_FPU) begin:intpreproc // Int Supported if (`IDIV_ON_FPU) begin:intpreproc // Int Supported
logic signedDiv, NegQuotE; logic [`XLEN-1:0] BE, PosA, PosB;
logic AsBit, BsBit, AsE, BsE, ALTBE;
logic [`XLEN-1:0] AE, BE, PosA, PosB;
logic [`DIVBLEN:0] ZeroDiff, p;
// Extract inputs, signs, zero, depending on W64 mode if applicable // Extract inputs, signs, zero, depending on W64 mode if applicable
assign signedDiv = ~Funct3E[0]; assign signedDiv = ~Funct3E[0];
assign NegQuotE = AsE ^ BsE; // Quotient is negative
// Source handling // Source handling
if (`XLEN==64) begin // 64-bit, supports W64 if (`XLEN==64) begin // 64-bit, supports W64
mux2 #(1) azeromux(~(|ForwardedSrcAE), ~(|ForwardedSrcAE[31:0]), W64E, AZeroE); mux2 #(64) amux(ForwardedSrcAE, {{32{ForwardedSrcAE[31] & signedDiv}}, ForwardedSrcAE[31:0]}, W64E, AE);
mux2 #(1) bzeromux(~(|ForwardedSrcBE), ~(|ForwardedSrcBE[31:0]), W64E, BZeroE); mux2 #(64) bmux(ForwardedSrcBE, {{32{ForwardedSrcBE[31] & signedDiv}}, ForwardedSrcBE[31:0]}, W64E, BE);
mux2 #(1) abitmux(ForwardedSrcAE[63], ForwardedSrcAE[31], W64E, AsBit);
mux2 #(1) bbitmux(ForwardedSrcBE[63], ForwardedSrcBE[31], W64E, BsBit);
mux2 #(64) amux(ForwardedSrcAE, {{(`XLEN-32){AsE}}, ForwardedSrcAE[31:0]}, W64E, AE);
mux2 #(64) bmux(ForwardedSrcBE, {{(`XLEN-32){BsE}}, ForwardedSrcBE[31:0]}, W64E, BE);
assign AsE = signedDiv & AsBit;
assign BsE = signedDiv & BsBit;
end else begin // 32 bits only end else begin // 32 bits only
assign AsE = signedDiv & ForwardedSrcAE[31];
assign BsE = signedDiv & ForwardedSrcBE[31];
assign AE = ForwardedSrcAE; assign AE = ForwardedSrcAE;
assign BE = ForwardedSrcBE; assign BE = ForwardedSrcBE;
assign AZeroE = ~(|ForwardedSrcAE); end
assign BZeroE = ~(|ForwardedSrcBE); assign AZeroE = ~(|AE);
end assign BZeroE = ~(|BE);
assign AsE = AE[`XLEN-1] & signedDiv;
assign BsE = BE[`XLEN-1] & signedDiv;
assign NegQuotE = AsE ^ BsE; // Integer Quotient is negative
// Force integer inputs to be postiive // Force integer inputs to be postiive
mux2 #(`XLEN) posamux(AE, -AE, AsE, PosA); mux2 #(`XLEN) posamux(AE, -AE, AsE, PosA);
mux2 #(`XLEN) posbmux(BE, -BE, BsE, PosB); mux2 #(`XLEN) posbmux(BE, -BE, BsE, PosB);
// Select integer or floating point inputs // Select integer or floating point inputs
mux2 #(`DIVb) ifxmux({Xm, {(`DIVb-`NF-1){1'b0}}}, {PosA, {(`DIVb-`XLEN){1'b0}}}, IntDivE, IFNormLenX); mux2 #(`DIVb) ifxmux({Xm, {(`DIVb-`NF-1){1'b0}}}, {PosA, {(`DIVb-`XLEN){1'b0}}}, IntDivE, IFX);
mux2 #(`DIVb) ifdmux({Ym, {(`DIVb-`NF-1){1'b0}}}, {PosB, {(`DIVb-`XLEN){1'b0}}}, IntDivE, IFNormLenD); mux2 #(`DIVb) ifdmux({Ym, {(`DIVb-`NF-1){1'b0}}}, {PosB, {(`DIVb-`XLEN){1'b0}}}, IntDivE, IFD);
end else begin // Int not supported
assign IFX = {Xm, {(`DIVb-`NF-1){1'b0}}};
assign IFD = {Ym, {(`DIVb-`NF-1){1'b0}}};
end
// count leading zeros for Subnorm FP and to normalize integer inputs
lzc #(`DIVb) lzcX (IFX, ell);
lzc #(`DIVb) lzcY (IFD, mE);
// Normalization shift
assign XPreproc = IFX << (ell + {{`DIVBLEN{1'b0}}, 1'b1}); // *** try to remove this +1
assign DPreproc = IFD << (mE + {{`DIVBLEN{1'b0}}, 1'b1});
// append leading 1 (for normal inputs)
// shift square root to be in range [1/4, 1)
// Normalized numbers are shifted right by 1 if the exponent is odd
// Denormalized numbers have Xe = 0 and an unbiased exponent of 1-BIAS. They are shifted right if the number of leading zeros is odd.
mux2 #(`DIVb+1) sqrtxmux({~XZeroE, XPreproc}, {1'b0, ~XZeroE, XPreproc[`DIVb-1:1]}, (Xe[0] ^ ell[0]), PreSqrtX);
assign DivX = {3'b000, ~NumerZeroE, XPreproc};
if (`IDIV_ON_FPU) begin:intrightshift // Int Supported
logic [`DIVBLEN:0] ZeroDiff, p;
logic ALTBE;
// calculate number of fractional bits p // calculate number of fractional bits p
assign ZeroDiff = mE - ell; // Difference in number of leading zeros assign ZeroDiff = mE - ell; // Difference in number of leading zeros
@ -133,34 +153,16 @@ module fdivsqrtpreproc (
flopen #(1) negquotreg(clk, IFDivStartE, NegQuotE, NegQuotM); flopen #(1) negquotreg(clk, IFDivStartE, NegQuotE, NegQuotM);
flopen #(1) bzeroreg(clk, IFDivStartE, BZeroE, BZeroM); flopen #(1) bzeroreg(clk, IFDivStartE, BZeroE, BZeroM);
flopen #(1) asignreg(clk, IFDivStartE, AsE, AsM); flopen #(1) asignreg(clk, IFDivStartE, AsE, AsM);
flopen #(`DIVBLEN+1) nreg(clk, IFDivStartE, nE, nM); flopen #(`DIVBLEN+1) nreg(clk, IFDivStartE, nE, nM);
flopen #(`DIVBLEN+1) mreg(clk, IFDivStartE, mE, mM); flopen #(`DIVBLEN+1) mreg(clk, IFDivStartE, mE, mM);
flopen #(`XLEN) srcareg(clk, IFDivStartE, AE, AM); flopen #(`XLEN) srcareg(clk, IFDivStartE, AE, AM);
if (`XLEN==64) if (`XLEN==64)
flopen #(1) w64reg(clk, IFDivStartE, W64E, W64M); flopen #(1) w64reg(clk, IFDivStartE, W64E, W64M);
end else begin
end else begin // Int not supported
assign IFNormLenX = {Xm, {(`DIVb-`NF-1){1'b0}}};
assign IFNormLenD = {Ym, {(`DIVb-`NF-1){1'b0}}};
assign NumerZeroE = XZeroE; assign NumerZeroE = XZeroE;
assign X = PreShiftX; assign X = PreShiftX;
end end
// count leading zeros for Subnorm FP and to normalize integer inputs
lzc #(`DIVb) lzcX (IFNormLenX, ell);
lzc #(`DIVb) lzcY (IFNormLenD, mE);
// Normalization shift
assign XPreproc = IFNormLenX << (ell + {{`DIVBLEN{1'b0}}, 1'b1}); // *** try to remove this +1
assign DPreproc = IFNormLenD << (mE + {{`DIVBLEN{1'b0}}, 1'b1});
// append leading 1 (for normal inputs)
// shift square root to be in range [1/4, 1)
// Normalized numbers are shifted right by 1 if the exponent is odd
// Denormalized numbers have Xe = 0 and an unbiased exponent of 1-BIAS. They are shifted right if the number of leading zeros is odd.
mux2 #(`DIVb+1) sqrtxmux({~XZeroE, XPreproc}, {1'b0, ~XZeroE, XPreproc[`DIVb-1:1]}, (Xe[0] ^ ell[0]), PreSqrtX);
assign DivX = {3'b000, ~NumerZeroE, XPreproc};
// Sqrt is initialized on step one as R(X-1), so depends on Radix // Sqrt is initialized on step one as R(X-1), so depends on Radix
if (`RADIX == 2) assign SqrtX = {3'b111, PreSqrtX}; if (`RADIX == 2) assign SqrtX = {3'b111, PreSqrtX};
else assign SqrtX = {2'b11, PreSqrtX, 1'b0}; else assign SqrtX = {2'b11, PreSqrtX, 1'b0};

View File

@ -122,11 +122,14 @@ module ram2p1r1wbe #(parameter DEPTH=1024, WIDTH=68) (
if(ce1) rd1 <= #1 mem[ra1]; */ if(ce1) rd1 <= #1 mem[ra1]; */
// Write divided into part for bytes and part for extra msbs // Write divided into part for bytes and part for extra msbs
// coverage off
// when byte write enables are tied high, the last IF is always taken
if(WIDTH >= 8) if(WIDTH >= 8)
always @(posedge clk) always @(posedge clk)
if (ce2 & we2) if (ce2 & we2)
for(i = 0; i < WIDTH/8; i++) for(i = 0; i < WIDTH/8; i++)
if(bwe2[i]) mem[wa2][i*8 +: 8] <= #1 wd2[i*8 +: 8]; if(bwe2[i]) mem[wa2][i*8 +: 8] <= #1 wd2[i*8 +: 8];
// coverage on
if (WIDTH%8 != 0) // handle msbs if width not a multiple of 8 if (WIDTH%8 != 0) // handle msbs if width not a multiple of 8
always @(posedge clk) always @(posedge clk)

View File

@ -71,6 +71,7 @@ module hazard (
// Similarly, CSR writes and fences flush all subsequent instructions and refetch them in light of the new operating modes and cache/TLB contents // Similarly, CSR writes and fences flush all subsequent instructions and refetch them in light of the new operating modes and cache/TLB contents
// Branch misprediction is found in the Execute stage and must flush the next two instructions. // Branch misprediction is found in the Execute stage and must flush the next two instructions.
// However, an active division operation resides in the Execute stage, and when the BP incorrectly mispredicts the divide as a taken branch, the divde must still complete // However, an active division operation resides in the Execute stage, and when the BP incorrectly mispredicts the divide as a taken branch, the divde must still complete
// When a WFI is interrupted and causes a trap, it flushes the rest of the pipeline but not the W stage, because the WFI needs to commit
assign FlushDCause = TrapM | RetM | CSRWriteFenceM | BPWrongE; assign FlushDCause = TrapM | RetM | CSRWriteFenceM | BPWrongE;
assign FlushECause = TrapM | RetM | CSRWriteFenceM |(BPWrongE & ~(DivBusyE | FDivBusyE)); assign FlushECause = TrapM | RetM | CSRWriteFenceM |(BPWrongE & ~(DivBusyE | FDivBusyE));
assign FlushMCause = TrapM | RetM | CSRWriteFenceM; assign FlushMCause = TrapM | RetM | CSRWriteFenceM;

View File

@ -62,7 +62,7 @@ module RASPredictor #(parameter int StackSize = 16 )(
assign PushE = CallE & ~StallM & ~FlushM; assign PushE = CallE & ~StallM & ~FlushM;
assign WrongPredReturnD = (BPReturnWrongD) & ~StallE & ~FlushE; assign WrongPredReturnD = (BPReturnWrongD) & ~StallE & ~FlushE;
assign FlushedReturnDE = (~StallE & FlushE & ReturnD) | (~StallM & FlushM & ReturnE); // flushed return assign FlushedReturnDE = (~StallE & FlushE & ReturnD) | (FlushM & ReturnE); // flushed return
assign RepairD = WrongPredReturnD | FlushedReturnDE ; assign RepairD = WrongPredReturnD | FlushedReturnDE ;

View File

@ -126,7 +126,7 @@ module decompress (
InstrD = {7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or InstrD = {7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or
else // if (instr16[6:5] == 2'b11) else // if (instr16[6:5] == 2'b11)
InstrD = {7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and InstrD = {7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and
else if (instr16[12:10] == 3'b111 & `XLEN > 32) else if (`XLEN > 32) //if (instr16[12:10] == 3'b111) full truth table no need to check [12:10]
if (instr16[6:5] == 2'b00) if (instr16[6:5] == 2'b00)
InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw InstrD = {7'b0100000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.subw
else if (instr16[6:5] == 2'b01) else if (instr16[6:5] == 2'b01)

View File

@ -130,7 +130,7 @@ module ifu (
logic CacheableF; // PMA indicates instruction address is cacheable logic CacheableF; // PMA indicates instruction address is cacheable
logic SelSpillNextF; // In a spill, stall pipeline and gate local stallF logic SelSpillNextF; // In a spill, stall pipeline and gate local stallF
logic BusStall; // Bus interface busy with multicycle operation logic BusStall; // Bus interface busy with multicycle operation
logic IFUCacheBusStallD; // EIther I$ or bus busy with multicycle operation logic IFUCacheBusStallF; // EIther I$ or bus busy with multicycle operation
logic GatedStallD; // StallD gated by selected next spill logic GatedStallD; // StallD gated by selected next spill
// branch predictor signal // branch predictor signal
logic [`XLEN-1:0] PC1NextF; // Branch predictor next PCF logic [`XLEN-1:0] PC1NextF; // Branch predictor next PCF
@ -147,7 +147,7 @@ module ifu (
if(`C_SUPPORTED) begin : Spill if(`C_SUPPORTED) begin : Spill
spill #(`ICACHE_SUPPORTED) spill(.clk, .reset, .StallD, .FlushD, .PCF, .PCPlus4F, .PCNextF, .InstrRawF, spill #(`ICACHE_SUPPORTED) spill(.clk, .reset, .StallD, .FlushD, .PCF, .PCPlus4F, .PCNextF, .InstrRawF,
.InstrUpdateDAF, .IFUCacheBusStallD, .ITLBMissF, .PCSpillNextF, .PCSpillF, .SelSpillNextF, .PostSpillInstrRawF, .CompressedF); .InstrUpdateDAF, .IFUCacheBusStallF, .ITLBMissF, .PCSpillNextF, .PCSpillF, .SelSpillNextF, .PostSpillInstrRawF, .CompressedF);
end else begin : NoSpill end else begin : NoSpill
assign PCSpillNextF = PCNextF; assign PCSpillNextF = PCNextF;
assign PCSpillF = PCF; assign PCSpillF = PCF;
@ -288,8 +288,8 @@ module ifu (
assign InstrRawF = IROMInstrF; assign InstrRawF = IROMInstrF;
end end
assign IFUCacheBusStallD = ICacheStallF | BusStall; assign IFUCacheBusStallF = ICacheStallF | BusStall;
assign IFUStallF = IFUCacheBusStallD | SelSpillNextF; assign IFUStallF = IFUCacheBusStallF | SelSpillNextF;
assign GatedStallD = StallD & ~SelSpillNextF; assign GatedStallD = StallD & ~SelSpillNextF;
flopenl #(32) AlignedInstrRawDFlop(clk, reset | FlushD, ~StallD, PostSpillInstrRawF, nop, InstrRawD); flopenl #(32) AlignedInstrRawDFlop(clk, reset | FlushD, ~StallD, PostSpillInstrRawF, nop, InstrRawD);

View File

@ -40,7 +40,7 @@ module spill #(
input logic [`XLEN-1:2] PCPlus4F, // PCF + 4 input logic [`XLEN-1:2] PCPlus4F, // PCF + 4
input logic [`XLEN-1:0] PCNextF, // The next PCF input logic [`XLEN-1:0] PCNextF, // The next PCF
input logic [31:0] InstrRawF, // Instruction from the IROM, I$, or bus. Used to check if the instruction if compressed input logic [31:0] InstrRawF, // Instruction from the IROM, I$, or bus. Used to check if the instruction if compressed
input logic IFUCacheBusStallD, // I$ or bus are stalled. Transition to second fetch of spill after the first is fetched input logic IFUCacheBusStallF, // I$ or bus are stalled. Transition to second fetch of spill after the first is fetched
input logic ITLBMissF, // ITLB miss, ignore memory request input logic ITLBMissF, // ITLB miss, ignore memory request
input logic InstrUpdateDAF, // Ignore memory request if the hptw support write and a DA page fault occurs (hptw is still active) input logic InstrUpdateDAF, // Ignore memory request if the hptw support write and a DA page fault occurs (hptw is still active)
output logic [`XLEN-1:0] PCSpillNextF, // The next PCF for one of the two memory addresses of the spill output logic [`XLEN-1:0] PCSpillNextF, // The next PCF for one of the two memory addresses of the spill
@ -78,7 +78,7 @@ module spill #(
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////
assign SpillF = &PCF[$clog2(SPILLTHRESHOLD)+1:1]; assign SpillF = &PCF[$clog2(SPILLTHRESHOLD)+1:1];
assign TakeSpillF = SpillF & ~IFUCacheBusStallD & ~(ITLBMissF | (`SVADU_SUPPORTED & InstrUpdateDAF)); assign TakeSpillF = SpillF & ~IFUCacheBusStallF & ~(ITLBMissF | (`SVADU_SUPPORTED & InstrUpdateDAF));
always_ff @(posedge clk) always_ff @(posedge clk)
if (reset | FlushD) CurrState <= #1 STATE_READY; if (reset | FlushD) CurrState <= #1 STATE_READY;
@ -88,14 +88,14 @@ module spill #(
case (CurrState) case (CurrState)
STATE_READY: if (TakeSpillF) NextState = STATE_SPILL; STATE_READY: if (TakeSpillF) NextState = STATE_SPILL;
else NextState = STATE_READY; else NextState = STATE_READY;
STATE_SPILL: if(IFUCacheBusStallD | StallD) NextState = STATE_SPILL; STATE_SPILL: if(StallD) NextState = STATE_SPILL;
else NextState = STATE_READY; else NextState = STATE_READY;
default: NextState = STATE_READY; default: NextState = STATE_READY;
endcase endcase
end end
assign SelSpillF = (CurrState == STATE_SPILL); assign SelSpillF = (CurrState == STATE_SPILL);
assign SelSpillNextF = (CurrState == STATE_READY & TakeSpillF) | (CurrState == STATE_SPILL & IFUCacheBusStallD); assign SelSpillNextF = (CurrState == STATE_READY & TakeSpillF) | (CurrState == STATE_SPILL & IFUCacheBusStallF);
assign SpillSaveF = (CurrState == STATE_READY) & TakeSpillF & ~FlushD; assign SpillSaveF = (CurrState == STATE_READY) & TakeSpillF & ~FlushD;
//////////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////

View File

@ -33,7 +33,9 @@
`include "wally-config.vh" `include "wally-config.vh"
module csrc #(parameter module csrc #(parameter
MHPMCOUNTERBASE = 12'hB00, MHPMCOUNTERBASE = 12'hB00,
MTIME = 12'hB01, // this is a memory-mapped register; no such CSR exists, and access should fault
MHPMCOUNTERHBASE = 12'hB80, MHPMCOUNTERHBASE = 12'hB80,
MTIMEH = 12'hB81, // this is a memory-mapped register; no such CSR exists, and access should fault
MHPMEVENTBASE = 12'h320, MHPMEVENTBASE = 12'h320,
HPMCOUNTERBASE = 12'hC00, HPMCOUNTERBASE = 12'hC00,
HPMCOUNTERHBASE = 12'hC80, HPMCOUNTERHBASE = 12'hC80,
@ -152,8 +154,10 @@ module csrc #(parameter
/* verilator lint_off WIDTH */ /* verilator lint_off WIDTH */
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT; // TIME register is a shadow of the memory-mapped MTIME from the CLINT if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT; // TIME register is a shadow of the memory-mapped MTIME from the CLINT
/* verilator lint_on WIDTH */ /* verilator lint_on WIDTH */
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS & CSRAdrM != MTIME)
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS)
CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else begin else begin
CSRCReadValM = 0; CSRCReadValM = 0;
IllegalCSRCAccessM = 1; // requested CSR doesn't exist IllegalCSRCAccessM = 1; // requested CSR doesn't exist
@ -164,10 +168,14 @@ module csrc #(parameter
if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT[31:0];// TIME register is a shadow of the memory-mapped MTIME from the CLINT if (CSRAdrM == TIME) CSRCReadValM = MTIME_CLINT[31:0];// TIME register is a shadow of the memory-mapped MTIME from the CLINT
else if (CSRAdrM == TIMEH) CSRCReadValM = MTIME_CLINT[63:32]; else if (CSRAdrM == TIMEH) CSRCReadValM = MTIME_CLINT[63:32];
/* verilator lint_on WIDTH */ /* verilator lint_on WIDTH */
else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; else if (CSRAdrM >= MHPMCOUNTERBASE & CSRAdrM < MHPMCOUNTERBASE+`COUNTERS & CSRAdrM != MTIME)
else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS) CSRCReadValM = HPMCOUNTER_REGW[CounterNumM]; CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= MHPMCOUNTERHBASE & CSRAdrM < MHPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM]; else if (CSRAdrM >= HPMCOUNTERBASE & CSRAdrM < HPMCOUNTERBASE+`COUNTERS)
else if (CSRAdrM >= HPMCOUNTERHBASE & CSRAdrM < HPMCOUNTERHBASE+`COUNTERS) CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM]; CSRCReadValM = HPMCOUNTER_REGW[CounterNumM];
else if (CSRAdrM >= MHPMCOUNTERHBASE & CSRAdrM < MHPMCOUNTERHBASE+`COUNTERS & CSRAdrM != MTIMEH)
CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
else if (CSRAdrM >= HPMCOUNTERHBASE & CSRAdrM < HPMCOUNTERHBASE+`COUNTERS)
CSRCReadValM = HPMCOUNTERH_REGW[CounterNumM];
else begin else begin
CSRCReadValM = 0; CSRCReadValM = 0;
IllegalCSRCAccessM = 1; // requested CSR doesn't exist IllegalCSRCAccessM = 1; // requested CSR doesn't exist

View File

@ -49,7 +49,9 @@ string tvpaths[] = '{
"csrwrites", "csrwrites",
"priv", "priv",
"ifu", "ifu",
"fpu" "fpu",
"lsu",
"vm64check"
}; };
string coremark[] = '{ string coremark[] = '{
@ -1052,6 +1054,28 @@ string imperas32f[] = '{
string arch64f[] = '{ string arch64f[] = '{
`RISCVARCHTEST, `RISCVARCHTEST,
"rv64i_m/F/src/fdiv_b1-01.S",
"rv64i_m/F/src/fdiv_b20-01.S",
"rv64i_m/F/src/fdiv_b2-01.S",
"rv64i_m/F/src/fdiv_b21-01.S",
"rv64i_m/F/src/fdiv_b3-01.S",
"rv64i_m/F/src/fdiv_b4-01.S",
"rv64i_m/F/src/fdiv_b5-01.S",
"rv64i_m/F/src/fdiv_b6-01.S",
"rv64i_m/F/src/fdiv_b7-01.S",
"rv64i_m/F/src/fdiv_b8-01.S",
"rv64i_m/F/src/fdiv_b9-01.S",
"rv64i_m/F/src/fsqrt_b1-01.S",
"rv64i_m/F/src/fsqrt_b20-01.S",
"rv64i_m/F/src/fsqrt_b2-01.S",
"rv64i_m/F/src/fsqrt_b3-01.S",
"rv64i_m/F/src/fsqrt_b4-01.S",
"rv64i_m/F/src/fsqrt_b5-01.S",
"rv64i_m/F/src/fsqrt_b7-01.S",
"rv64i_m/F/src/fsqrt_b8-01.S",
"rv64i_m/F/src/fsqrt_b9-01.S",
"rv64i_m/F/src/fadd_b10-01.S", "rv64i_m/F/src/fadd_b10-01.S",
"rv64i_m/F/src/fadd_b1-01.S", "rv64i_m/F/src/fadd_b1-01.S",
"rv64i_m/F/src/fadd_b11-01.S", "rv64i_m/F/src/fadd_b11-01.S",
@ -1203,6 +1227,28 @@ string imperas32f[] = '{
string arch64d[] = '{ string arch64d[] = '{
`RISCVARCHTEST, `RISCVARCHTEST,
// for speed
"rv64i_m/D/src/fdiv.d_b1-01.S",
"rv64i_m/D/src/fdiv.d_b20-01.S",
"rv64i_m/D/src/fdiv.d_b2-01.S",
"rv64i_m/D/src/fdiv.d_b21-01.S",
"rv64i_m/D/src/fdiv.d_b3-01.S",
"rv64i_m/D/src/fdiv.d_b4-01.S",
"rv64i_m/D/src/fdiv.d_b5-01.S",
"rv64i_m/D/src/fdiv.d_b6-01.S",
"rv64i_m/D/src/fdiv.d_b7-01.S",
"rv64i_m/D/src/fdiv.d_b8-01.S",
"rv64i_m/D/src/fdiv.d_b9-01.S",
"rv64i_m/D/src/fsqrt.d_b1-01.S",
"rv64i_m/D/src/fsqrt.d_b20-01.S",
"rv64i_m/D/src/fsqrt.d_b2-01.S",
"rv64i_m/D/src/fsqrt.d_b3-01.S",
"rv64i_m/D/src/fsqrt.d_b4-01.S",
"rv64i_m/D/src/fsqrt.d_b5-01.S",
"rv64i_m/D/src/fsqrt.d_b7-01.S",
"rv64i_m/D/src/fsqrt.d_b8-01.S",
"rv64i_m/D/src/fsqrt.d_b9-01.S",
"rv64i_m/D/src/fadd.d_b10-01.S", "rv64i_m/D/src/fadd.d_b10-01.S",
"rv64i_m/D/src/fadd.d_b1-01.S", "rv64i_m/D/src/fadd.d_b1-01.S",
"rv64i_m/D/src/fadd.d_b11-01.S", "rv64i_m/D/src/fadd.d_b11-01.S",

View File

@ -36,6 +36,7 @@ rvtest_entry_point:
csrw mtvec, t0 # Initialize MTVEC to trap_handler csrw mtvec, t0 # Initialize MTVEC to trap_handler
csrw mideleg, zero # Don't delegate interrupts csrw mideleg, zero # Don't delegate interrupts
csrw medeleg, zero # Don't delegate exceptions csrw medeleg, zero # Don't delegate exceptions
li t0, 0x80
csrw mie, t0 # Enable machine timer interrupt csrw mie, t0 # Enable machine timer interrupt
la t0, topoftrapstack la t0, topoftrapstack
csrw mscratch, t0 # MSCRATCH holds trap stack pointer csrw mscratch, t0 # MSCRATCH holds trap stack pointer
@ -65,9 +66,8 @@ interrupt: # must be a timer interrupt
j trap_return # clean up and return j trap_return # clean up and return
exception: exception:
csrr t1, mepc # add 4 to MEPC to determine return Address li t0, 2
addi t1, t1, 4 csrr t1, mcause
csrw mepc, t1
li t1, 8 # is it an ecall trap? li t1, 8 # is it an ecall trap?
andi t0, t0, 0xFC # if CAUSE = 8, 9, or 11 andi t0, t0, 0xFC # if CAUSE = 8, 9, or 11
bne t0, t1, trap_return # ignore other exceptions bne t0, t1, trap_return # ignore other exceptions
@ -86,6 +86,20 @@ changeprivilege:
csrs mstatus, a0 # set mstatus.MPP with desired privilege csrs mstatus, a0 # set mstatus.MPP with desired privilege
trap_return: # return from trap handler trap_return: # return from trap handler
csrr t0, mepc # get address of instruction that caused exception
lh t0, 0(t0) # get instruction that caused exception
li t1, 3
and t0, t0, t1 # mask off upper bits
beq t0, t1, instr32 # if lower 2 bits are 11, instruction is uncompresssed
li t0, 2 # increment PC by 2 for compressed instruction
j updateepc
instr32:
li t0, 4
updateepc:
csrr t1, mepc # add 2 or 4 (from t0) to MEPC to determine return Address
add t1, t1, t0
csrw mepc, t1
ld t1, -8(tp) # restore t1 and t0 ld t1, -8(tp) # restore t1 and t0
ld t0, 0(tp) ld t0, 0(tp)
csrrw tp, mscratch, tp # restore tp csrrw tp, mscratch, tp # restore tp

View File

@ -27,9 +27,11 @@
#include "WALLY-init-lib.h" #include "WALLY-init-lib.h"
main: main:
li t0, -5
csrw stimecmp, t0 # initialize so ImperasDV agrees
csrrw t0, stimecmp, t0 csrrw t0, stimecmp, t0
csrrw t0, satp, t0 csrrw t0, satp, zero
csrrw t0, stvec, t0 csrrw t0, stvec, zero
csrrw t0, sscratch, t0 csrrw t0, sscratch, zero
j done j done

View File

@ -42,6 +42,7 @@ main:
clz t1, t0 clz t1, t0
# Test forwarding from store conditional # Test forwarding from store conditional
mv a0, sp
lr.w t0, 0(a0) lr.w t0, 0(a0)
sc.w t0, a1, 0(a0) sc.w t0, a1, 0(a0)
addi t0, t0, 1 addi t0, t0, 1

View File

@ -43,4 +43,7 @@ main:
//.hword 0x9C01 //# Illegal compressed instruction with op = 01, instr[15:10] = 100111, and 0's everywhere else //.hword 0x9C01 //# Illegal compressed instruction with op = 01, instr[15:10] = 100111, and 0's everywhere else
j done j done

View File

@ -33,7 +33,8 @@ main:
ecall ecall
# Test read to stimecmp fails when MCOUNTEREN_TM is not set # Test read to stimecmp fails when MCOUNTEREN_TM is not set
addi t0, zero, 0 li t1, -3
csrw stimecmp, t1
csrr t0, stimecmp csrr t0, stimecmp
@ -56,6 +57,9 @@ main:
ecall # machine mode again ecall # machine mode again
# switch to supervisor mode
li a0, 1
ecall
# Test write to STVAL, SCAUSE, SEPC, and STIMECMP CSRs # Test write to STVAL, SCAUSE, SEPC, and STIMECMP CSRs
li t0, 0 li t0, 0
@ -70,6 +74,10 @@ main:
# Switch to machine mode # Switch to machine mode
li a0, 3 li a0, 3
ecall ecall
# Write to MCOUNTINHIBIT CSR
csrw mcountinhibit, t0
# Testing the HPMCOUNTERM performance counter: writing # Testing the HPMCOUNTERM performance counter: writing
# Base address is 2816 (MHPMCOUNTERBASE) # Base address is 2816 (MHPMCOUNTERBASE)
# There are 32 HPMCOUNTER registers # There are 32 HPMCOUNTER registers
@ -108,6 +116,33 @@ main:
# Testing the HPMCOUNTERM performance counter: reading # Testing the HPMCOUNTERM performance counter: reading
csrr t0, 2817 csrr t0, 2817
# Test writes to pmp address registers
csrw 951, t0
csrw 952, t0
csrw 953, t0
csrw 954, t0
csrw 955, t0
csrw 956, t0
csrw 957, t0
csrw 958, t0
# Testing writes to MTVAL, MCAUSE
li t0, 0
csrw mtval, t0
csrw mcause, t0
# set mstatus to enable floating point registers (mstatus.FS = 11)
bseti t1, zero, 13
csrs mstatus, t1
bseti t1, zero, 14
csrs mstatus, t1
# Test writes to floating point CSRs
csrw frm, t0
csrw fflags, t0
j done j done

173
tests/coverage/vm64check.S Normal file
View File

@ -0,0 +1,173 @@
///////////////////////////////////////////
// vm64check.S
//
// Written: David_Harris@hmc.edu 7 April 2023
//
// Purpose: vm64check coverage
//
// 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.
////////////////////////////////////////////////////////////////////////////////////////////////
// Cover IMMU vm64check block by jumping to illegal virtual addresses
// Need a nonstandard trap handler to deal with returns from theses jumps
// assign eq_46_38 = &(VAdr[46:38]) | ~|(VAdr[46:38]);
// assign eq_63_47 = &(VAdr[63:47]) | ~|(VAdr[63:47]);
// assign UpperBitsUnequal = SV39Mode ? ~(eq_63_47 & eq_46_38) : ~eq_63_47;
.section .text.init
.global rvtest_entry_point
rvtest_entry_point:
la sp, topofstack # Initialize stack pointer (not used)
# Set up interrupts
la t0, trap_handler
csrw mtvec, t0 # Initialize MTVEC to trap_handler
# set up PMP so user and supervisor mode can access full address space
csrw pmpcfg0, 0xF # configure PMP0 to TOR RWX
li t0, 0xFFFFFFFF
csrw pmpaddr0, t0 # configure PMP0 top of range to 0xFFFFFFFF to allow all 32-bit addresses
# SATP in non-39 mode
csrw satp, zero
// vm64check coverage
check1:
// check virtual addresses with bits 63:47 and/or 46:38 being equal or unequal
li t0, 0x00000001800F0000 # unimplemented memory with upper and lower all zero
la ra, check2
jalr t0
check2:
li t0, 0xFFFFFFF1800F0000 # unimplemented memory with upper and lower all one
la ra, check3
jalr t0
check3:
li t0, 0xFFF81001800F0000 # unimplemented memory with upper all one, lower mixed
la ra, check4
jalr t0
check4:
li t0, 0x03001001800F0000 # unimplemented memory with upper mixed, lower mixed
la ra, check5
jalr t0
check5:
li t0, 0x00001001800F0000 # unimplemented memory with upper all zero, lower mixed
la ra, check11
jalr t0
check11:
# SATP in SV39 mode
li t0, 0x8000000000000000
csrw satp, t0
// check virtual addresses with bits 63:47 and/or 46:38 being equal or unequal
li t0, 0x00000001800F0000 # unimplemented memory with upper and lower all zero
la ra, check12
jalr t0
check12:
li t0, 0xFFFFFFF1800F0000 # unimplemented memory with upper and lower all one
la ra, check13
jalr t0
check13:
li t0, 0xFFF81001800F0000 # unimplemented memory with upper all one, lower mixed
la ra, check14
jalr t0
check14:
li t0, 0x03001001800F0000 # unimplemented memory with upper mixed, lower mixed
la ra, check15
jalr t0
check15:
li t0, 0x00001001800F0000 # unimplemented memory with upper all zero, lower mixed
la ra, check16
jalr t0
check16:
write_tohost:
la t1, tohost
li t0, 1 # 1 for success, 3 for failure
sd t0, 0(t1) # send success code
self_loop:
j self_loop # wait
.align 4 # trap handlers must be aligned to multiple of 4
trap_handler:
csrw mepc, ra # return to address in ra
mret
.section .tohost
tohost: # write to HTIF
.dword 0
fromhost:
.dword 0
# Initialize stack with room for 512 bytes
.bss
.space 512
topofstack:
j done
lw t1, 0(t0)
li t0, 0xFFFFFFFF80000000
lw t1, 0(t0)
li t1, 0xFFF8000080000000
lw t1, 0(t0)
li t1, 0x1000000080000000
lw t1, 0(t0)
li t1, 0x0000010080000000
lw t1, 0(t0)
li t0, 0x8000000000000000
csrw satp, t0 # SV39 mode
li t0, 0x0000000080000000
lw t1, 0(t0)
li t0, 0xFFFFFFFF80000000
lw t1, 0(t0)
li t1, 0xFFF8000080000000
lw t1, 0(t0)
li t1, 0x1000000080000000
lw t1, 0(t0)
li t1, 0x0000010080000000
lw t1, 0(t0)
li t0, 0x9000000000000000
csrw satp, t0 # SV48 mode
li t0, 0x0000000080000000
lw t1, 0(t0)
li t0, 0xFFFFFFFF80000000
lw t1, 0(t0)
li t1, 0xFFF8000080000000
lw t1, 0(t0)
li t1, 0x1000000080000000
lw t1, 0(t0)
li t1, 0x0000010080000000
lw t1, 0(t0)
li t0, 0x0000000000000000
csrw satp, t0 # disable virtual memory