mirror of
https://github.com/openhwgroup/cvw.git
synced 2025-06-27 17:01:20 -04:00
Merge pull request #1411 from rosethompson/main
Fixes Misalgined Instruction Page Fault
This commit is contained in:
commit
56e6749eec
8 changed files with 180 additions and 11 deletions
|
@ -70,7 +70,7 @@ module ebufsmarb (
|
|||
case (CurrState)
|
||||
IDLE: if (both) NextState = ARBITRATE;
|
||||
else NextState = IDLE;
|
||||
ARBITRATE: if (HREADY & FinalBeatD & ~(LSUReq & IFUReq)) NextState = IDLE;
|
||||
ARBITRATE: if (HREADY & FinalBeatD & ~both) NextState = IDLE;
|
||||
else NextState = ARBITRATE;
|
||||
default: NextState = IDLE;
|
||||
endcase
|
||||
|
@ -80,7 +80,7 @@ module ebufsmarb (
|
|||
// Controller 0 (IFU)
|
||||
assign IFUSave = CurrState == IDLE & both;
|
||||
assign IFURestore = CurrState == ARBITRATE;
|
||||
assign IFUDisable = CurrState == ARBITRATE;
|
||||
assign IFUDisable = IFURestore;
|
||||
assign IFUSelect = (NextState == ARBITRATE) ? 1'b0 : IFUReq;
|
||||
// Controller 1 (LSU)
|
||||
// When both the IFU and LSU request at the same time, the FSM will go into the arbitrate state.
|
||||
|
@ -89,7 +89,8 @@ module ebufsmarb (
|
|||
// This is necessary because the pipeline is stalled for the entire duration of both transactions,
|
||||
// and the LSU memory request will still be active.
|
||||
flopr #(1) ifureqreg(HCLK, ~HRESETn, IFUReq, IFUReqDelay);
|
||||
assign LSUDisable = (CurrState == ARBITRATE) ? 1'b0 : (IFUReqDelay & ~(HREADY & FinalBeatD));
|
||||
//assign LSUDisable = (CurrState != ARBITRATE) & (IFUReqDelay & ~(HREADY & FinalBeatD));
|
||||
assign LSUDisable = (CurrState != ARBITRATE) & IFUReqDelay;
|
||||
assign LSUSelect = (NextState == ARBITRATE) ? 1'b1: LSUReq;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -64,6 +64,7 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||
output logic [31:0] InstrM, // The decoded instruction in Memory stage
|
||||
output logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
||||
output logic [P.XLEN-1:0] PCM, // Memory stage instruction address
|
||||
output logic [P.XLEN-1:0] PCSpillM, // Memory stage instruction address
|
||||
// branch predictor
|
||||
output logic [3:0] IClassM, // The valid instruction class. 1-hot encoded as jalr, ret, jr (not ret), j, br
|
||||
output logic BPDirWrongM, // Prediction direction is wrong
|
||||
|
@ -149,13 +150,23 @@ module ifu import cvw::*; #(parameter cvw_t P) (
|
|||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if(P.ZCA_SUPPORTED) begin : Spill
|
||||
logic [P.XLEN-1:0] PCSpillD, PCSpillE;
|
||||
logic [P.XLEN-1:0] PCIncrM;
|
||||
logic SelSpillF, SelSpillD, SelSpillE, SelSpillM;
|
||||
spill #(P) spill(.clk, .reset, .StallF, .FlushD, .PCF, .PCPlus4F, .PCNextF, .InstrRawF, .CacheableF,
|
||||
.IFUCacheBusStallF, .ITLBMissOrUpdateAF, .PCSpillNextF, .PCSpillF, .SelSpillNextF, .PostSpillInstrRawF, .CompressedF);
|
||||
.IFUCacheBusStallF, .ITLBMissOrUpdateAF, .PCSpillNextF, .PCSpillF, .SelSpillNextF, .SelSpillF, .PostSpillInstrRawF, .CompressedF);
|
||||
flopenr #(1) SpillDReg(clk, reset, ~StallD, SelSpillF, SelSpillD);
|
||||
flopenr #(1) SpillEReg(clk, reset, ~StallE, SelSpillD, SelSpillE);
|
||||
flopenr #(1) SpillMReg(clk, reset, ~StallM, SelSpillE, SelSpillM);
|
||||
assign PCIncrM = PCM + 'd2;
|
||||
mux2 #(P.XLEN) pcspillmmux(PCM, PCIncrM, SelSpillM, PCSpillM);
|
||||
|
||||
end else begin : NoSpill
|
||||
assign PCSpillNextF = PCNextF;
|
||||
assign PCSpillF = PCF;
|
||||
assign PostSpillInstrRawF = InstrRawF;
|
||||
assign {SelSpillNextF, CompressedF} = '0;
|
||||
assign PCSpillM = PCM;
|
||||
end
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -44,6 +44,7 @@ module spill import cvw::*; #(parameter cvw_t P) (
|
|||
output logic [P.XLEN-1:0] PCSpillNextF, // The next PCF for one of the two memory addresses of the spill
|
||||
output logic [P.XLEN-1:0] PCSpillF, // PCF for one of the two memory addresses of the spill
|
||||
output logic SelSpillNextF, // During the transition between the two spill operations, the IFU should stall the pipeline
|
||||
output logic SelSpillF, // Select incremented PC on a spill
|
||||
output logic [31:0] PostSpillInstrRawF,// The final 32 bit instruction after merging the two spilled fetches into 1 instruction
|
||||
output logic CompressedF); // The fetched instruction is compressed
|
||||
|
||||
|
@ -54,7 +55,6 @@ module spill import cvw::*; #(parameter cvw_t P) (
|
|||
logic [P.XLEN-1:0] PCPlus2NextF, PCPlus2F;
|
||||
logic TakeSpillF;
|
||||
logic SpillF;
|
||||
logic SelSpillF;
|
||||
logic SpillSaveF;
|
||||
logic [15:0] InstrFirstHalfF;
|
||||
logic EarlyCompressedF;
|
||||
|
|
|
@ -36,6 +36,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||
input logic [31:0] InstrM, // current instruction
|
||||
input logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
||||
input logic [P.XLEN-1:0] PCM, // program counter, next PC going to trap/return logic
|
||||
input logic [P.XLEN-1:0] PCSpillM, // program counter, next PC going to trap/return logic aligned after an instruction spill
|
||||
input logic [P.XLEN-1:0] SrcAM, IEUAdrxTvalM, // SrcA and memory address from IEU
|
||||
input logic CSRReadM, CSRWriteM, // read or write CSR
|
||||
input logic TrapM, // trap is occurring
|
||||
|
@ -140,7 +141,7 @@ module csr import cvw::*; #(parameter cvw_t P) (
|
|||
always_comb
|
||||
if (InterruptM) NextFaultMtvalM = '0;
|
||||
else case (CauseM)
|
||||
12, 1, 3: NextFaultMtvalM = PCM; // Instruction page/access faults, breakpoint
|
||||
12, 1, 3: NextFaultMtvalM = PCSpillM; // Instruction page/access faults, breakpoint
|
||||
2: NextFaultMtvalM = {{(P.XLEN-32){1'b0}}, InstrOrigM}; // Illegal instruction fault
|
||||
0, 4, 6, 13, 15, 5, 7: NextFaultMtvalM = IEUAdrxTvalM; // Instruction misaligned, Load/Store Misaligned/page/access faults
|
||||
default: NextFaultMtvalM = '0; // Ecall, interrupts
|
||||
|
|
|
@ -39,6 +39,7 @@ module privileged import cvw::*; #(parameter cvw_t P) (
|
|||
input logic [31:0] InstrOrigM, // Original compressed or uncompressed instruction in Memory stage for Illegal Instruction MTVAL
|
||||
input logic [P.XLEN-1:0] IEUAdrxTvalM, // address from IEU
|
||||
input logic [P.XLEN-1:0] PCM, // program counter
|
||||
input logic [P.XLEN-1:0] PCSpillM, // program counter
|
||||
// control signals
|
||||
input logic InstrValidM, // Current instruction is valid (not flushed)
|
||||
input logic CommittedM, CommittedF, // current instruction is using bus; don't interrupt
|
||||
|
@ -133,7 +134,7 @@ module privileged import cvw::*; #(parameter cvw_t P) (
|
|||
|
||||
// Control and Status Registers
|
||||
csr #(P) csr(.clk, .reset, .FlushM, .FlushW, .StallE, .StallM, .StallW,
|
||||
.InstrM, .InstrOrigM, .PCM, .SrcAM, .IEUAdrxTvalM,
|
||||
.InstrM, .InstrOrigM, .PCM, .PCSpillM, .SrcAM, .IEUAdrxTvalM,
|
||||
.CSRReadM, .CSRWriteM, .TrapM, .mretM, .sretM, .InterruptM,
|
||||
.MTimerInt, .MExtInt, .SExtInt, .MSwInt,
|
||||
.MTIME_CLINT, .InstrValidM, .FRegWriteM, .LoadStallD, .StoreStallD,
|
||||
|
|
|
@ -62,7 +62,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||
logic [31:0] InstrD;
|
||||
logic [31:0] InstrM, InstrOrigM;
|
||||
logic [P.XLEN-1:0] PCSpillF, PCE, PCLinkE;
|
||||
logic [P.XLEN-1:0] PCM;
|
||||
logic [P.XLEN-1:0] PCM, PCSpillM;
|
||||
logic [P.XLEN-1:0] CSRReadValW, MDUResultW;
|
||||
logic [P.XLEN-1:0] EPCM, TrapVectorM;
|
||||
logic [1:0] MemRWE;
|
||||
|
@ -184,7 +184,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||
.PCLinkE, .PCSrcE, .IEUAdrE, .IEUAdrM, .PCE, .BPWrongE, .BPWrongM,
|
||||
// Mem
|
||||
.CommittedF, .EPCM, .TrapVectorM, .RetM, .TrapM, .InvalidateICacheM, .CSRWriteFenceM,
|
||||
.InstrD, .InstrM, .InstrOrigM, .PCM, .IClassM, .BPDirWrongM,
|
||||
.InstrD, .InstrM, .InstrOrigM, .PCM, .PCSpillM, .IClassM, .BPDirWrongM,
|
||||
.BTAWrongM, .RASPredPCWrongM, .IClassWrongM,
|
||||
// Faults out
|
||||
.IllegalBaseInstrD, .IllegalFPUInstrD, .InstrPageFaultF, .IllegalIEUFPUInstrD, .InstrMisalignedFaultM,
|
||||
|
@ -289,7 +289,7 @@ module wallypipelinedcore import cvw::*; #(parameter cvw_t P) (
|
|||
privileged #(P) priv(
|
||||
.clk, .reset,
|
||||
.FlushD, .FlushE, .FlushM, .FlushW, .StallD, .StallE, .StallM, .StallW,
|
||||
.CSRReadM, .CSRWriteM, .SrcAM, .PCM,
|
||||
.CSRReadM, .CSRWriteM, .SrcAM, .PCM, .PCSpillM,
|
||||
.InstrM, .InstrOrigM, .CSRReadValW, .EPCM, .TrapVectorM,
|
||||
.RetM, .TrapM, .sfencevmaM, .InvalidateICacheM, .DCacheStallM, .ICacheStallF,
|
||||
.InstrValidM, .CommittedM, .CommittedF,
|
||||
|
|
155
tests/coverage/WALLY-init-lib-misalignedSpill.h
Normal file
155
tests/coverage/WALLY-init-lib-misalignedSpill.h
Normal file
|
@ -0,0 +1,155 @@
|
|||
///////////////////////////////////////////
|
||||
// WALLY-init-lib.h
|
||||
//
|
||||
// Written: David_Harris@hmc.edu 21 March 2023
|
||||
//
|
||||
// Purpose: Initialize stack, handle interrupts, terminate test case
|
||||
//
|
||||
// A component of the CORE-V-WALLY configurable RISC-V project.
|
||||
// https://github.com/openhwgroup/cvw
|
||||
//
|
||||
// Copyright (C) 2021-23 Harvey Mudd College & Oklahoma State University
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.1
|
||||
//
|
||||
// Licensed under the Solderpad Hardware License v 2.1 (the “License”); you may not use this file
|
||||
// except in compliance with the License, or, at your option, the Apache License version 2.0. You
|
||||
// may obtain a copy of the License at
|
||||
//
|
||||
// https://solderpad.org/licenses/SHL-2.1/
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, any work distributed under the
|
||||
// License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// either express or implied. See the License for the specific language governing permissions
|
||||
// and limitations under the License.
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// load code to initalize stack, handle interrupts, terminate
|
||||
// The PMP tests are sensitive to the exact addresses in this code, so unfortunately
|
||||
// modifying anything breaks those tests.
|
||||
|
||||
.section .text.init
|
||||
.global rvtest_entry_point
|
||||
|
||||
rvtest_entry_point:
|
||||
la sp, topofstack # Initialize stack pointer (not used)
|
||||
|
||||
# Set up interrupts
|
||||
la t0, trap_handler
|
||||
csrw mtvec, t0 # Initialize MTVEC to trap_handler
|
||||
csrw mideleg, zero # Don't delegate interrupts
|
||||
csrw medeleg, zero # Don't delegate exceptions
|
||||
# li t0, -1 # set mtimecmp to biggest number so it doesnt interrupt again
|
||||
# li t1, 0x02004000 # MTIMECMP in CLINT
|
||||
# sd t0, 0(t1)
|
||||
li t0, 0x80
|
||||
# li t0, 0x00
|
||||
csrw mie, t0 # Enable machine timer interrupt
|
||||
la t0, topoftrapstack
|
||||
csrw mscratch, t0 # MSCRATCH holds trap stack pointer
|
||||
csrsi mstatus, 0x8 # Turn on mstatus.MIE global interrupt enable
|
||||
# set up PMP so user and supervisor mode can access full address space
|
||||
csrw pmpcfg0, 0xF # configure PMP0 to TOR RWX
|
||||
li t0, 0xFFFFFFFF
|
||||
csrw pmpaddr0, t0 # configure PMP0 top of range to 0xFFFFFFFF to allow all 32-bit addresses
|
||||
j main # Call main function in user test program
|
||||
|
||||
done:
|
||||
li a0, 4 # argument to finish program
|
||||
ecall # system call to finish program
|
||||
j self_loop # wait forever (not taken)
|
||||
|
||||
.align 4 # trap handlers must be aligned to multiple of 4
|
||||
trap_handler:
|
||||
# Load trap handler stack pointer tp
|
||||
csrrw tp, mscratch, tp # swap MSCRATCH and tp
|
||||
sd t0, 0(tp) # Save t0 and t1 on the stack
|
||||
sd t1, -8(tp)
|
||||
csrr t0, mcause # Check the cause
|
||||
csrr t1, mtval # And the trap value
|
||||
bgez t0, exception # if msb is clear, it is an exception
|
||||
|
||||
interrupt: # must be a timer interrupt
|
||||
li t0, -1 # set mtimecmp to biggest number so it doesnt interrupt again
|
||||
li t1, 0x02004000 # MTIMECMP in CLIN
|
||||
sd t0, 0(t1)
|
||||
csrw stimecmp, t0 # sets stimecmp to big number so it doesnt interrupt
|
||||
li t0, 32
|
||||
csrc sip, t0 # clears stimer interrupt
|
||||
j trap_return # clean up and return
|
||||
|
||||
exception:
|
||||
csrr t0, mcause
|
||||
li t1, 0xC # is it an instruction page fault
|
||||
li a0, 3 # set a0 to 3 to ecall looks like a program terminate
|
||||
beq t0, t1, ecall # terminate program for instruction page fault
|
||||
li t1, 8 # is it an ecall trap?
|
||||
andi t0, t0, 0xFC # if CAUSE = 8, 9, or 11
|
||||
bne t0, t1, trap_return # ignore other exceptions
|
||||
|
||||
ecall:
|
||||
li t0, 4
|
||||
beq a0, t0, write_tohost # call 4: terminate program
|
||||
bltu a0, t0, changeprivilege # calls 0-3: change privilege level
|
||||
j trap_return # ignore other ecalls
|
||||
|
||||
changeprivilege:
|
||||
li t0, 0x00001800 # mask off mstatus.MPP in bits 11-12
|
||||
csrc mstatus, t0
|
||||
andi a0, a0, 0x003 # only keep bottom two bits of argument
|
||||
slli a0, a0, 11 # move into mstatus.MPP position
|
||||
csrs mstatus, a0 # set mstatus.MPP with desired privilege
|
||||
|
||||
trap_return: # return from trap handler
|
||||
csrr t0, mepc # get address of instruction that caused exception
|
||||
li t1, 0x20000
|
||||
csrs mstatus, t1 # set mprv bit to fetch instruction with permission of code that trapped
|
||||
lh t0, 0(t0) # get instruction that caused exception
|
||||
csrc mstatus, t1 # clear mprv bit to restore normal operation
|
||||
li t1, 3
|
||||
and t0, t0, t1 # mask off upper bits
|
||||
beq t0, t1, instr32 # if lower 2 bits are 11, instruction is uncompresssed
|
||||
li t0, 2 # increment PC by 2 for compressed instruction
|
||||
j updateepc
|
||||
instr32:
|
||||
li t0, 4
|
||||
updateepc:
|
||||
csrr t1, mepc # add 2 or 4 (from t0) to MEPC to determine return Address
|
||||
add t1, t1, t0
|
||||
csrw mepc, t1
|
||||
|
||||
ld t1, -8(tp) # restore t1 and t0
|
||||
ld t0, 0(tp)
|
||||
csrrw tp, mscratch, tp # restore tp
|
||||
mret # return from trap
|
||||
|
||||
write_tohost:
|
||||
la t1, tohost
|
||||
li t0, 1 # 1 for success, 3 for failure
|
||||
sd t0, 0(t1) # send success code
|
||||
|
||||
self_loop:
|
||||
j self_loop # wait
|
||||
|
||||
.section .tohost
|
||||
tohost: # write to HTIF
|
||||
.dword 0
|
||||
fromhost:
|
||||
.dword 0
|
||||
|
||||
.EQU XLEN,64
|
||||
begin_signature:
|
||||
.fill 6*(XLEN/32),4,0xdeadbeef #
|
||||
end_signature:
|
||||
|
||||
# Initialize stack with room for 512 bytes
|
||||
.bss
|
||||
.space 512
|
||||
topofstack:
|
||||
# And another stack for the trap handler
|
||||
.bss
|
||||
.space 512
|
||||
topoftrapstack:
|
||||
|
||||
.align 4
|
||||
.section .text.main
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
// load code to initalize stack, handle interrupts, terminate
|
||||
|
||||
#include "WALLY-init-lib.h"
|
||||
#include "WALLY-init-lib-misalignedSpill.h"
|
||||
|
||||
# run-elf.bash find this in project description
|
||||
main:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue