Got the new MMU design to pass simple tests #60
This commit is contained in:
parent
ea56481ead
commit
af2acbd46e
|
@ -44,9 +44,16 @@ trait Pipeline {
|
|||
plugins.foreach(_.pipeline = this.asInstanceOf[T])
|
||||
plugins.foreach(_.setup(this.asInstanceOf[T]))
|
||||
|
||||
plugins.foreach{ p =>
|
||||
p.parentScope = Component.current.dslBody //Put the given plugin as a child of the current component
|
||||
p.reflectNames()
|
||||
}
|
||||
|
||||
//Build plugins
|
||||
plugins.foreach(_.build(this.asInstanceOf[T]))
|
||||
|
||||
|
||||
|
||||
//Interconnect stages
|
||||
class KeyInfo{
|
||||
var insertStageId = Int.MaxValue
|
||||
|
|
|
@ -170,7 +170,7 @@ object LinuxGen {
|
|||
)
|
||||
)
|
||||
if(withMmu) config.plugins += new MmuPlugin(
|
||||
virtualRange = _(31 downto 28) === 0xC,
|
||||
virtualRange = a => True,
|
||||
ioRange = _(31 downto 28) === 0xF,
|
||||
allowUserIo = true
|
||||
)
|
||||
|
|
|
@ -109,7 +109,7 @@ object CsrPluginConfig{
|
|||
sbadaddrAccess = CsrAccess.READ_WRITE,
|
||||
scycleAccess = CsrAccess.READ_WRITE,
|
||||
sinstretAccess = CsrAccess.READ_WRITE,
|
||||
satpAccess = CsrAccess.READ_WRITE,
|
||||
satpAccess = CsrAccess.NONE, //Implemented into the MMU plugin
|
||||
medelegAccess = CsrAccess.READ_WRITE,
|
||||
midelegAccess = CsrAccess.READ_WRITE,
|
||||
pipelineCsrRead = false,
|
||||
|
@ -643,7 +643,7 @@ class CsrPlugin(config: CsrPluginConfig) extends Plugin[VexRiscv] with Exception
|
|||
})
|
||||
|
||||
val sortedByStage = groupedByStage.sortWith((a, b) => pipeline.indexOf(a.stage) < pipeline.indexOf(b.stage))
|
||||
sortedByStage.zipWithIndex.foreach(e => e._1.port.setName(e._1.stage.getName() + "_exception_agregat"))
|
||||
// sortedByStage.zipWithIndex.foreach(e => e._1.port.setName(e._1.stage.getName() + "_exception_agregat"))
|
||||
exceptionValids := exceptionValidsRegs
|
||||
for(portInfo <- sortedByStage; port = portInfo.port ; stage = portInfo.stage; stageId = indexOf(portInfo.stage)) {
|
||||
when(port.valid) {
|
||||
|
|
|
@ -223,7 +223,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
var redoBranch : Flow[UInt] = null
|
||||
val catchSomething = catchAccessFault || catchAddressMisaligned || memoryTranslatorPortConfig != null
|
||||
|
||||
var dBusAccess : DBusAccess = null
|
||||
@dontName var dBusAccess : DBusAccess = null
|
||||
override def newDBusAccess(): DBusAccess = {
|
||||
assert(dBusAccess == null)
|
||||
dBusAccess = DBusAccess()
|
||||
|
@ -383,6 +383,8 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
|||
if(catchSomething) memoryExceptionPort.valid := False
|
||||
if(memoryTranslatorPortConfig != null) redoBranch.valid := False
|
||||
}
|
||||
|
||||
arbitration.flushAll setWhen(redoBranch.valid)
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -607,8 +607,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt,
|
|||
}
|
||||
|
||||
def stageXToIBusRsp[T <: Data](stage : Any, input : T): (T) ={
|
||||
iBusRsp.stages.dropWhile(_ != stage).foldLeft(input)((data,stage) => RegNextWhen(data, stage.output.ready))
|
||||
|
||||
iBusRsp.stages.dropWhile(_ != stage).tail.foldLeft(input)((data,stage) => RegNextWhen(data, stage.output.ready))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -305,6 +305,8 @@ class IBusSimplePlugin(resetVector : BigInt,
|
|||
redoBranch.payload := stages.last.input.payload
|
||||
}
|
||||
|
||||
decode.arbitration.flushAll setWhen(redoBranch.valid)
|
||||
|
||||
if(catchSomething){
|
||||
decodeExceptionPort.code.assignDontCare()
|
||||
decodeExceptionPort.badAddr := join.pc //TODO Should it be the physical address insted ?
|
||||
|
@ -315,7 +317,7 @@ class IBusSimplePlugin(resetVector : BigInt,
|
|||
}
|
||||
if(memoryTranslatorPortConfig != null) {
|
||||
val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault())
|
||||
when(stages.last.input.valid && (mmu.joinCtx.exception || !mmu.joinCtx.allowExecute || (!mmu.joinCtx.allowUser && privilegeService.isUser(decode)))){
|
||||
when(stages.last.input.valid && !mmu.joinCtx.refilling && (mmu.joinCtx.exception || !mmu.joinCtx.allowExecute || (!mmu.joinCtx.allowUser && privilegeService.isUser(decode)))){
|
||||
decodeExceptionPort.code := 12
|
||||
exceptionDetected := True
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ class MmuPlugin(virtualRange : UInt => Bool,
|
|||
allowUserIo : Boolean,
|
||||
allowMachineModeMmu : Boolean = false) extends Plugin[VexRiscv] with MemoryTranslator {
|
||||
|
||||
var dBus : DBusAccess = null
|
||||
var dBusAccess : DBusAccess = null
|
||||
val portsInfo = ArrayBuffer[MmuPort]()
|
||||
|
||||
override def newTranslationPort(priority : Int,args : Any): MemoryTranslatorBus = {
|
||||
|
@ -61,7 +61,7 @@ class MmuPlugin(virtualRange : UInt => Bool,
|
|||
decoderService.add(SFENCE_VMA, List(IS_SFENCE_VMA -> True))
|
||||
|
||||
|
||||
dBus = pipeline.service(classOf[DBusAccessService]).newDBusAccess()
|
||||
dBusAccess = pipeline.service(classOf[DBusAccessService]).newDBusAccess()
|
||||
}
|
||||
|
||||
override def build(pipeline: VexRiscv): Unit = {
|
||||
|
@ -142,19 +142,19 @@ class MmuPlugin(virtualRange : UInt => Bool,
|
|||
}
|
||||
val dBusRsp = new Area{
|
||||
val pte = PTE()
|
||||
pte.assignFromBits(dBus.rsp.data)
|
||||
val exception = !pte.V || (!pte.R && pte.W) || dBus.rsp.error
|
||||
pte.assignFromBits(dBusAccess.rsp.data)
|
||||
val exception = !pte.V || (!pte.R && pte.W) || dBusAccess.rsp.error
|
||||
val leaf = pte.R || pte.X
|
||||
}
|
||||
|
||||
val pteBuffer = RegNextWhen(dBusRsp.pte, dBus.rsp.valid)
|
||||
val pteBuffer = RegNextWhen(dBusRsp.pte, dBusAccess.rsp.valid)
|
||||
|
||||
dBus.cmd.valid := False
|
||||
dBus.cmd.write := False
|
||||
dBus.cmd.size := 2
|
||||
dBus.cmd.address.assignDontCare()
|
||||
dBus.cmd.data.assignDontCare()
|
||||
dBus.cmd.writeMask.assignDontCare()
|
||||
dBusAccess.cmd.valid := False
|
||||
dBusAccess.cmd.write := False
|
||||
dBusAccess.cmd.size := 2
|
||||
dBusAccess.cmd.address.assignDontCare()
|
||||
dBusAccess.cmd.data.assignDontCare()
|
||||
dBusAccess.cmd.writeMask.assignDontCare()
|
||||
switch(state){
|
||||
is(State.IDLE){
|
||||
for(port <- portsInfo.sortBy(_.priority)){
|
||||
|
@ -168,14 +168,14 @@ class MmuPlugin(virtualRange : UInt => Bool,
|
|||
}
|
||||
}
|
||||
is(State.L1_CMD){
|
||||
dBus.cmd.valid := True
|
||||
dBus.cmd.address := satp.ppn @@ vpn1 @@ U"00"
|
||||
when(dBus.cmd.ready){
|
||||
dBusAccess.cmd.valid := True
|
||||
dBusAccess.cmd.address := satp.ppn @@ vpn1 @@ U"00"
|
||||
when(dBusAccess.cmd.ready){
|
||||
state := State.L1_RSP
|
||||
}
|
||||
}
|
||||
is(State.L1_RSP){
|
||||
when(dBus.rsp.valid){
|
||||
when(dBusAccess.rsp.valid){
|
||||
when(dBusRsp.leaf || dBusRsp.exception){
|
||||
state := State.IDLE
|
||||
} otherwise {
|
||||
|
@ -184,20 +184,20 @@ class MmuPlugin(virtualRange : UInt => Bool,
|
|||
}
|
||||
}
|
||||
is(State.L0_CMD){
|
||||
dBus.cmd.valid := True
|
||||
dBus.cmd.address := pteBuffer.PPN1(9 downto 0) @@ pteBuffer.PPN0 @@ vpn0 @@ U"00"
|
||||
when(dBus.cmd.ready){
|
||||
dBusAccess.cmd.valid := True
|
||||
dBusAccess.cmd.address := pteBuffer.PPN1(9 downto 0) @@ pteBuffer.PPN0 @@ vpn0 @@ U"00"
|
||||
when(dBusAccess.cmd.ready){
|
||||
state := State.L0_RSP
|
||||
}
|
||||
}
|
||||
is(State.L0_RSP){
|
||||
when(dBus.rsp.valid) {
|
||||
when(dBusAccess.rsp.valid) {
|
||||
state := State.IDLE
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
when(dBus.rsp.valid && (dBusRsp.leaf || dBusRsp.exception)){
|
||||
when(dBusAccess.rsp.valid && (dBusRsp.leaf || dBusRsp.exception)){
|
||||
for(port <- ports){
|
||||
when(portId === port.id) {
|
||||
port.entryToReplace.increment()
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
package vexriscv.plugin
|
||||
|
||||
import vexriscv.{Pipeline, Stage}
|
||||
import spinal.core.Area
|
||||
import spinal.core.{Area, Nameable}
|
||||
|
||||
/**
|
||||
* Created by PIC32F_USER on 03/03/2017.
|
||||
*/
|
||||
trait Plugin[T <: Pipeline] {
|
||||
trait Plugin[T <: Pipeline] extends Nameable{
|
||||
var pipeline : T = null.asInstanceOf[T]
|
||||
def getName() = this.getClass.getSimpleName.replace("$","")
|
||||
setName(this.getClass.getSimpleName.replace("$",""))
|
||||
|
||||
def setup(pipeline: T) : Unit = {}
|
||||
def build(pipeline: T) : Unit
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
*.map
|
||||
*.v
|
||||
*.elf
|
||||
*.o
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -20,20 +20,108 @@ _start:
|
|||
csrw mtvec, x1
|
||||
csrw stvec, x1
|
||||
|
||||
//Test 1
|
||||
test1: //test ram
|
||||
li x28, 1
|
||||
la x1, ROM_2
|
||||
li x2, 0x27262524
|
||||
lw x1, 4(x1)
|
||||
bne x1, x2, fail
|
||||
|
||||
//Test 2
|
||||
test2: //dummy mret
|
||||
li x28, 2
|
||||
la x1, test3
|
||||
csrw mepc, x1
|
||||
li x1, 0x1800
|
||||
csrw mstatus, x1
|
||||
mret
|
||||
j fail
|
||||
|
||||
|
||||
test3: // jump to supervisor
|
||||
li x28, 3
|
||||
li x1, 0x0800
|
||||
csrw mstatus, x1
|
||||
la x1, test4
|
||||
csrw mepc, x1
|
||||
mret
|
||||
j fail
|
||||
|
||||
|
||||
|
||||
test4: //test ram mmu off
|
||||
li x28, 4
|
||||
la x1, ROM_3
|
||||
li x2, 0x37363534
|
||||
lw x1, 4(x1)
|
||||
bne x1, x2, fail
|
||||
|
||||
test5: //setup MMU
|
||||
|
||||
li x28, 5
|
||||
la x1, MMU_TABLE_0 + 0x800
|
||||
la x2, MMU_TABLE_1
|
||||
srli x2, x2, 2
|
||||
ori x2, x2, 0x11
|
||||
sw x2, 0(x1)
|
||||
|
||||
la x1, MMU_TABLE_1 + 0x000*4
|
||||
li x2, 0x80000000
|
||||
srli x2, x2, 2
|
||||
ori x2, x2, 0x1F
|
||||
sw x2, 0(x1)
|
||||
|
||||
|
||||
li x28, 5
|
||||
la x1, MMU_TABLE_0 + 0x900
|
||||
la x2, MMU_TABLE_2
|
||||
srli x2, x2, 2
|
||||
ori x2, x2, 0x11
|
||||
sw x2, 0(x1)
|
||||
|
||||
la x1, MMU_TABLE_2 + 0x00A*4
|
||||
la x2, ROM_4
|
||||
srli x2, x2, 2
|
||||
ori x2, x2, 0x1F
|
||||
sw x2, 0(x1)
|
||||
|
||||
la x1, MMU_TABLE_0
|
||||
srli x1, x1, 12
|
||||
li x2, 0x80000000
|
||||
or x1, x1, x2
|
||||
csrw satp, x1
|
||||
|
||||
|
||||
test6: //read through MMU !
|
||||
li x28, 6
|
||||
li x1, 0x9000A008
|
||||
li x2, 0x4B4A4948
|
||||
lw x1, 0(x1)
|
||||
bne x1, x2, fail
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
j pass
|
||||
|
||||
|
||||
fail: //x28 => error code
|
||||
csrwi satp, 0
|
||||
j failFence
|
||||
failFence:
|
||||
li x2, 0xF00FFF24
|
||||
sw x28, 0(x2)
|
||||
|
||||
pass:
|
||||
csrwi satp, 0
|
||||
j passFence
|
||||
passFence:
|
||||
li x2, 0xF00FFF20
|
||||
sw x0, 0(x2)
|
||||
|
||||
|
@ -45,3 +133,77 @@ pass:
|
|||
nop
|
||||
nop
|
||||
nop
|
||||
|
||||
.align 12
|
||||
MMU_TABLE_0:
|
||||
.word 0
|
||||
|
||||
.align 12
|
||||
MMU_TABLE_1:
|
||||
.word 0
|
||||
|
||||
.align 12
|
||||
MMU_TABLE_2:
|
||||
.word 0
|
||||
|
||||
.align 12
|
||||
MMU_TABLE_3:
|
||||
.word 0
|
||||
|
||||
.align 12
|
||||
ROM_0:
|
||||
.word 0x03020100
|
||||
.word 0x07060504
|
||||
.word 0x0B0A0908
|
||||
.word 0x0F0E0D0C
|
||||
|
||||
.align 12
|
||||
ROM_1:
|
||||
.word 0x13121110
|
||||
.word 0x17161514
|
||||
.word 0x1B1A1918
|
||||
.word 0x1F1E1D1C
|
||||
|
||||
.align 12
|
||||
ROM_2:
|
||||
.word 0x23222120
|
||||
.word 0x27262524
|
||||
.word 0x2B2A2928
|
||||
.word 0x2F2E2D2C
|
||||
|
||||
.align 12
|
||||
ROM_3:
|
||||
.word 0x33323130
|
||||
.word 0x37363534
|
||||
.word 0x3B3A3938
|
||||
.word 0x3F3E3D3C
|
||||
|
||||
.align 12
|
||||
ROM_4:
|
||||
.word 0x43424140
|
||||
.word 0x47464544
|
||||
.word 0x4B4A4948
|
||||
.word 0x4F4E4D4C
|
||||
|
||||
.align 12
|
||||
ROM_5:
|
||||
.word 0x53525150
|
||||
.word 0x57565554
|
||||
.word 0x5B5A5958
|
||||
.word 0x5F5E5D5C
|
||||
|
||||
.align 12
|
||||
ROM_6:
|
||||
.word 0x63626160
|
||||
.word 0x67666564
|
||||
.word 0x6B6A6968
|
||||
.word 0x6F6E6D6C
|
||||
|
||||
.align 12
|
||||
ROM_7:
|
||||
.word 0x73727170
|
||||
.word 0x77767574
|
||||
.word 0x7B7A7978
|
||||
.word 0x7F7E7D7C
|
||||
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
OUTPUT_ARCH( "riscv" )
|
||||
|
||||
MEMORY {
|
||||
onChipRam (W!RX)/*(RX)*/ : ORIGIN = 0x80000000, LENGTH = 8K
|
||||
onChipRam (W!RX)/*(RX)*/ : ORIGIN = 0x80000000, LENGTH = 1M
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
|
|
|
@ -289,20 +289,42 @@ public:
|
|||
|
||||
union mcause {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
struct __attribute__((packed)) {
|
||||
uint32_t exceptionCode : 31;
|
||||
uint32_t interrupt : 1;
|
||||
};
|
||||
}__attribute__((packed)) mcause;
|
||||
} mcause;
|
||||
|
||||
|
||||
union scause {
|
||||
uint32_t raw;
|
||||
struct {
|
||||
struct __attribute__((packed)){
|
||||
uint32_t exceptionCode : 31;
|
||||
uint32_t interrupt : 1;
|
||||
};
|
||||
}__attribute__((packed)) scause;
|
||||
} scause;
|
||||
|
||||
union satp {
|
||||
uint32_t raw;
|
||||
struct __attribute__((packed)){
|
||||
uint32_t ppn : 22;
|
||||
uint32_t _x : 9;
|
||||
uint32_t mode : 1;
|
||||
};
|
||||
}satp;
|
||||
|
||||
union Tlb {
|
||||
uint32_t raw;
|
||||
struct __attribute__((packed)){
|
||||
uint32_t v : 1;
|
||||
uint32_t r : 1;
|
||||
uint32_t w : 1;
|
||||
uint32_t x : 1;
|
||||
uint32_t u : 1;
|
||||
uint32_t _dummy : 5;
|
||||
uint32_t ppn : 22;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
@ -324,6 +346,7 @@ public:
|
|||
privilege = 3;
|
||||
medeleg = 0;
|
||||
mideleg = 0;
|
||||
satp.mode = 0;
|
||||
}
|
||||
|
||||
virtual void rfWrite(int32_t address, int32_t data) {
|
||||
|
@ -346,6 +369,29 @@ public:
|
|||
virtual bool dRead(int32_t address, int32_t size, uint32_t *data) = 0;
|
||||
virtual void dWrite(int32_t address, int32_t size, uint32_t data) = 0;
|
||||
|
||||
enum AccessKind {READ,WRITE,EXECUTE};
|
||||
bool v2p(uint32_t v, uint32_t *p, AccessKind kind){
|
||||
if(privilege == 3 || satp.mode == 0){
|
||||
*p = v;
|
||||
} else {
|
||||
Tlb tlb;
|
||||
dRead((satp.ppn << 12) | ((v >> 22) << 2), 4, &tlb.raw);
|
||||
if(!tlb.v) return true;
|
||||
if(!tlb.x && !tlb.r && !tlb.w){
|
||||
dRead((tlb.ppn << 12) | (((v >> 12) & 0x3FF) << 2), 4, &tlb.raw);
|
||||
if(!tlb.v) return true;
|
||||
}
|
||||
if(!tlb.u && privilege == 0) return true;
|
||||
switch(kind){
|
||||
case READ: if(!tlb.r) return true; break;
|
||||
case WRITE: if(!tlb.w) return true; break;
|
||||
case EXECUTE: if(!tlb.x) return true; break;
|
||||
}
|
||||
*p = (tlb.ppn << 12) | (v & 0xFFF);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void exception(bool interrupt,int32_t cause) {
|
||||
exception(interrupt, cause, false, 0);
|
||||
}
|
||||
|
@ -396,6 +442,7 @@ public:
|
|||
|
||||
|
||||
virtual bool csrRead(int32_t csr, uint32_t *value){
|
||||
if(((csr >> 8) & 0x3) > privilege) return true;
|
||||
switch(csr){
|
||||
case MSTATUS: *value = status.raw; break;
|
||||
case MIP: *value = ip.raw; break;
|
||||
|
@ -415,6 +462,7 @@ public:
|
|||
case STVAL: *value = sbadaddr; break;
|
||||
case SEPC: *value = sepc; break;
|
||||
case SSCRATCH: *value = sscratch; break;
|
||||
case SATP: *value = satp.raw; break;
|
||||
default: return true; break;
|
||||
}
|
||||
return false;
|
||||
|
@ -422,6 +470,7 @@ public:
|
|||
|
||||
#define maskedWrite(dst, src, mask) dst=(dst & ~mask)|(src & mask);
|
||||
virtual bool csrWrite(int32_t csr, uint32_t value){
|
||||
if(((csr >> 8) & 0x3) > privilege) return true;
|
||||
switch(csr){
|
||||
case MSTATUS: status.raw = value; break;
|
||||
case MIP: ip.raw = value; break;
|
||||
|
@ -441,6 +490,7 @@ public:
|
|||
case STVAL: sbadaddr = value; break;
|
||||
case SEPC: sepc = value; break;
|
||||
case SSCRATCH: sscratch = value; break;
|
||||
case SATP: satp.raw = value; break;
|
||||
|
||||
default: ilegalInstruction(); return true; break;
|
||||
}
|
||||
|
@ -513,22 +563,26 @@ public:
|
|||
#define i16_swsp_imm ((iBits(9, 4) << 2) + (iBits(7, 2) << 6))
|
||||
uint32_t i;
|
||||
uint32_t u32Buf;
|
||||
uint32_t pAddr;
|
||||
if (pc & 2) {
|
||||
if(iRead(pc - 2, &i)){
|
||||
if(v2p(pc - 2, &pAddr, EXECUTE)){ exception(0, 12); return; }
|
||||
if(iRead(pAddr, &i)){
|
||||
exception(0, 1);
|
||||
return;
|
||||
}
|
||||
i >>= 16;
|
||||
if (i & 3 == 3) {
|
||||
uint32_t u32Buf;
|
||||
if(iRead(pc + 2, &u32Buf)){
|
||||
if(v2p(pc + 2, &pAddr, EXECUTE)){ exception(0, 12); return; }
|
||||
if(iRead(pAddr, &u32Buf)){
|
||||
exception(0, 1);
|
||||
return;
|
||||
}
|
||||
i |= u32Buf << 16;
|
||||
}
|
||||
} else {
|
||||
if(iRead(pc, &i)){
|
||||
if(v2p(pc, &pAddr, EXECUTE)){ exception(0, 12); return; }
|
||||
if(iRead(pAddr, &i)){
|
||||
exception(0, 1);
|
||||
return;
|
||||
}
|
||||
|
@ -561,7 +615,8 @@ public:
|
|||
if(address & (size-1)){
|
||||
exception(0, 4, address);
|
||||
} else {
|
||||
if(dRead(address, size, &data)){
|
||||
if(v2p(address, &pAddr, READ)){ exception(0, 13); return; }
|
||||
if(dRead(pAddr, size, &data)){
|
||||
exception(0, 5, address);
|
||||
} else {
|
||||
switch ((i >> 12) & 0x7) {
|
||||
|
@ -580,7 +635,8 @@ public:
|
|||
if(address & (size-1)){
|
||||
exception(0, 6, address);
|
||||
} else {
|
||||
dWrite(address, size, i32_rs2);
|
||||
if(v2p(address, &pAddr, WRITE)){ exception(0, 15); return; }
|
||||
dWrite(pAddr, size, i32_rs2);
|
||||
pcWrite(pc + 4);
|
||||
}
|
||||
}break;
|
||||
|
@ -645,18 +701,18 @@ public:
|
|||
switch(i){
|
||||
case 0x30200073:{ //MRET
|
||||
if(privilege < 3){ ilegalInstruction(); return;}
|
||||
status.mpp = 0;
|
||||
privilege = status.mpp;
|
||||
status.mie = status.mpie;
|
||||
status.mpie = 1;
|
||||
privilege = status.mpp;
|
||||
status.mpp = 0;
|
||||
pcWrite(mepc);
|
||||
}break;
|
||||
case 0x10200073:{ //SRET
|
||||
if(privilege < 1){ ilegalInstruction(); return;}
|
||||
status.spp = 0;
|
||||
privilege = status.spp;
|
||||
status.sie = status.spie;
|
||||
status.spie = 1;
|
||||
privilege = status.spp;
|
||||
status.spp = 0;
|
||||
pcWrite(sepc);
|
||||
}break;
|
||||
case 0x00000073:{ //ECALL
|
||||
|
@ -699,7 +755,8 @@ public:
|
|||
if(address & 0x3){
|
||||
exception(0, 4, address);
|
||||
} else {
|
||||
if(dRead(i16_rf1 + i16_lw_imm, 4, &data)) {
|
||||
if(v2p(address, &pAddr, READ)){ exception(0, 13); return; }
|
||||
if(dRead(address, 4, &data)) {
|
||||
exception(1, 5, address);
|
||||
} else {
|
||||
rfWrite(i16_addr2, data); pcWrite(pc + 2);
|
||||
|
@ -711,7 +768,8 @@ public:
|
|||
if(address & 0x3){
|
||||
exception(0, 6, address);
|
||||
} else {
|
||||
dWrite(address, 4, i16_rf2);
|
||||
if(v2p(address, &pAddr, WRITE)){ exception(0, 15); return; }
|
||||
dWrite(pAddr, 4, i16_rf2);
|
||||
pcWrite(pc + 2);
|
||||
}
|
||||
}break;
|
||||
|
@ -746,7 +804,8 @@ public:
|
|||
if(address & 0x3){
|
||||
exception(0, 4, address);
|
||||
} else {
|
||||
if(dRead(address, 4, &data)){
|
||||
if(v2p(address, &pAddr, READ)){ exception(0, 13); return; }
|
||||
if(dRead(pAddr, 4, &data)){
|
||||
exception(1, 5, address);
|
||||
} else {
|
||||
rfWrite(rd32, data); pcWrite(pc + 2);
|
||||
|
@ -775,7 +834,8 @@ public:
|
|||
if(address & 3){
|
||||
exception(0,6, address);
|
||||
} else {
|
||||
dWrite(address, 4, regs[iBits(2,5)]); pcWrite(pc + 2);
|
||||
if(v2p(address, &pAddr, WRITE)){ exception(0, 15); return; }
|
||||
dWrite(pAddr, 4, regs[iBits(2,5)]); pcWrite(pc + 2);
|
||||
}
|
||||
}break;
|
||||
}
|
||||
|
@ -884,7 +944,8 @@ public:
|
|||
cout << "dRead size=" << size << endl;
|
||||
fail();
|
||||
}
|
||||
if(address & (size-1) != 0) cout << "Ref did a unaligned read" << endl;
|
||||
if(address & (size-1) != 0)
|
||||
cout << "Ref did a unaligned read" << endl;
|
||||
if((address & 0xF0000000) == 0xF0000000){
|
||||
MemRead t = periphRead.front();
|
||||
if(t.address != address || t.size != size){
|
||||
|
@ -899,7 +960,8 @@ public:
|
|||
return false;
|
||||
}
|
||||
virtual void dWrite(int32_t address, int32_t size, uint32_t data){
|
||||
if(address & (size-1) != 0) cout << "Ref did a unaligned write" << endl;
|
||||
if(address & (size-1) != 0)
|
||||
cout << "Ref did a unaligned write" << endl;
|
||||
if((address & 0xF0000000) == 0xF0000000){
|
||||
MemWrite w;
|
||||
w.address = address;
|
||||
|
@ -2879,6 +2941,10 @@ int main(int argc, char **argv, char **env) {
|
|||
printf("BOOT\n");
|
||||
timespec startedAt = timer_start();
|
||||
|
||||
#ifdef MMU
|
||||
redo(REDO,Workspace("mmu").withRiscvRef()->loadHex("../raw/mmu/build/mmu.hex")->bootAt(0x80000000u)->run(50e3););
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
for(int idx = 0;idx < 1;idx++){
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
DEBUG?=no
|
||||
DEBUG?=yes
|
||||
|
||||
IBUS?=CACHED
|
||||
IBUS_TC?=no
|
||||
|
|
Loading…
Reference in New Issue