This commit is contained in:
Ross Thompson 2023-10-05 10:39:06 -05:00
commit 824f37bba4
31 changed files with 311 additions and 104 deletions

View File

@ -158,6 +158,12 @@ localparam ZBB_SUPPORTED = 0;
localparam ZBC_SUPPORTED = 0;
localparam ZBS_SUPPORTED = 0;
// New compressed instructions
localparam ZCB_SUPPORTED = 1;
localparam ZCA_SUPPORTED = 0;
localparam ZCF_SUPPORTED = 0;
localparam ZCD_SUPPORTED = 0;
// Memory synthesis configuration
localparam USE_SRAM = 0;

View File

@ -171,6 +171,12 @@ localparam ZBB_SUPPORTED = 1;
localparam ZBC_SUPPORTED = 1;
localparam ZBS_SUPPORTED = 1;
// New compressed instructions
localparam ZCB_SUPPORTED = 1;
localparam ZCA_SUPPORTED = 0;
localparam ZCF_SUPPORTED = 0;
localparam ZCD_SUPPORTED = 0;
// Memory synthesis configuration
localparam USE_SRAM = 0;

View File

@ -159,6 +159,12 @@ localparam ZBB_SUPPORTED = 0;
localparam ZBC_SUPPORTED = 0;
localparam ZBS_SUPPORTED = 0;
// New compressed instructions
localparam ZCB_SUPPORTED = 0;
localparam ZCA_SUPPORTED = 0;
localparam ZCF_SUPPORTED = 0;
localparam ZCD_SUPPORTED = 0;
// Memory synthesis configuration
localparam USE_SRAM = 0;

View File

@ -171,6 +171,12 @@ localparam ZBB_SUPPORTED = 1;
localparam ZBC_SUPPORTED = 1;
localparam ZBS_SUPPORTED = 1;
// New compressed instructions
localparam ZCB_SUPPORTED = 1;
localparam ZCA_SUPPORTED = 0;
localparam ZCF_SUPPORTED = 0;
localparam ZCD_SUPPORTED = 0;
// Memory synthesis configuration
localparam USE_SRAM = 0;

View File

@ -159,6 +159,12 @@ localparam ZBB_SUPPORTED = 0;
localparam ZBC_SUPPORTED = 0;
localparam ZBS_SUPPORTED = 0;
// New compressed instructions
localparam ZCB_SUPPORTED = 0;
localparam ZCA_SUPPORTED = 0;
localparam ZCF_SUPPORTED = 0;
localparam ZCD_SUPPORTED = 0;
// Memory synthesis configuration
localparam USE_SRAM = 0;

View File

@ -158,6 +158,12 @@ localparam ZBB_SUPPORTED = 0;
localparam ZBC_SUPPORTED = 0;
localparam ZBS_SUPPORTED = 0;
// New compressed instructions
localparam ZCB_SUPPORTED = 0;
localparam ZCA_SUPPORTED = 0;
localparam ZCF_SUPPORTED = 0;
localparam ZCD_SUPPORTED = 0;
// Memory synthesis configuration
localparam USE_SRAM = 0;

View File

@ -161,6 +161,12 @@ localparam ZBB_SUPPORTED = 0;
localparam ZBC_SUPPORTED = 0;
localparam ZBS_SUPPORTED = 0;
// New compressed instructions
localparam ZCB_SUPPORTED = 0;
localparam ZCA_SUPPORTED = 0;
localparam ZCF_SUPPORTED = 0;
localparam ZCD_SUPPORTED = 0;
// Memory synthesis configuration
localparam USE_SRAM = 0;

View File

@ -164,6 +164,12 @@ localparam ZBB_SUPPORTED = 1;
localparam ZBC_SUPPORTED = 1;
localparam ZBS_SUPPORTED = 1;
// New compressed instructions
localparam ZCB_SUPPORTED = 1;
localparam ZCA_SUPPORTED = 0;
localparam ZCF_SUPPORTED = 0;
localparam ZCD_SUPPORTED = 0;
// Memory synthesis configuration
localparam USE_SRAM = 0;

View File

@ -161,6 +161,12 @@ localparam ZBB_SUPPORTED = 0;
localparam ZBC_SUPPORTED = 0;
localparam ZBS_SUPPORTED = 0;
// New compressed instructions
localparam ZCB_SUPPORTED = 0;
localparam ZCA_SUPPORTED = 0;
localparam ZCF_SUPPORTED = 0;
localparam ZCD_SUPPORTED = 0;
// Memory synthesis configuration
localparam USE_SRAM = 0;

View File

@ -96,6 +96,10 @@ localparam cvw_t P = '{
ZBB_SUPPORTED : ZBB_SUPPORTED,
ZBC_SUPPORTED : ZBC_SUPPORTED,
ZBS_SUPPORTED : ZBS_SUPPORTED,
ZCA_SUPPORTED : ZCA_SUPPORTED,
ZCB_SUPPORTED : ZCB_SUPPORTED,
ZCD_SUPPORTED : ZCD_SUPPORTED,
ZCF_SUPPORTED : ZCF_SUPPORTED,
USE_SRAM : USE_SRAM,
M_MODE : M_MODE,
S_MODE : S_MODE,

View File

