mirror of
				https://github.com/openhwgroup/cvw
				synced 2025-02-11 06:05:49 +00:00 
			
		
		
		
	Merge branch 'main' of https://github.com/openhwgroup/cvw
This commit is contained in:
		
						commit
						608728b3c5
					
				@ -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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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, 
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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)
 | 
			
		||||
 | 
			
		||||
@ -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), 
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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, 
 | 
			
		||||
 | 
			
		||||
@ -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, 
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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]);
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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.  
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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 
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user