MMU implemented

Datacached using MMU implemented
It compile, but nothing is tested
This commit is contained in:
Charles Papon 2017-04-28 16:41:23 +02:00
parent ba2ca77114
commit 010ba568f0
7 changed files with 109 additions and 53 deletions

View File

@ -29,6 +29,7 @@ trait Pipeline {
}
def build(): Unit ={
plugins.foreach(_.pipeline = this.asInstanceOf[T])
plugins.foreach(_.setup(this.asInstanceOf[T]))
//Build plugins

View File

@ -79,7 +79,7 @@ class BranchPlugin(earlyBranch : Boolean,
}
override def build(pipeline: VexRiscv): Unit = prediction match {
case NONE => buildWithoutPrediction(pipeline)
case `NONE` => buildWithoutPrediction(pipeline)
case `STATIC` => buildWithPrediction(pipeline)
case `DYNAMIC` => buildWithPrediction(pipeline)
}

View File

@ -1,7 +1,7 @@
package SpinalRiscv.Plugin
import SpinalRiscv.Riscv._
import SpinalRiscv.{Stageable, DecoderService, Riscv, VexRiscv}
import SpinalRiscv._
import spinal.core._
import spinal.lib._
@ -12,17 +12,20 @@ case class DataCacheConfig( cacheSize : Int,
addressWidth : Int,
cpuDataWidth : Int,
memDataWidth : Int,
catchAccessFault : Boolean = false){
catchAccessFault : Boolean = false,
tagSizeShift : Int = 0){ //Used to force infering ram
def burstSize = bytePerLine*8/memDataWidth
val burstLength = bytePerLine/(memDataWidth/8)
assert(catchAccessFault == false)
}
case class DataMmuConfig(dTlbSize : Int)
class DBusCachedPlugin(config : DataCacheConfig) extends Plugin[VexRiscv]{
class DBusCachedPlugin(config : DataCacheConfig, mmuConfig : DataMmuConfig = null) extends Plugin[VexRiscv]{
import config._
var dBus : DataCacheMemBus = null
var mmuBus : MemoryTranslatorBus = null
object MEMORY_ENABLE extends Stageable(Bool)
object MEMORY_ADDRESS_LOW extends Stageable(UInt(2 bits))
@ -56,6 +59,9 @@ class DBusCachedPlugin(config : DataCacheConfig) extends Plugin[VexRiscv]{
List(LB, LH, LW, LBU, LHU, LWU).map(_ -> loadActions) ++
List(SB, SH, SW).map(_ -> storeActions)
)
if(mmuConfig != null)
mmuBus = pipeline.service(classOf[MemoryTranslator]).newTranslationPort(pipeline.memory,mmuConfig.dTlbSize)
}
override def build(pipeline: VexRiscv): Unit = {
@ -98,6 +104,15 @@ class DBusCachedPlugin(config : DataCacheConfig) extends Plugin[VexRiscv]{
import memory._
cache.io.cpu.memory.isValid := arbitration.isValid && input(MEMORY_ENABLE)
cache.io.cpu.memory.isStuck := arbitration.isStuck
cache.io.cpu.memory.isRemoved := arbitration.removeIt
if(mmuBus != null){
cache.io.cpu.memory.mmuBus <> mmuBus
} else {
cache.io.cpu.memory.mmuBus.rsp.physicalAddress := cache.io.cpu.memory.mmuBus.cmd.virtualAddress
cache.io.cpu.memory.mmuBus.rsp.allowExecute := True
cache.io.cpu.memory.mmuBus.rsp.allowRead := True
cache.io.cpu.memory.mmuBus.rsp.allowWrite := True
}
}
writeBack plug new Area{
@ -236,9 +251,12 @@ case class DataCacheCpuExecuteArgs(p : DataCacheConfig) extends Bundle{
case class DataCacheCpuMemory(p : DataCacheConfig) extends Bundle with IMasterSlave{
val isValid = Bool
val isStuck = Bool
val isRemoved = Bool
val mmuBus = MemoryTranslatorBus()
override def asMaster(): Unit = {
out(isValid, isStuck)
out(isValid, isStuck, isRemoved)
slave(mmuBus)
}
}
@ -435,7 +453,7 @@ class DataCache(p : DataCacheConfig) extends Component{
val request = requestIn.stage() //TODO FMAX half pipe ?
request.ready := False
val buffer = Mem(Bits(p.memDataWidth bits),memTransactionPerLine << 1) // WARNING << 1 could resolve cyclone II issue, //.add(new AttributeString("ramstyle","M4K"))
val buffer = Mem(Bits(p.memDataWidth bits),memTransactionPerLine << tagSizeShift) // WARNING << tagSizeShift could resolve cyclone II issue, //.add(new AttributeString("ramstyle","M4K"))
//Send line read commands to fill the buffer
val readLineCmdCounter = Reg(UInt(log2Up(memTransactionPerLine + 1) bits)) init(0)
@ -513,21 +531,23 @@ class DataCache(p : DataCacheConfig) extends Component{
val stageA = new Area{
val request = RegNextWhen(io.cpu.execute.args, !io.cpu.memory.isStuck)
io.cpu.memory.mmuBus.cmd.isValid := io.cpu.memory.isValid //TODO filter request kind
io.cpu.memory.mmuBus.cmd.virtualAddress := request.address
}
val stageB = new Area {
io.flushDone := False
val request = RegNextWhen(stageA.request, !io.cpu.writeBack.isStuck)
// val waysHit = RegNextWhen(way.tagReadRspTwoRegIn.used && stageA.request.address(tagRange) === way.tagReadRspTwoRegIn.address,!io.cpu.writeBack.isStuck) //Manual retiming
val waysHit = way.tagReadRspTwo.used && request.address(tagRange) === way.tagReadRspTwo.address
val mmuRsp = RegNextWhen(io.cpu.memory.mmuBus.rsp, !io.cpu.writeBack.isStuck)
// val waysHit = RegNextWhen(way.tagReadRspTwoRegIn.used && stageA.mmuRsp.physicalAddress(tagRange) === way.tagReadRspTwoRegIn.address,!io.cpu.writeBack.isStuck) //Manual retiming
val waysHit = way.tagReadRspTwo.used && mmuRsp.physicalAddress(tagRange) === way.tagReadRspTwo.address
//Evict the cache after reset
val requestValid = io.cpu.writeBack.isValid || RegNextWhen(False, !io.cpu.writeBack.isStuck, True)
request.kind init(DataCacheCpuCmdKind.EVICT)
request.all init(True)
request.address init(0)
mmuRsp.physicalAddress init(0)
io.cpu.writeBack.haltIt := requestValid
@ -551,17 +571,17 @@ class DataCache(p : DataCacheConfig) extends Component{
is(EVICT){
when(request.all){
tagsWriteCmd.valid := True
tagsWriteCmd.address := request.address(lineRange)
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
tagsWriteCmd.data.used := False
when(request.address(lineRange) =/= lineCount-1){
request.address.getDrivingReg(lineRange) := request.address(lineRange) + 1
when(mmuRsp.physicalAddress(lineRange) =/= lineCount-1){
mmuRsp.physicalAddress.getDrivingReg(lineRange) := mmuRsp.physicalAddress(lineRange) + 1
}otherwise{
io.cpu.writeBack.haltIt := False
}
}otherwise{
when(waysHit) {
tagsWriteCmd.valid := True
tagsWriteCmd.address := request.address(lineRange)
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
tagsWriteCmd.data.used := False
}
io.cpu.writeBack.haltIt := False
@ -572,15 +592,15 @@ class DataCache(p : DataCacheConfig) extends Component{
// when(!flushAllState){
// victim.requestIn.valid := waysRead(0).tag.used && waysRead(0).tag.dirty
// victim.requestIn.way := writebackWayId
// victim.requestIn.address := writebackWayInfo.address @@ request.address(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
// victim.requestIn.address := writebackWayInfo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
//
// tagsWriteCmd.way := writebackWayId
// tagsWriteCmd.address := request.address(lineRange)
// tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
// tagsWriteCmd.data.used := False
//
// when(!victim.requestIn.isStall) {
// request.address.getDrivingReg(lineRange) := request.address(lineRange) + 1
// flushAllDone := request.address(lineRange) === lineCount-1
// mmuRsp.physicalAddress.getDrivingReg(lineRange) := mmuRsp.physicalAddress(lineRange) + 1
// flushAllDone := mmuRsp.physicalAddress(lineRange) === lineCount-1
// flushAllState := True
// tagsWriteCmd.valid := True
// }
@ -597,11 +617,11 @@ class DataCache(p : DataCacheConfig) extends Component{
//
// victim.requestIn.valid := True
// victim.requestIn.way := writebackWayId
// victim.requestIn.address := writebackWayInfo.address @@ request.address(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
// victim.requestIn.address := writebackWayInfo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
//
// tagsWriteCmd.valid := victim.requestIn.ready
// tagsWriteCmd.way := writebackWayId
// tagsWriteCmd.address := request.address(lineRange)
// tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
// tagsWriteCmd.data.used := False
// } otherwise{
// io.cpu.memory.haltIt := False
@ -615,7 +635,7 @@ class DataCache(p : DataCacheConfig) extends Component{
val memCmdSent = RegInit(False)
when(!victim.request.valid) { //Avoid mixing memory request while victim is pending
io.mem.cmd.wr := request.wr
io.mem.cmd.address := request.address(tagRange.high downto wordRange.low) @@ U(0,wordRange.low bit)
io.mem.cmd.address := mmuRsp.physicalAddress(tagRange.high downto wordRange.low) @@ U(0,wordRange.low bit)
io.mem.cmd.mask := request.mask
io.mem.cmd.data := request.data
io.mem.cmd.length := 1
@ -632,20 +652,20 @@ class DataCache(p : DataCacheConfig) extends Component{
when(waysHit || !loadingNotDone){
io.cpu.writeBack.haltIt := False
dataWriteCmd.valid := request.wr
dataWriteCmd.address := request.address(lineRange.high downto wordRange.low)
dataWriteCmd.address := mmuRsp.physicalAddress(lineRange.high downto wordRange.low)
dataWriteCmd.data := request.data
dataWriteCmd.mask := request.mask
tagsWriteCmd.valid := !loadingNotDone || request.wr
tagsWriteCmd.address := request.address(lineRange)
tagsWriteCmd.address := mmuRsp.physicalAddress(lineRange)
tagsWriteCmd.data.used := True
tagsWriteCmd.data.dirty := request.wr
tagsWriteCmd.data.address := request.address(tagRange)
tagsWriteCmd.data.address := mmuRsp.physicalAddress(tagRange)
} otherwise {
val victimRequired = way.tagReadRspTwo.used && way.tagReadRspTwo.dirty
loaderValid := loadingNotDone && !(victimNotSent && victim.request.isStall) //Additional condition used to be sure of that all previous victim are written into the RAM
victim.requestIn.valid := victimRequired && victimNotSent
victim.requestIn.address := way.tagReadRspTwo.address @@ request.address(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
victim.requestIn.address := way.tagReadRspTwo.address @@ mmuRsp.physicalAddress(lineRange) @@ U((lineRange.low - 1 downto 0) -> false)
}
}
}
@ -660,7 +680,7 @@ class DataCache(p : DataCacheConfig) extends Component{
//The whole life of a loading task, the corresponding manager request is present
val loader = new Area{
val valid = RegNext(stageB.loaderValid) init(False)
val baseAddress = stageB.request.address
val baseAddress = stageB.mmuRsp.physicalAddress
val memCmdSent = RegInit(False)
when(valid && !memCmdSent) {

View File

@ -7,6 +7,7 @@ import spinal.core.Area
* Created by PIC32F_USER on 03/03/2017.
*/
trait Plugin[T <: Pipeline] {
var pipeline : T = null.asInstanceOf[T]
def getName() = this.getClass.getSimpleName.replace("$","")
def setup(pipeline: T) : Unit = {}

View File

@ -21,3 +21,26 @@ case class ExceptionCause() extends Bundle{
trait ExceptionService{
def newExceptionPort(stage : Stage, priority : Int = 0) : Flow[ExceptionCause]
}
case class MemoryTranslatorCmd() extends Bundle{
val isValid = Bool
val virtualAddress = UInt(32 bits)
}
case class MemoryTranslatorRsp() extends Bundle{
val physicalAddress = UInt(32 bits)
val allowRead, allowWrite, allowExecute = Bool
}
case class MemoryTranslatorBus() extends Bundle with IMasterSlave{
val cmd = MemoryTranslatorCmd()
val rsp = MemoryTranslatorRsp()
override def asMaster() : Unit = {
out(cmd)
in(rsp)
}
}
trait MemoryTranslator{
def newTranslationPort(stage : Stage, cacheSize : Int) : MemoryTranslatorBus
}

View File

@ -203,24 +203,24 @@ object TopLevel {
configTest.plugins ++= List(
new PcManagerSimplePlugin(0x00000000l, true),
new IBusSimplePlugin(
interfaceKeepData = true,
catchAccessFault = false
),
// new IBusCachedPlugin(
// config = InstructionCacheConfig(
// cacheSize = 4096,
// bytePerLine =32,
// wayCount = 1,
// wrappedMemAccess = true,
// addressWidth = 32,
// cpuDataWidth = 32,
// memDataWidth = 32,
// catchAccessFault = false,
// asyncTagMemory = false,
// twoStageLogic = true
// )
// new IBusSimplePlugin(
// interfaceKeepData = true,
// catchAccessFault = false
// ),
new IBusCachedPlugin(
config = InstructionCacheConfig(
cacheSize = 4096,
bytePerLine =32,
wayCount = 1,
wrappedMemAccess = true,
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32,
catchAccessFault = false,
asyncTagMemory = false,
twoStageLogic = true
)
),
// new DBusSimplePlugin(
// catchAddressMisaligned = false,
@ -239,15 +239,26 @@ object TopLevel {
// ),
new DBusCachedPlugin(
config = new DataCacheConfig(
cacheSize = 128,
cacheSize = 4096,
bytePerLine = 32,
wayCount = 1,
addressWidth = 32,
cpuDataWidth = 32,
memDataWidth = 32,
catchAccessFault = false
catchAccessFault = false,
tagSizeShift = 2
),
mmuConfig = DataMmuConfig(
dTlbSize = 6
)
),
new MemoryTranslatorPlugin(
tlbSize = 32,
exceptionCode = 13,
mmuRange = !_(31)
),
new MachineCsr(csrConfigAll),
new DecoderSimplePlugin(
catchIllegalInstruction = false
),
@ -264,10 +275,10 @@ object TopLevel {
// new HazardSimplePlugin(true, true, true, true),
// new HazardSimplePlugin(false, true, false, true),
new HazardSimplePlugin(
bypassExecute = false,
bypassMemory = false,
bypassWriteBack = false,
bypassWriteBackBuffer = false,
bypassExecute = true,
bypassMemory = true,
bypassWriteBack = true,
bypassWriteBackBuffer = true,
pessimisticUseSrc = false,
pessimisticWriteRegFile = false,
pessimisticAddressMatch = false
@ -282,9 +293,9 @@ object TopLevel {
)
)
val toplevel = new VexRiscv(configFull)
// val toplevel = new VexRiscv(configFull)
// val toplevel = new VexRiscv(configLight)
// val toplevel = new VexRiscv(configTest)
val toplevel = new VexRiscv(configTest)
toplevel.decode.input(toplevel.config.INSTRUCTION).addAttribute(Verilator.public)
toplevel.decode.input(toplevel.config.PC).addAttribute(Verilator.public)
toplevel.decode.arbitration.isValid.addAttribute(Verilator.public)

View File

@ -1,4 +1,4 @@
IBUS=IBUS_SIMPLE
IBUS=IBUS_CACHED
DBUS=DBUS_CACHED
TRACE=no
TRACE_START=0