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(_.pipeline = this.asInstanceOf[T])
|
||||||
plugins.foreach(_.setup(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
|
//Build plugins
|
||||||
plugins.foreach(_.build(this.asInstanceOf[T]))
|
plugins.foreach(_.build(this.asInstanceOf[T]))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//Interconnect stages
|
//Interconnect stages
|
||||||
class KeyInfo{
|
class KeyInfo{
|
||||||
var insertStageId = Int.MaxValue
|
var insertStageId = Int.MaxValue
|
||||||
|
|
|
@ -170,7 +170,7 @@ object LinuxGen {
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if(withMmu) config.plugins += new MmuPlugin(
|
if(withMmu) config.plugins += new MmuPlugin(
|
||||||
virtualRange = _(31 downto 28) === 0xC,
|
virtualRange = a => True,
|
||||||
ioRange = _(31 downto 28) === 0xF,
|
ioRange = _(31 downto 28) === 0xF,
|
||||||
allowUserIo = true
|
allowUserIo = true
|
||||||
)
|
)
|
||||||
|
|
|
@ -109,7 +109,7 @@ object CsrPluginConfig{
|
||||||
sbadaddrAccess = CsrAccess.READ_WRITE,
|
sbadaddrAccess = CsrAccess.READ_WRITE,
|
||||||
scycleAccess = CsrAccess.READ_WRITE,
|
scycleAccess = CsrAccess.READ_WRITE,
|
||||||
sinstretAccess = CsrAccess.READ_WRITE,
|
sinstretAccess = CsrAccess.READ_WRITE,
|
||||||
satpAccess = CsrAccess.READ_WRITE,
|
satpAccess = CsrAccess.NONE, //Implemented into the MMU plugin
|
||||||
medelegAccess = CsrAccess.READ_WRITE,
|
medelegAccess = CsrAccess.READ_WRITE,
|
||||||
midelegAccess = CsrAccess.READ_WRITE,
|
midelegAccess = CsrAccess.READ_WRITE,
|
||||||
pipelineCsrRead = false,
|
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))
|
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
|
exceptionValids := exceptionValidsRegs
|
||||||
for(portInfo <- sortedByStage; port = portInfo.port ; stage = portInfo.stage; stageId = indexOf(portInfo.stage)) {
|
for(portInfo <- sortedByStage; port = portInfo.port ; stage = portInfo.stage; stageId = indexOf(portInfo.stage)) {
|
||||||
when(port.valid) {
|
when(port.valid) {
|
||||||
|
|
|
@ -223,7 +223,7 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
||||||
var redoBranch : Flow[UInt] = null
|
var redoBranch : Flow[UInt] = null
|
||||||
val catchSomething = catchAccessFault || catchAddressMisaligned || memoryTranslatorPortConfig != null
|
val catchSomething = catchAccessFault || catchAddressMisaligned || memoryTranslatorPortConfig != null
|
||||||
|
|
||||||
var dBusAccess : DBusAccess = null
|
@dontName var dBusAccess : DBusAccess = null
|
||||||
override def newDBusAccess(): DBusAccess = {
|
override def newDBusAccess(): DBusAccess = {
|
||||||
assert(dBusAccess == null)
|
assert(dBusAccess == null)
|
||||||
dBusAccess = DBusAccess()
|
dBusAccess = DBusAccess()
|
||||||
|
@ -383,6 +383,8 @@ class DBusSimplePlugin(catchAddressMisaligned : Boolean = false,
|
||||||
if(catchSomething) memoryExceptionPort.valid := False
|
if(catchSomething) memoryExceptionPort.valid := False
|
||||||
if(memoryTranslatorPortConfig != null) redoBranch.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) ={
|
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
|
redoBranch.payload := stages.last.input.payload
|
||||||
}
|
}
|
||||||
|
|
||||||
|
decode.arbitration.flushAll setWhen(redoBranch.valid)
|
||||||
|
|
||||||
if(catchSomething){
|
if(catchSomething){
|
||||||
decodeExceptionPort.code.assignDontCare()
|
decodeExceptionPort.code.assignDontCare()
|
||||||
decodeExceptionPort.badAddr := join.pc //TODO Should it be the physical address insted ?
|
decodeExceptionPort.badAddr := join.pc //TODO Should it be the physical address insted ?
|
||||||
|
@ -315,7 +317,7 @@ class IBusSimplePlugin(resetVector : BigInt,
|
||||||
}
|
}
|
||||||
if(memoryTranslatorPortConfig != null) {
|
if(memoryTranslatorPortConfig != null) {
|
||||||
val privilegeService = pipeline.serviceElse(classOf[PrivilegeService], PrivilegeServiceDefault())
|
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
|
decodeExceptionPort.code := 12
|
||||||
exceptionDetected := True
|
exceptionDetected := True
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ class MmuPlugin(virtualRange : UInt => Bool,
|
||||||
allowUserIo : Boolean,
|
allowUserIo : Boolean,
|
||||||
allowMachineModeMmu : Boolean = false) extends Plugin[VexRiscv] with MemoryTranslator {
|
allowMachineModeMmu : Boolean = false) extends Plugin[VexRiscv] with MemoryTranslator {
|
||||||
|
|
||||||
var dBus : DBusAccess = null
|
var dBusAccess : DBusAccess = null
|
||||||
val portsInfo = ArrayBuffer[MmuPort]()
|
val portsInfo = ArrayBuffer[MmuPort]()
|
||||||
|
|
||||||
override def newTranslationPort(priority : Int,args : Any): MemoryTranslatorBus = {
|
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))
|
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 = {
|
override def build(pipeline: VexRiscv): Unit = {
|
||||||
|
@ -142,19 +142,19 @@ class MmuPlugin(virtualRange : UInt => Bool,
|
||||||
}
|
}
|
||||||
val dBusRsp = new Area{
|
val dBusRsp = new Area{
|
||||||
val pte = PTE()
|
val pte = PTE()
|
||||||
pte.assignFromBits(dBus.rsp.data)
|
pte.assignFromBits(dBusAccess.rsp.data)
|
||||||
val exception = !pte.V || (!pte.R && pte.W) || dBus.rsp.error
|
val exception = !pte.V || (!pte.R && pte.W) || dBusAccess.rsp.error
|
||||||
val leaf = pte.R || pte.X
|
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
|
dBusAccess.cmd.valid := False
|
||||||
dBus.cmd.write := False
|
dBusAccess.cmd.write := False
|
||||||
dBus.cmd.size := 2
|
dBusAccess.cmd.size := 2
|
||||||
dBus.cmd.address.assignDontCare()
|
dBusAccess.cmd.address.assignDontCare()
|
||||||
dBus.cmd.data.assignDontCare()
|
dBusAccess.cmd.data.assignDontCare()
|
||||||
dBus.cmd.writeMask.assignDontCare()
|
dBusAccess.cmd.writeMask.assignDontCare()
|
||||||
switch(state){
|
switch(state){
|
||||||
is(State.IDLE){
|
is(State.IDLE){
|
||||||
for(port <- portsInfo.sortBy(_.priority)){
|
for(port <- portsInfo.sortBy(_.priority)){
|
||||||
|
@ -168,14 +168,14 @@ class MmuPlugin(virtualRange : UInt => Bool,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is(State.L1_CMD){
|
is(State.L1_CMD){
|
||||||
dBus.cmd.valid := True
|
dBusAccess.cmd.valid := True
|
||||||
dBus.cmd.address := satp.ppn @@ vpn1 @@ U"00"
|
dBusAccess.cmd.address := satp.ppn @@ vpn1 @@ U"00"
|
||||||
when(dBus.cmd.ready){
|
when(dBusAccess.cmd.ready){
|
||||||
state := State.L1_RSP
|
state := State.L1_RSP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is(State.L1_RSP){
|
is(State.L1_RSP){
|
||||||
when(dBus.rsp.valid){
|
when(dBusAccess.rsp.valid){
|
||||||
when(dBusRsp.leaf || dBusRsp.exception){
|
when(dBusRsp.leaf || dBusRsp.exception){
|
||||||
state := State.IDLE
|
state := State.IDLE
|
||||||
} otherwise {
|
} otherwise {
|
||||||
|
@ -184,20 +184,20 @@ class MmuPlugin(virtualRange : UInt => Bool,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is(State.L0_CMD){
|
is(State.L0_CMD){
|
||||||
dBus.cmd.valid := True
|
dBusAccess.cmd.valid := True
|
||||||
dBus.cmd.address := pteBuffer.PPN1(9 downto 0) @@ pteBuffer.PPN0 @@ vpn0 @@ U"00"
|
dBusAccess.cmd.address := pteBuffer.PPN1(9 downto 0) @@ pteBuffer.PPN0 @@ vpn0 @@ U"00"
|
||||||
when(dBus.cmd.ready){
|
when(dBusAccess.cmd.ready){
|
||||||
state := State.L0_RSP
|
state := State.L0_RSP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
is(State.L0_RSP){
|
is(State.L0_RSP){
|
||||||
when(dBus.rsp.valid) {
|
when(dBusAccess.rsp.valid) {
|
||||||
state := State.IDLE
|
state := State.IDLE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
when(dBus.rsp.valid && (dBusRsp.leaf || dBusRsp.exception)){
|
when(dBusAccess.rsp.valid && (dBusRsp.leaf || dBusRsp.exception)){
|
||||||
for(port <- ports){
|
for(port <- ports){
|
||||||
when(portId === port.id) {
|
when(portId === port.id) {
|
||||||
port.entryToReplace.increment()
|
port.entryToReplace.increment()
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
package vexriscv.plugin
|
package vexriscv.plugin
|
||||||
|
|
||||||
import vexriscv.{Pipeline, Stage}
|
import vexriscv.{Pipeline, Stage}
|
||||||
import spinal.core.Area
|
import spinal.core.{Area, Nameable}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by PIC32F_USER on 03/03/2017.
|
* Created by PIC32F_USER on 03/03/2017.
|
||||||
*/
|
*/
|
||||||
trait Plugin[T <: Pipeline] {
|
trait Plugin[T <: Pipeline] extends Nameable{
|
||||||
var pipeline : T = null.asInstanceOf[T]
|
var pipeline : T = null.asInstanceOf[T]
|
||||||
def getName() = this.getClass.getSimpleName.replace("$","")
|
setName(this.getClass.getSimpleName.replace("$",""))
|
||||||
|
|
||||||
def setup(pipeline: T) : Unit = {}
|
def setup(pipeline: T) : Unit = {}
|
||||||
def build(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 mtvec, x1
|
||||||
csrw stvec, x1
|
csrw stvec, x1
|
||||||
|
|
||||||
//Test 1
|
test1: //test ram
|
||||||
li x28, 1
|
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
|
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
|
j pass
|
||||||
|
|
||||||
|
|
||||||
fail: //x28 => error code
|
fail: //x28 => error code
|
||||||
|
csrwi satp, 0
|
||||||
|
j failFence
|
||||||
|
failFence:
|
||||||
li x2, 0xF00FFF24
|
li x2, 0xF00FFF24
|
||||||
sw x28, 0(x2)
|
sw x28, 0(x2)
|
||||||
|
|
||||||
pass:
|
pass:
|
||||||
|
csrwi satp, 0
|
||||||
|
j passFence
|
||||||
|
passFence:
|
||||||
li x2, 0xF00FFF20
|
li x2, 0xF00FFF20
|
||||||
sw x0, 0(x2)
|
sw x0, 0(x2)
|
||||||
|
|
||||||
|
@ -45,3 +133,77 @@ pass:
|
||||||
nop
|
nop
|
||||||
nop
|
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" )
|
OUTPUT_ARCH( "riscv" )
|
||||||
|
|
||||||
MEMORY {
|
MEMORY {
|
||||||
onChipRam (W!RX)/*(RX)*/ : ORIGIN = 0x80000000, LENGTH = 8K
|
onChipRam (W!RX)/*(RX)*/ : ORIGIN = 0x80000000, LENGTH = 1M
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
|
|
|
@ -289,20 +289,42 @@ public:
|
||||||
|
|
||||||
union mcause {
|
union mcause {
|
||||||
uint32_t raw;
|
uint32_t raw;
|
||||||
struct {
|
struct __attribute__((packed)) {
|
||||||
uint32_t exceptionCode : 31;
|
uint32_t exceptionCode : 31;
|
||||||
uint32_t interrupt : 1;
|
uint32_t interrupt : 1;
|
||||||
};
|
};
|
||||||
}__attribute__((packed)) mcause;
|
} mcause;
|
||||||
|
|
||||||
|
|
||||||
union scause {
|
union scause {
|
||||||
uint32_t raw;
|
uint32_t raw;
|
||||||
struct {
|
struct __attribute__((packed)){
|
||||||
uint32_t exceptionCode : 31;
|
uint32_t exceptionCode : 31;
|
||||||
uint32_t interrupt : 1;
|
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;
|
privilege = 3;
|
||||||
medeleg = 0;
|
medeleg = 0;
|
||||||
mideleg = 0;
|
mideleg = 0;
|
||||||
|
satp.mode = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void rfWrite(int32_t address, int32_t data) {
|
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 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;
|
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) {
|
void exception(bool interrupt,int32_t cause) {
|
||||||
exception(interrupt, cause, false, 0);
|
exception(interrupt, cause, false, 0);
|
||||||
}
|
}
|
||||||
|
@ -396,6 +442,7 @@ public:
|
||||||
|
|
||||||
|
|
||||||
virtual bool csrRead(int32_t csr, uint32_t *value){
|
virtual bool csrRead(int32_t csr, uint32_t *value){
|
||||||
|
if(((csr >> 8) & 0x3) > privilege) return true;
|
||||||
switch(csr){
|
switch(csr){
|
||||||
case MSTATUS: *value = status.raw; break;
|
case MSTATUS: *value = status.raw; break;
|
||||||
case MIP: *value = ip.raw; break;
|
case MIP: *value = ip.raw; break;
|
||||||
|
@ -415,6 +462,7 @@ public:
|
||||||
case STVAL: *value = sbadaddr; break;
|
case STVAL: *value = sbadaddr; break;
|
||||||
case SEPC: *value = sepc; break;
|
case SEPC: *value = sepc; break;
|
||||||
case SSCRATCH: *value = sscratch; break;
|
case SSCRATCH: *value = sscratch; break;
|
||||||
|
case SATP: *value = satp.raw; break;
|
||||||
default: return true; break;
|
default: return true; break;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -422,6 +470,7 @@ public:
|
||||||
|
|
||||||
#define maskedWrite(dst, src, mask) dst=(dst & ~mask)|(src & mask);
|
#define maskedWrite(dst, src, mask) dst=(dst & ~mask)|(src & mask);
|
||||||
virtual bool csrWrite(int32_t csr, uint32_t value){
|
virtual bool csrWrite(int32_t csr, uint32_t value){
|
||||||
|
if(((csr >> 8) & 0x3) > privilege) return true;
|
||||||
switch(csr){
|
switch(csr){
|
||||||
case MSTATUS: status.raw = value; break;
|
case MSTATUS: status.raw = value; break;
|
||||||
case MIP: ip.raw = value; break;
|
case MIP: ip.raw = value; break;
|
||||||
|
@ -441,6 +490,7 @@ public:
|
||||||
case STVAL: sbadaddr = value; break;
|
case STVAL: sbadaddr = value; break;
|
||||||
case SEPC: sepc = value; break;
|
case SEPC: sepc = value; break;
|
||||||
case SSCRATCH: sscratch = value; break;
|
case SSCRATCH: sscratch = value; break;
|
||||||
|
case SATP: satp.raw = value; break;
|
||||||
|
|
||||||
default: ilegalInstruction(); return true; break;
|
default: ilegalInstruction(); return true; break;
|
||||||
}
|
}
|
||||||
|
@ -513,22 +563,26 @@ public:
|
||||||
#define i16_swsp_imm ((iBits(9, 4) << 2) + (iBits(7, 2) << 6))
|
#define i16_swsp_imm ((iBits(9, 4) << 2) + (iBits(7, 2) << 6))
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
uint32_t u32Buf;
|
uint32_t u32Buf;
|
||||||
|
uint32_t pAddr;
|
||||||
if (pc & 2) {
|
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);
|
exception(0, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
i >>= 16;
|
i >>= 16;
|
||||||
if (i & 3 == 3) {
|
if (i & 3 == 3) {
|
||||||
uint32_t u32Buf;
|
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);
|
exception(0, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
i |= u32Buf << 16;
|
i |= u32Buf << 16;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(iRead(pc, &i)){
|
if(v2p(pc, &pAddr, EXECUTE)){ exception(0, 12); return; }
|
||||||
|
if(iRead(pAddr, &i)){
|
||||||
exception(0, 1);
|
exception(0, 1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -561,7 +615,8 @@ public:
|
||||||
if(address & (size-1)){
|
if(address & (size-1)){
|
||||||
exception(0, 4, address);
|
exception(0, 4, address);
|
||||||
} else {
|
} else {
|
||||||
if(dRead(address, size, &data)){
|
if(v2p(address, &pAddr, READ)){ exception(0, 13); return; }
|
||||||
|
if(dRead(pAddr, size, &data)){
|
||||||
exception(0, 5, address);
|
exception(0, 5, address);
|
||||||
} else {
|
} else {
|
||||||
switch ((i >> 12) & 0x7) {
|
switch ((i >> 12) & 0x7) {
|
||||||
|
@ -580,7 +635,8 @@ public:
|
||||||
if(address & (size-1)){
|
if(address & (size-1)){
|
||||||
exception(0, 6, address);
|
exception(0, 6, address);
|
||||||
} else {
|
} else {
|
||||||
dWrite(address, size, i32_rs2);
|
if(v2p(address, &pAddr, WRITE)){ exception(0, 15); return; }
|
||||||
|
dWrite(pAddr, size, i32_rs2);
|
||||||
pcWrite(pc + 4);
|
pcWrite(pc + 4);
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
@ -645,18 +701,18 @@ public:
|
||||||
switch(i){
|
switch(i){
|
||||||
case 0x30200073:{ //MRET
|
case 0x30200073:{ //MRET
|
||||||
if(privilege < 3){ ilegalInstruction(); return;}
|
if(privilege < 3){ ilegalInstruction(); return;}
|
||||||
status.mpp = 0;
|
privilege = status.mpp;
|
||||||
status.mie = status.mpie;
|
status.mie = status.mpie;
|
||||||
status.mpie = 1;
|
status.mpie = 1;
|
||||||
privilege = status.mpp;
|
status.mpp = 0;
|
||||||
pcWrite(mepc);
|
pcWrite(mepc);
|
||||||
}break;
|
}break;
|
||||||
case 0x10200073:{ //SRET
|
case 0x10200073:{ //SRET
|
||||||
if(privilege < 1){ ilegalInstruction(); return;}
|
if(privilege < 1){ ilegalInstruction(); return;}
|
||||||
status.spp = 0;
|
privilege = status.spp;
|
||||||
status.sie = status.spie;
|
status.sie = status.spie;
|
||||||
status.spie = 1;
|
status.spie = 1;
|
||||||
privilege = status.spp;
|
status.spp = 0;
|
||||||
pcWrite(sepc);
|
pcWrite(sepc);
|
||||||
}break;
|
}break;
|
||||||
case 0x00000073:{ //ECALL
|
case 0x00000073:{ //ECALL
|
||||||
|
@ -699,7 +755,8 @@ public:
|
||||||
if(address & 0x3){
|
if(address & 0x3){
|
||||||
exception(0, 4, address);
|
exception(0, 4, address);
|
||||||
} else {
|
} 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);
|
exception(1, 5, address);
|
||||||
} else {
|
} else {
|
||||||
rfWrite(i16_addr2, data); pcWrite(pc + 2);
|
rfWrite(i16_addr2, data); pcWrite(pc + 2);
|
||||||
|
@ -711,7 +768,8 @@ public:
|
||||||
if(address & 0x3){
|
if(address & 0x3){
|
||||||
exception(0, 6, address);
|
exception(0, 6, address);
|
||||||
} else {
|
} else {
|
||||||
dWrite(address, 4, i16_rf2);
|
if(v2p(address, &pAddr, WRITE)){ exception(0, 15); return; }
|
||||||
|
dWrite(pAddr, 4, i16_rf2);
|
||||||
pcWrite(pc + 2);
|
pcWrite(pc + 2);
|
||||||
}
|
}
|
||||||
}break;
|
}break;
|
||||||
|
@ -746,7 +804,8 @@ public:
|
||||||
if(address & 0x3){
|
if(address & 0x3){
|
||||||
exception(0, 4, address);
|
exception(0, 4, address);
|
||||||
} else {
|
} else {
|
||||||
if(dRead(address, 4, &data)){
|
if(v2p(address, &pAddr, READ)){ exception(0, 13); return; }
|
||||||
|
if(dRead(pAddr, 4, &data)){
|
||||||
exception(1, 5, address);
|
exception(1, 5, address);
|
||||||
} else {
|
} else {
|
||||||
rfWrite(rd32, data); pcWrite(pc + 2);
|
rfWrite(rd32, data); pcWrite(pc + 2);
|
||||||
|
@ -775,7 +834,8 @@ public:
|
||||||
if(address & 3){
|
if(address & 3){
|
||||||
exception(0,6, address);
|
exception(0,6, address);
|
||||||
} else {
|
} 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;
|
}break;
|
||||||
}
|
}
|
||||||
|
@ -884,7 +944,8 @@ public:
|
||||||
cout << "dRead size=" << size << endl;
|
cout << "dRead size=" << size << endl;
|
||||||
fail();
|
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){
|
if((address & 0xF0000000) == 0xF0000000){
|
||||||
MemRead t = periphRead.front();
|
MemRead t = periphRead.front();
|
||||||
if(t.address != address || t.size != size){
|
if(t.address != address || t.size != size){
|
||||||
|
@ -899,7 +960,8 @@ public:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
virtual void dWrite(int32_t address, int32_t size, uint32_t data){
|
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){
|
if((address & 0xF0000000) == 0xF0000000){
|
||||||
MemWrite w;
|
MemWrite w;
|
||||||
w.address = address;
|
w.address = address;
|
||||||
|
@ -2879,6 +2941,10 @@ int main(int argc, char **argv, char **env) {
|
||||||
printf("BOOT\n");
|
printf("BOOT\n");
|
||||||
timespec startedAt = timer_start();
|
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++){
|
for(int idx = 0;idx < 1;idx++){
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
DEBUG?=no
|
DEBUG?=yes
|
||||||
|
|
||||||
IBUS?=CACHED
|
IBUS?=CACHED
|
||||||
IBUS_TC?=no
|
IBUS_TC?=no
|
||||||
|
|
Loading…
Reference in New Issue