@ -161,6 +161,12 @@ typedef struct packed {
logic ZBC_SUPPORTED;
logic ZBS_SUPPORTED;
// compressed
logic ZCA_SUPPORTED;
logic ZCB_SUPPORTED;
logic ZCD_SUPPORTED;
logic ZCF_SUPPORTED;
// Memory synthesis configuration
logic USE_SRAM;

View File

@ -30,7 +30,7 @@
////////////////////////////////////////////////////////////////////////////////////////////////
module decompress #(parameter XLEN)(
module decompress import cvw::*; #(parameter cvw_t P) (
input logic [31:0] InstrRawD, // 32-bit instruction or raw compressed 16-bit instruction in bottom half
output logic [31:0] InstrD, // Decompressed instruction
output logic IllegalCompInstrD // Invalid decompressed instruction
@ -88,20 +88,60 @@ module decompress #(parameter XLEN)(
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
5'b00001: InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld
5'b00001: if (P.C_SUPPORTED & P.D_SUPPORTED | P.ZCD_SUPPORTED)
InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000111}; // c.fld
else begin // unsupported instruction
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
5'b00010: InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000011}; // c.lw
5'b00011: if (XLEN==32)
InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw
5'b00011: if (P.XLEN==32)
if (P.C_SUPPORTED & P.F_SUPPORTED | P.ZCF_SUPPORTED)
InstrD = {immCL, rs1p, 3'b010, rdp, 7'b0000111}; // c.flw
else begin
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
else
InstrD = {immCLD, rs1p, 3'b011, rdp, 7'b0000011}; // c.ld;
5'b00101: InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd
5'b00100: if (P.ZCB_SUPPORTED)
if (instr16[12:10] == 3'b000)
InstrD = {10'b0, instr16[6:5], rs1p, 3'b100, rdp, 7'b0000011}; // c.lbu
else if (instr16[12:10] == 3'b001) begin
if (instr16[6])
InstrD = {10'b0, instr16[5], 1'b0, rs1p, 3'b001, rdp, 7'b0000011}; // c.lh
else
InstrD = {10'b0, instr16[5], 1'b0, rs1p, 3'b101, rdp, 7'b0000011}; // c.lhu
end else if (instr16[12:10] == 3'b010)
InstrD = {7'b0, rs2p, rs1p, 3'b000, 3'b000, instr16[6:5], 7'b0000011}; // c.sb
else if (instr16[12:10] == 3'b011 & instr16[6] == 1'b0)
InstrD = {7'b0, rs2p, rs1p, 3'b001, 3'b000, instr16[5], 1'b0, 7'b0000011}; // c.sh
else begin
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
else begin
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
5'b00101: if (P.C_SUPPORTED & P.D_SUPPORTED | P.ZCD_SUPPORTED)
InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100111}; // c.fsd
else begin // unsupported instruction
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
5'b00110: InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100011}; // c.sw
5'b00111: if (XLEN==32)
InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw
5'b00111: if (P.XLEN==32)
if (P.C_SUPPORTED & P.F_SUPPORTED | P.ZCF_SUPPORTED)
InstrD = {immCS[11:5], rs2p, rs1p, 3'b010, immCS[4:0], 7'b0100111}; // c.fsw
else begin
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
else
InstrD = {immCSD[11:5], rs2p, rs1p, 3'b011, immCSD[4:0], 7'b0100011}; //c.sd
5'b01000: InstrD = {immCI, rds1, 3'b000, rds1, 7'b0010011}; // c.addi
5'b01001: if (XLEN==32)
5'b01001: if (P.XLEN==32)
InstrD = {immCJ, 5'b00001, 7'b1101111}; // c.jal
else
InstrD = {immCI, rds1, 3'b000, rds1, 7'b0011011}; // c.addiw
@ -125,33 +165,51 @@ module decompress #(parameter XLEN)(
InstrD = {7'b0000000, rs2p, rds1p, 3'b110, rds1p, 7'b0110011}; // c.or
else // if (instr16[6:5] == 2'b11)
InstrD = {7'b0000000, rs2p, rds1p, 3'b111, rds1p, 7'b0110011}; // c.and
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)
else if (instr16[12:10] == 3'b111) begin
if (instr16[6:5] == 2'b00 & P.XLEN > 32)
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 & P.XLEN > 32)
InstrD = {7'b0000000, rs2p, rds1p, 3'b000, rds1p, 7'b0111011}; // c.addw
else if (instr16[6:2] == 5'b11000 & P.ZCB_SUPPORTED)
InstrD = {12'b000011111111, rds1p, 3'b111, rds1p, 7'b0010011}; // c.zext.b = andi rd, rs1, 255
else if (instr16[6:2] == 5'b10101 & P.ZCB_SUPPORTED)
InstrD = {12'b011000000100, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.b
else if (instr16[6:2] == 5'b11010 & P.ZCB_SUPPORTED)
InstrD = {7'b0000100, 5'b00000, rds1p, 3'b100, rds1p, 3'b011, P.XLEN > 32, 3'b011}; // c.zext.h
else if (instr16[6:2] == 5'b11011 & P.ZCB_SUPPORTED)
InstrD = {12'b011000000101, rds1p, 3'b001, rds1p, 7'b0010011}; // c.sext.h
else if (instr16[6:2] == 5'b11101 & P.ZCB_SUPPORTED)
InstrD = {12'b111111111111, rds1p, 3'b100, rds1p, 7'b0010011}; // c.not = xori
else if (instr16[6:2] == 5'b11100 & P.ZCB_SUPPORTED & P.XLEN > 32)
InstrD = {7'b0000100, 5'b00000, rds1p, 3'b000, rds1p, 7'b0111011}; // c.zext.w = add.uw rd, rs1, 0
else if (instr16[6:5] == 2'b10 & P.ZCB_SUPPORTED)
InstrD = {7'b0000001, rs2p, rds1p, 3'b000, rds1p, 7'b0110011}; // c.mul
else begin // reserved
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
// coverage off
// are excluding this branch from coverage because in rv64gc XLEN is always 64 and thus greater than 32 bits
// This branch will only be taken if instr16[12:10] == 3'b111 and 'XLEN !> 32, because all other
// possible values for instr16[12:10] are covered by branches above. XLEN !> 32
// will never occur in rv64gc so this branch can not be covered
else begin // illegal instruction
end else begin // illegal instruction
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
// coverage on
5'b01101: InstrD = {immCJ, 5'b00000, 7'b1101111}; // c.j
5'b01110: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b000, immCB[4:0], 7'b1100011}; // c.beqz
5'b01111: InstrD = {immCB[11:5], 5'b00000, rs1p, 3'b001, immCB[4:0], 7'b1100011}; // c.bnez
5'b10000: InstrD = {6'b000000, immSH, rds1, 3'b001, rds1, 7'b0010011}; // c.slli
5'b10001: InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp
5'b10001: if (P.C_SUPPORTED & P.D_SUPPORTED | P.ZCD_SUPPORTED)
InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000111}; // c.fldsp
else begin // unsupported instruction
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
5'b10010: InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000011}; // c.lwsp
5'b10011: if (XLEN == 32)
InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp
5'b10011: if (P.XLEN == 32)
if (P.C_SUPPORTED & P.F_SUPPORTED | P.ZCF_SUPPORTED)
InstrD = {immCILSP, 5'b00010, 3'b010, rds1, 7'b0000111}; // c.flwsp
else begin
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
else
InstrD = {immCILSPD, 5'b00010, 3'b011, rds1, 7'b0000011}; // c.ldsp
5'b10100: if (instr16[12] == 0)
@ -167,10 +225,20 @@ module decompress #(parameter XLEN)(
InstrD = {12'b0, rds1, 3'b000, 5'b00001, 7'b1100111}; // c.jalr
else
InstrD = {7'b0000000, rs2, rds1, 3'b000, rds1, 7'b0110011}; // c.add
5'b10101: InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp
5'b10101: if (P.C_SUPPORTED & P.D_SUPPORTED | P.ZCD_SUPPORTED)
InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100111}; // c.fsdsp
else begin // unsupported instruction
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
5'b10110: InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100011}; // c.swsp
5'b10111: if (XLEN==32)
InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp
5'b10111: if (P.XLEN==32)
if (P.C_SUPPORTED & P.F_SUPPORTED | P.ZCF_SUPPORTED)
InstrD = {immCSS[11:5], rs2, 5'b00010, 3'b010, immCSS[4:0], 7'b0100111}; // c.fswsp
else begin
IllegalCompInstrD = 1;
InstrD = {16'b0, instr16}; // preserve instruction for mtval on trap
end
else
InstrD = {immCSSD[11:5], rs2, 5'b00010, 3'b011, immCSSD[4:0], 7'b0100011}; // c.sdsp
default: begin // illegal instruction

View File

@ -70,23 +70,24 @@ module ifu import cvw::*; #(parameter cvw_t P) (
output logic IClassWrongM, // Class prediction is wrong
output logic ICacheStallF, // I$ busy with multicycle operation
// Faults
input logic IllegalBaseInstrD, // Illegal non-compressed instruction
input logic IllegalFPUInstrD, // Illegal FP instruction
input logic IllegalBaseInstrD, // Illegal non-compressed instruction
input logic IllegalFPUInstrD, // Illegal FP instruction
output logic InstrPageFaultF, // Instruction page fault
output logic IllegalIEUFPUInstrD, // Illegal instruction including compressed & FP
output logic InstrMisalignedFaultM, // Branch target not aligned to 4 bytes if no compressed allowed (2 bytes if allowed)
// mmu management
input logic [1:0] PrivilegeModeW, // Priviledge mode in Writeback stage
input logic [P.XLEN-1:0] PTE, // Hardware page table walker (HPTW) writes Page table entry (PTE) to ITLB
input logic [1:0] PageType, // Hardware page table walker (HPTW) writes PageType to ITLB
input logic ITLBWriteF, // Writes PTE and PageType to ITLB
input logic [P.XLEN-1:0] SATP_REGW, // Location of the root page table and page table configuration
input logic STATUS_MXR, // Status CSR: make executable page readable
input logic STATUS_SUM, // Status CSR: Supervisor access to user memory
input logic STATUS_MPRV, // Status CSR: modify machine privilege
input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level
input logic [1:0] PrivilegeModeW, // Priviledge mode in Writeback stage
input logic [P.XLEN-1:0] PTE, // Hardware page table walker (HPTW) writes Page table entry (PTE) to ITLB
input logic [1:0] PageType, // Hardware page table walker (HPTW) writes PageType to ITLB
input logic ITLBWriteF, // Writes PTE and PageType to ITLB
input logic [P.XLEN-1:0] SATP_REGW, // Location of the root page table and page table configuration
input logic STATUS_MXR, // Status CSR: make executable page readable
input logic STATUS_SUM, // Status CSR: Supervisor access to user memory
input logic STATUS_MPRV, // Status CSR: modify machine privilege
input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level
input logic ENVCFG_PBMTE, // Page-based memory types enabled
input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries
input logic ENVCFG_HADE, // HPTW A/D Update enable
input logic sfencevmaM, // Virtual memory address fence, invalidate TLB entries
output logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
output logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits
input var logic [7:0] PMPCFG_ARRAY_REGW[P.PMP_ENTRIES-1:0], // PMP configuration from privileged unit
@ -171,7 +172,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
assign TLBFlush = sfencevmaM & ~StallMQ;
mmu #(.P(P), .TLB_ENTRIES(P.ITLB_ENTRIES), .IMMU(1))
immu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE,
immu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE, .ENVCFG_HADE,
.PrivilegeModeW, .DisableTranslation(1'b0),
.VAdr(PCFExt),
.Size(2'b10),
@ -352,9 +353,9 @@ module ifu import cvw::*; #(parameter cvw_t P) (
flopenrc #(P.XLEN) PCDReg(clk, reset, FlushD, ~StallD, PCF, PCD);
// expand 16-bit compressed instructions to 32 bits
if (P.C_SUPPORTED) begin
if (P.C_SUPPORTED | P.ZCA_SUPPORTED) begin
logic IllegalCompInstrD;
decompress #(P.XLEN) decomp(.InstrRawD, .InstrD, .IllegalCompInstrD);
decompress #(P) decomp(.InstrRawD, .InstrD, .IllegalCompInstrD);
assign IllegalIEUInstrD = IllegalBaseInstrD | IllegalCompInstrD; // illegal if bad 32 or 16-bit instr
end else begin
assign InstrD = InstrRawD;

View File

@ -83,6 +83,7 @@ module spill import cvw::*; #(parameter cvw_t P) (
assign SpillF = CacheableF ? SpillCachedF : SpillUncachedF;
end else
assign SpillF = PCF[1]; // *** might relax - only spill if next instruction is uncompressed
// Don't take the spill if there is a stall, TLB miss, or hardware update to the D/A bits
assign TakeSpillF = SpillF & ~IFUCacheBusStallF & ~(ITLBMissF | (P.SVADU_SUPPORTED & InstrUpdateDAF));
always_ff @(posedge clk)

View File

@ -81,6 +81,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV, // STATUS CSR bits: make executable readable, supervisor user memory, machine privilege
input logic [1:0] STATUS_MPP, // Machine previous privilege mode
input logic ENVCFG_PBMTE, // Page-based memory types enabled
input logic ENVCFG_HADE, // HPTW A/D Update enable
input logic [P.XLEN-1:0] PCSpillF, // Fetch PC
input logic ITLBMissF, // ITLB miss causes HPTW (hardware pagetable walker) walk
input logic InstrUpdateDAF, // ITLB hit needs to update dirty or access bits
@ -153,7 +154,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
hptw #(P) hptw(.clk, .reset, .MemRWM, .AtomicM, .ITLBMissF, .ITLBWriteF,
.DTLBMissM, .DTLBWriteM, .InstrUpdateDAF, .DataUpdateDAM,
.FlushW, .DCacheStallM, .SATP_REGW, .PCSpillF,
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .PrivilegeModeW,
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_HADE, .PrivilegeModeW,
.ReadDataM(ReadDataM[P.XLEN-1:0]), // ReadDataM is LLEN, but HPTW only needs XLEN
.WriteDataM, .Funct3M, .LSUFunct3M, .Funct7M, .LSUFunct7M,
.IEUAdrExtM, .PTE, .IHWriteDataM, .PageType, .PreLSURWM, .LSUAtomicM,
@ -190,7 +191,7 @@ module lsu import cvw::*; #(parameter cvw_t P) (
assign DisableTranslation = SelHPTW | FlushDCacheM;
assign WriteAccessM = PreLSURWM[0] | (|CMOpM);
mmu #(.P(P), .TLB_ENTRIES(P.DTLB_ENTRIES), .IMMU(0))
dmmu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE,
dmmu(.clk, .reset, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE, .ENVCFG_HADE,
.PrivilegeModeW, .DisableTranslation, .VAdr(IHAdrM), .Size(LSUFunct3M[1:0]),
.PTE, .PageTypeWriteVal(PageType), .TLBWrite(DTLBWriteM), .TLBFlush(sfencevmaM),
.PhysicalAddress(PAdrM), .TLBMiss(DTLBMissM), .Cacheable(CacheableM), .Idempotent(), .SelTIM(SelDTIM),

View File

@ -38,6 +38,7 @@ module hptw import cvw::*; #(parameter cvw_t P) (
// system status
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
input logic [1:0] STATUS_MPP,
input logic ENVCFG_HADE, // HPTW A/D Update enable
input logic [1:0] PrivilegeModeW,
input logic [P.XLEN-1:0] ReadDataM, // page table entry from LSU
input logic [P.XLEN-1:0] WriteDataM,
@ -153,7 +154,7 @@ module hptw import cvw::*; #(parameter cvw_t P) (
logic [P.XLEN-1:0] AccessedPTE;
assign AccessedPTE = {PTE[P.XLEN-1:8], (SetDirty | PTE[7]), 1'b1, PTE[5:0]}; // set accessed bit, conditionally set dirty bit
mux2 #(P.XLEN) NextPTEMux(ReadDataM, AccessedPTE, UpdatePTE, NextPTE);
mux2 #(P.XLEN) NextPTEMux(ReadDataM, AccessedPTE, UpdatePTE, NextPTE); // NextPTE = ReadDataM when HADE = 0 because UpdatePTE = 0
flopenr #(P.PA_BITS) HPTWAdrWriteReg(clk, reset, SaveHPTWAdr, HPTWReadAdr, HPTWWriteAdr);
assign SaveHPTWAdr = WalkerState == L0_ADR;
@ -182,11 +183,12 @@ module hptw import cvw::*; #(parameter cvw_t P) (
// hptw needs to know if there is a Dirty or Access fault occuring on this
// memory access. If there is the PTE needs to be updated seting Access
// and possibly also Dirty. Dirty is set if the operation is a store/amo.
// However any other fault should not cause the update.
assign HPTWUpdateDA = ValidLeafPTE & (~Accessed | SetDirty) & ~OtherPageFault;
// However any other fault should not cause the update, and updates are in software when ENVCFG_HADE = 0
assign HPTWUpdateDA = ValidLeafPTE & (~Accessed | SetDirty) & ENVCFG_HADE & ~OtherPageFault;
assign HPTWRW[0] = (WalkerState == UPDATE_PTE); // HPTWRW[0] will always be 0 if HADE = 0 because HPTWUpdateDA will be 0 so WalkerState never is UPDATE_PTE
assign UpdatePTE = (WalkerState == LEAF) & HPTWUpdateDA; // UpdatePTE will always be 0 if HADE = 0 because HPTWUpdateDA will be 0
assign HPTWRW[0] = (WalkerState == UPDATE_PTE);
assign UpdatePTE = (WalkerState == LEAF) & HPTWUpdateDA;
end else begin // block: hptwwrites
assign NextPTE = ReadDataM;
assign HPTWAdr = HPTWReadAdr;

View File

@ -35,6 +35,7 @@ module mmu import cvw::*; #(parameter cvw_t P,
input logic STATUS_MPRV, // Status CSR: modify machine privilege
input logic [1:0] STATUS_MPP, // Status CSR: previous machine privilege level
input logic ENVCFG_PBMTE, // Page-based memory types enabled
input logic ENVCFG_HADE, // HPTW A/D Update enable
input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor
input logic DisableTranslation, // virtual address translation disabled during D$ flush and HPTW walk that use physical addresses
input logic [P.XLEN+1:0] VAdr, // virtual/physical address from IEU or physical address from HPTW
@ -82,7 +83,7 @@ module mmu import cvw::*; #(parameter cvw_t P,
.clk, .reset,
.SATP_MODE(SATP_REGW[P.XLEN-1:P.XLEN-P.SVMODE_BITS]),
.SATP_ASID(SATP_REGW[P.ASID_BASE+P.ASID_BITS-1:P.ASID_BASE]),
.VAdr(VAdr[P.XLEN-1:0]), .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE,
.VAdr(VAdr[P.XLEN-1:0]), .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE, .ENVCFG_HADE,
.PrivilegeModeW, .ReadAccess, .WriteAccess,
.DisableTranslation, .PTE, .PageTypeWriteVal,
.TLBWrite, .TLBFlush, .TLBPAdr, .TLBMiss, .TLBHit,

View File

@ -58,6 +58,7 @@ module tlb import cvw::*; #(parameter cvw_t P,
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
input logic [1:0] STATUS_MPP,
input logic ENVCFG_PBMTE, // Page-based memory types enabled
input logic ENVCFG_HADE, // HPTW A/D Update enable
input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor
input logic ReadAccess,
input logic WriteAccess,
@ -104,7 +105,7 @@ module tlb import cvw::*; #(parameter cvw_t P,
assign VPN = VAdr[P.VPN_BITS+11:12];
tlbcontrol #(P, ITLB) tlbcontrol(.SATP_MODE, .VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE,
tlbcontrol #(P, ITLB) tlbcontrol(.SATP_MODE, .VAdr, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .ENVCFG_PBMTE, .ENVCFG_HADE,
.PrivilegeModeW, .ReadAccess, .WriteAccess, .DisableTranslation, .TLBFlush,
.PTEAccessBits, .CAMHit, .Misaligned,
.TLBMiss, .TLBHit, .TLBPageFault,

View File

@ -32,10 +32,11 @@ module tlbcontrol import cvw::*; #(parameter cvw_t P, ITLB = 0) (
input logic STATUS_MXR, STATUS_SUM, STATUS_MPRV,
input logic [1:0] STATUS_MPP,
input logic ENVCFG_PBMTE, // Page-based memory types enabled
input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor
input logic ENVCFG_HADE, // HPTW A/D Update enable
input logic [1:0] PrivilegeModeW, // Current privilege level of the processeor
input logic ReadAccess, WriteAccess,
input logic DisableTranslation,
input logic TLBFlush, // Invalidate all TLB entries
input logic TLBFlush, // Invalidate all TLB entries
input logic [11:0] PTEAccessBits,
input logic CAMHit,
input logic Misaligned,
@ -114,50 +115,12 @@ module tlbcontrol import cvw::*; #(parameter cvw_t P, ITLB = 0) (
end
// Determine wheter to update DA bits. With SVADU, it is done in hardware
if (P.SVADU_SUPPORTED) assign UpdateDA = PreUpdateDA & Translate & TLBHit & ~TLBPageFault;
else assign UpdateDA = PreUpdateDA;
assign UpdateDA = P.SVADU_SUPPORTED & PreUpdateDA & Translate & TLBHit & ~TLBPageFault & ENVCFG_HADE;
// Determine whether page fault occurs
assign PrePageFault = UpperBitsUnequal | Misaligned | ~PTE_V | ImproperPrivilege | (P.XLEN == 64 & (BadPBMT | BadNAPOT | BadReserved)) | (PreUpdateDA & ~P.SVADU_SUPPORTED);
assign PrePageFault = UpperBitsUnequal | Misaligned | ~PTE_V | ImproperPrivilege | (P.XLEN == 64 & (BadPBMT | BadNAPOT | BadReserved)) | (PreUpdateDA & (~P.SVADU_SUPPORTED | ~ENVCFG_HADE));
assign TLBPageFault = Translate & TLBHit & (PrePageFault | InvalidAccess);
/*
// Check whether the access is allowed, page faulting if not.
if (ITLB == 1) begin:itlb // Instruction TLB fault checking
// User mode may only execute user mode pages, and supervisor mode may
// only execute non-user mode pages.
assign ImproperPrivilege = ((EffectivePrivilegeMode == P.U_MODE) & ~PTE_U) |
((EffectivePrivilegeMode == P.S_MODE) & PTE_U);
assign CausePageFault = ImproperPrivilege | ~PTE_X | UpperBitsUnequal | BadPTE | BadPBMT | Misaligned | ~PTE_V | (~PTE_A & P.SVADU_SUPPORTED);
assign TLBPageFault = Translate & TLBHit & CausePageFault;
// Determine wheter to update DA bits
if(P.SVADU_SUPPORTED) assign UpdateDA = Translate & TLBHit & ~PTE_A & ~TLBPageFault;
else assign UpdateDA = ~PTE_A;
end else begin:dtlb // Data TLB fault checking
logic InvalidRead, InvalidWrite;
// User mode may only load/store from user mode pages, and supervisor mode
// may only access user mode pages when STATUS_SUM is low.
assign ImproperPrivilege = ((EffectivePrivilegeMode == P.U_MODE) & ~PTE_U) |
((EffectivePrivilegeMode == P.S_MODE) & PTE_U & ~STATUS_SUM);
// Check for read error. Reads are invalid when the page is not readable
// (and executable pages are not readable) or when the page is neither
// readable nor executable (and executable pages are readable).
assign InvalidRead = ReadAccess & ~PTE_R & (~STATUS_MXR | ~PTE_X);
// Check for write error. Writes are invalid when the page's write bit is
// low.
assign InvalidWrite = WriteAccess & ~PTE_W;
if(P.SVADU_SUPPORTED) begin : hptwwrites
assign UpdateDA = Translate & TLBHit & (~PTE_A | WriteAccess & ~PTE_D) & ~TLBPageFault;
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | UpperBitsUnequal | Misaligned | ~PTE_V)); // *** update to match
end else begin
// Fault for software handling if access bit is off or writing a page with dirty bit off
assign UpdateDA = ~PTE_A | WriteAccess & ~PTE_D;
assign TLBPageFault = (Translate & TLBHit & (ImproperPrivilege | InvalidRead | InvalidWrite | UpdateDA | UpperBitsUnequal | Misaligned | ~PTE_V));
end
end
*/
assign TLBHit = CAMHit & TLBAccess;
assign TLBMiss = ~CAMHit & TLBAccess & Translate ;
endmodule

View File

@ -86,6 +86,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
output logic [2:0] FRM_REGW,
output logic [3:0] ENVCFG_CBE,
output logic ENVCFG_PBMTE, // Page-based memory type enable
output logic ENVCFG_HADE, // HPTW A/D Update enable
//
output logic [P.XLEN-1:0] CSRReadValW, // value read from CSR
output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC, accounting for traps and returns
@ -292,6 +293,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
// Broadcast appropriate environment configuration based on privilege mode
assign ENVCFG_STCE = MENVCFG_REGW[63]; // supervisor timer counter enable
assign ENVCFG_PBMTE = MENVCFG_REGW[62]; // page-based memory types enable
assign ENVCFG_HADE = MENVCFG_REGW[61]; // Hardware A/D Update enable
assign ENVCFG_CBE = (PrivilegeModeW == P.M_MODE) ? 4'b1111 :
(PrivilegeModeW == P.S_MODE | !P.S_SUPPORTED) ? MENVCFG_REGW[7:4] :
(MENVCFG_REGW[7:4] & SENVCFG_REGW[7:4]);

View File

@ -172,7 +172,8 @@ module csrm import cvw::*; #(parameter cvw_t P) (
assign MENVCFG_WriteValM = {
MENVCFG_PreWriteValM[63] & P.SSTC_SUPPORTED,
MENVCFG_PreWriteValM[62] & P.SVPBMT_SUPPORTED,
54'b0,
MENVCFG_PreWriteValM[61] & P.SVADU_SUPPORTED,
53'b0,
MENVCFG_PreWriteValM[7] & P.ZICBOZ_SUPPORTED,
MENVCFG_PreWriteValM[6:4] & {3{P.ZICBOM_SUPPORTED}},
3'b0,

View File

@ -84,6 +84,7 @@ module privileged import cvw::*; #(parameter cvw_t P) (
output logic [2:0] FRM_REGW, // FPU rounding mode
output logic [3:0] ENVCFG_CBE, // Cache block operation enables
output logic ENVCFG_PBMTE, // Page-based memory type enable
output logic ENVCFG_HADE, // HPTW A/D Update enable
// PC logic output in privileged unit
output logic [P.XLEN-1:0] UnalignedPCNextF, // Next PC from trap/return PC logic
// control outputs
@ -138,7 +139,7 @@ module privileged import cvw::*; #(parameter cvw_t P) (
.STATUS_MIE, .STATUS_SIE, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_TW, .STATUS_FS,
.MEDELEG_REGW, .MIP_REGW, .MIE_REGW, .MIDELEG_REGW,
.SATP_REGW, .PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.SetFflagsM, .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE,
.SetFflagsM, .FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_HADE,
.CSRReadValW,.UnalignedPCNextF, .IllegalCSRAccessM, .BigEndianM);
// pipeline early-arriving trap sources

View File

@ -78,6 +78,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
logic LoadStallD, StoreStallD, MDUStallD, CSRRdStallD;
logic SquashSCW;
logic MDUActiveE; // Mul/Div instruction being executed
logic ENVCFG_HADE; // HPTW A/D Update enable
logic ENVCFG_PBMTE; // Page-based memory type enable
logic [3:0] ENVCFG_CBE; // Cache Block operation enables
logic [3:0] CMOpM; // 1: cbo.inval; 2: cbo.flush; 4: cbo.clean; 8: cbo.zero
@ -185,7 +186,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
.IllegalBaseInstrD, .IllegalFPUInstrD, .InstrPageFaultF, .IllegalIEUFPUInstrD, .InstrMisalignedFaultM,
// mmu management
.PrivilegeModeW, .PTE, .PageType, .SATP_REGW, .STATUS_MXR, .STATUS_SUM, .STATUS_MPRV,
.STATUS_MPP, .ENVCFG_PBMTE, .ITLBWriteF, .sfencevmaM, .ITLBMissF,
.STATUS_MPP, .ENVCFG_PBMTE, .ENVCFG_HADE, .ITLBWriteF, .sfencevmaM, .ITLBMissF,
// pmp/pma (inside mmu) signals.
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW, .InstrAccessFaultF, .InstrUpdateDAF);
@ -234,6 +235,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
.STATUS_MPRV, // from csr
.STATUS_MPP, // from csr
.ENVCFG_PBMTE, // from csr
.ENVCFG_HADE, // from csr
.sfencevmaM, // connects to privilege
.DCacheStallM, // connects to privilege
.LoadPageFaultM, // connects to privilege
@ -296,7 +298,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
.PrivilegeModeW, .SATP_REGW,
.STATUS_MXR, .STATUS_SUM, .STATUS_MPRV, .STATUS_MPP, .STATUS_FS,
.PMPCFG_ARRAY_REGW, .PMPADDR_ARRAY_REGW,
.FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM, .BigEndianM);
.FRM_REGW, .ENVCFG_CBE, .ENVCFG_PBMTE, .ENVCFG_HADE, .BreakpointFaultM, .EcallFaultM, .wfiM, .IntPendingM, .BigEndianM);
end else begin
assign CSRReadValW = 0;
assign UnalignedPCNextF = PC2NextF;

View File

@ -63,6 +63,11 @@ module riscvassertions import cvw::*; #(parameter cvw_t P);
assert ((P.ZICBOP_SUPPORTED == 0) || (P.DCACHE_SUPPORTED == 1)) else $error("ZICBOP requires DCACHE_SUPPORTED");
assert ((P.SVPBMT_SUPPORTED == 0) || (P.VIRTMEM_SUPPORTED == 1 && P.XLEN==64)) else $error("SVPBMT requires VIRTMEM_SUPPORTED and RV64");
assert ((P.SVNAPOT_SUPPORTED == 0) || (P.VIRTMEM_SUPPORTED == 1 && P.XLEN==64)) else $error("SVNAPOT requires VIRTMEM_SUPPORTED and RV64");
assert ((P.ZCB_SUPPORTED == 0) || (P.M_SUPPORTED == 1 && (P.ZBA_SUPPORTED == 1 || P.XLEN == 32) && P.ZBB_SUPPORTED == 1)) else $error("ZCB requires M and ZBB (and also ZBA for RV64)");
assert ((P.C_SUPPORTED == 0) || (P.ZCA_SUPPORTED == 0 && P.ZCF_SUPPORTED == 0 && P.ZCD_SUPPORTED == 0)) else $error("C and ZCA/ZCD/ZCF cannot simultaneously be supported");
assert ((P.ZCA_SUPPORTED == 1) || (P.ZCD_SUPPORTED == 0 && P.ZCF_SUPPORTED == 0)) else $error("ZCF or ZCD requires ZCA");
assert ((P.ZCF_SUPPORTED == 0) || (P.F_SUPPORTED == 1)) else $error("ZCF requires F");
assert ((P.ZCD_SUPPORTED == 0) || (P.D_SUPPORTED == 1)) else $error("ZCD requires D");
end
endmodule

View File

@ -35,8 +35,15 @@ beef0110
0000000f
0000000c
00000bad
beef0770 # Test 11.3.1.3.5: check successful read/write when A=0 and SVADU=1
beef0aa0 # Test 11.3.1.3.6: check successful read/write when D=0 and SVADU=1
0000000f # Test 11.3.1.3.6(a) page fault on write when A = 0
0000000d # Test 11.3.1.3.6(a) page fault on read when A = 0
00000bad
0000000f # Test 11.3.1.3.7(a) page fault on write when D = 0
deadbeef # Test 11.3.1.3.7(a) successful read when D = 0
00000009 # call from going to m mode from s mode
0000000b # ecall from going to S mode from m mode
beef0770 # Test 11.3.1.3.6: check successful read/write when A=0 and MENVCFG.HADE=1
beef0aa0 # Test 11.3.1.3.7: check successful read/write when D=0 and MENVCFG.HADE=1
beef0077 # Test 11.3.1.4.1: successful read back of saved value with new memory mapping
00000009 # Test 11.3.1.5.1: ecall from going to m mode from s mode
00000000 # previous value of mprv before being set

View File

@ -1324,6 +1324,18 @@ write_mideleg:
csrw mideleg, t4
j test_loop
write_menvcfg:
// writes the value in t4 to the menvcfg register
// Doesn't log anything
csrw menvcfg, t4
j test_loop
write_menvcfgh:
// writes the value in t4 to the menvcfgh register
// Doesn't log anything
csrw menvcfgh, t4
j test_loop
executable_test:
// Execute the code at the address in t3, returning the value in t2.
// Assumes the code modifies t2, to become the value stored in t4 for this test.

View File

@ -157,13 +157,28 @@ test_cases:
.4byte 0xBFFDE0, 0xbad, executable_test # instr page fault when X=0
# In the following two tests, SVADU is supported, so the hardware handles the A/D bits
# Initially test with HADE = 0, so needing to set A/D bits triggers page fault
# test 11.3.1.3.6(a) Accessed flag == 0
.4byte 0x3020, 0xBEEF0770, write32_test # store page fault when A=0
.4byte 0x3020, 0xBEEF0770, read32_test # load page fault when A=0
# test 11.3.1.3.7(a) Dirty flag == 0
.4byte 0x4658, 0xBEEF0AA0, write32_test # store page fault when D=0
.4byte 0x4658, 0xDEADBEEF, read32_test # read success when D=0; default DEADBEEF value wasn't changed
# Now set HADE bit
.4byte 0x0, 0x0, goto_m_mode # change to M mode, 0x9 written to output
.4byte 0x0, 0x20000000, write_menvcfgh # set menvcfg.HADE = 1
.4byte 0x0, 0x0, goto_s_mode # change to S mode, 0xb written to output
# Since SVADU is 1, there are no faults when A/D=0
# test 11.3.1.3.6 Accessed flag == 0
# test 11.3.1.3.6(b) Accessed flag == 0
.4byte 0x3020, 0xBEEF0770, write32_test # Write success when A=0 and SVADU is enabled
.4byte 0x3020, 0xBEEF0770, read32_test # Read success when A=0 and SVADU is enabled
# test 11.3.1.3.7 Dirty flag == 0
# test 11.3.1.3.7(b) Dirty flag == 0
.4byte 0x4658, 0xBEEF0AA0, write32_test # write successs when D=0 and SVADU is enabled
.4byte 0x4658, 0xBEEF0AA0, read32_test # read success when D=0

View File

@ -84,9 +84,23 @@ beef0110 # Test 11.3.1.3.4: read test success
00000000
00000bad
00000000
beef0770 # Test 11.3.1.3.6: check successful read/write when A=0 and SVADU=1
0000000f # Test 11.3.1.3.6(a): write test with page fault
00000000
0000000d # read test with page fault
00000000
00000bad
00000000
0000000f # Test 11.3.1.3.7(a): write test with page fault
00000000
deadbeef # read test success but nothing was written so read back default
deadbeef
00000009 # ecall from going to M mode from S mode
00000000
0000000B # ecall from going to S mode from M mode
00000000
beef0770 # Test 11.3.1.3.6(b): check successful read/write when A=0 and SVADU=1
0990dead
beef0aa0 # Test 11.3.1.3.7: check successful read/write when D=0 and SVADU=1
beef0aa0 # Test 11.3.1.3.7(b): check successful read/write when D=0 and SVADU=1
0440dead
0000000d # Test 11.3.1.3.8: read test with page fault for nonzero reserved bit
00000000

View File

@ -92,9 +92,23 @@ beef0110 # Test 11.3.1.3.4: read test success
00000000
00000bad
00000000
beef0770 # Test 11.3.1.3.5: check successful read/write when A=0 and SVADU=1
0000000f # Test 11.3.1.3.6(a): write test with page fault
00000000
0000000d # read test with page fault
00000000
00000bad
00000000
0000000f # Test 11.3.1.3.7(a): write test with page fault
00000000
deadbeef # read test success but get deadbeef because nothing was written
deadbeef
00000009 # ecall from going to M mode from S mode
00000000
0000000B # ecall from going to S mode from M mode
00000000
beef0770 # Test 11.3.1.3.6(b): check successful read/write when A=0 and SVADU=1
0990dead
beef0aa0 # Test 11.3.1.3.6: check successful read/write when D=0 and SVADU=1
beef0aa0 # Test 11.3.1.3.7(b): check successful read/write when D=0 and SVADU=1
0440dead
beef0000 # Test 11.3.1.4.1: read test success on new page table mapping
0000dead

View File

@ -194,13 +194,29 @@ test_cases:
# *** fetches on pages with X = 1 already tested in 11.3.1.3.1
.8byte 0x5AA0, 0x1, executable_test # instr page fault when X=0
# In the following two tests, SVADU is supported, so the hardware handles the A/D bits
# Initially test with HADE = 0, so needing to set A/D bits triggers page fault
# test 11.3.1.3.6(a) Accessed flag == 0
.8byte 0x36D0, 0x0990DEADBEEF0770, write64_test# store page fault when A=0
.8byte 0x3AB8, 0x0990DEADBEEF0990, read64_test# load page fault when A=0
# test 11.3.1.3.7(a) Dirty flag == 0
.8byte 0x4658, 0x0440DEADBEEF0AA0, write64_test# store page fault when D=0
.8byte 0x4AA0, 0xDEADBEEFDEADBEEF, read64_test# read success when D=0
# Now set HADE bit
.8byte 0x0, 0x0, goto_m_mode # change to M mode, 0x9 written to output
.8byte 0x0, 0x2000000000000000, write_menvcfg # set menvcfg.HADE = 1
.8byte 0x0, 0x0, goto_s_mode # change to S mode, 0xb written to output
# Since SVADU is 1, there are no faults when A/D=0
# test 11.3.1.3.6 Accessed flag == 0
# test 11.3.1.3.6(b) Accessed flag == 0
.8byte 0x36D0, 0x0990DEADBEEF0770, write64_test # Write success when A=0 and SVADU is enabled
.8byte 0x36D0, 0x0990DEADBEEF0770, read64_test # Read success when A=0 and SVADU is enabled
# test 11.3.1.3.7 Dirty flag == 0
# test 11.3.1.3.7(b) Dirty flag == 0
.8byte 0x4658, 0x0440DEADBEEF0AA0, write64_test # Write success when D=0 and SVADU is enabled
.8byte 0x4658, 0x0440DEADBEEF0AA0, read64_test # read success when D=0

View File

@ -187,7 +187,23 @@ test_cases:
# executes on pages with X = 1 already tested in 11.3.1.3.1
.8byte 0x010088888000, 0x2, executable_test # execute fault when X=0
# In the following two tests, SVADU is supported, so the hardware handles the A/D bits
# Initially test with HADE = 0, so needing to set A/D bits triggers page fault
# test 11.3.1.3.6(a) Accessed flag == 0
.8byte 0x802036D0, 0x0990DEADBEEF0770, write64_test # store page fault when A=0
.8byte 0x802036D0, 0x0990DEADBEEF0990, read64_test # load page fault when A=0
# test 11.3.1.3.7(a) Dirty flag == 0
.8byte 0x80204658, 0x0440DEADBEEF0AA0, write64_test # store page fault when D=0
.8byte 0x80204658, 0xDEADBEEFDEADBEEF, read64_test # read success when D=0
# Now set HADE bit
.8byte 0x0, 0x0, goto_m_mode # change to M mode, 0x9 written to output
.8byte 0x0, 0x2000000000000000, write_menvcfg # set menvcfg.HADE = 1
.8byte 0x0, 0x0, goto_s_mode # change to S mode, 0xb written to output
# Since SVADU is 1, there are no faults when A/D=0
# test 11.3.1.3.6 Accessed flag == 0