D$ now support thightly coupled ram.

Add IBusDBusCachedTightlyCoupledRam plugin
This commit is contained in:
Dolu1990 2023-02-22 15:26:14 +01:00
parent 220b599c9a
commit 9605b663bf
2 changed files with 127 additions and 2 deletions

View File

@ -5,6 +5,7 @@ import vexriscv._
import spinal.core._ import spinal.core._
import spinal.lib._ import spinal.lib._
import spinal.lib.bus.amba4.axi.Axi4 import spinal.lib.bus.amba4.axi.Axi4
import spinal.lib.bus.misc.SizeMapping
import scala.collection.mutable.ArrayBuffer import scala.collection.mutable.ArrayBuffer
@ -27,6 +28,24 @@ trait DBusEncodingService {
def loadData() : Bits def loadData() : Bits
} }
case class TightlyCoupledDataBus() extends Bundle with IMasterSlave {
val enable = Bool()
val address = UInt(32 bits)
val write_enable = Bool()
val write_data = Bits(32 bits)
val write_mask = Bits(4 bits)
val read_data = Bits(32 bits)
override def asMaster(): Unit = {
out(enable, address, write_enable, write_data, write_mask)
in(read_data)
}
}
case class TightlyCoupledDataPortParameter(name : String, hit : UInt => Bool)
case class TightlyCoupledDataPort(p : TightlyCoupledDataPortParameter, var bus : TightlyCoupledDataBus)
class DBusCachedPlugin(val config : DataCacheConfig, class DBusCachedPlugin(val config : DataCacheConfig,
memoryTranslatorPortConfig : Any = null, memoryTranslatorPortConfig : Any = null,
dBusCmdMasterPipe : Boolean = false, dBusCmdMasterPipe : Boolean = false,
@ -63,6 +82,14 @@ class DBusCachedPlugin(val config : DataCacheConfig,
args args
} }
val tightlyCoupledPorts = ArrayBuffer[TightlyCoupledDataPort]()
def tightlyGen = tightlyCoupledPorts.nonEmpty
def newTightlyCoupledPort(mapping : UInt => Bool) = {
val port = TightlyCoupledDataPort(TightlyCoupledDataPortParameter(null, mapping), TightlyCoupledDataBus())
tightlyCoupledPorts += port
port.bus
}
override def addLoadWordEncoding(key : MaskedLiteral): Unit = { override def addLoadWordEncoding(key : MaskedLiteral): Unit = {
val decoderService = pipeline.service(classOf[DecoderService]) val decoderService = pipeline.service(classOf[DecoderService])
@ -127,6 +154,8 @@ class DBusCachedPlugin(val config : DataCacheConfig,
object MEMORY_ENABLE extends Stageable(Bool) object MEMORY_ENABLE extends Stageable(Bool)
object MEMORY_MANAGMENT extends Stageable(Bool) object MEMORY_MANAGMENT extends Stageable(Bool)
object MEMORY_WR extends Stageable(Bool) object MEMORY_WR extends Stageable(Bool)
object MEMORY_TIGHTLY extends Stageable(Bits(tightlyCoupledPorts.size bits))
object MEMORY_TIGHTLY_DATA extends Stageable(Bits(32 bits))
object MEMORY_LRSC extends Stageable(Bool) object MEMORY_LRSC extends Stageable(Bool)
object MEMORY_AMO extends Stageable(Bool) object MEMORY_AMO extends Stageable(Bool)
object MEMORY_FENCE extends Stageable(Bool) object MEMORY_FENCE extends Stageable(Bool)
@ -374,6 +403,25 @@ class DBusCachedPlugin(val config : DataCacheConfig,
KeepAttribute(memory.input(MEMORY_VIRTUAL_ADDRESS).getDrivingReg()) KeepAttribute(memory.input(MEMORY_VIRTUAL_ADDRESS).getDrivingReg())
) )
} }
if(tightlyGen){
insert(MEMORY_TIGHTLY) := B(tightlyCoupledPorts.map(_.p.hit(input(SRC_ADD).asUInt)))
when(insert(MEMORY_TIGHTLY).orR){
cache.io.cpu.execute.isValid := False
arbitration.haltItself setWhen(stages.dropWhile(_ != execute).tail.map(s => s.arbitration.isValid && s.input(HAS_SIDE_EFFECT)).orR)
}
for((port, sel) <- (tightlyCoupledPorts, input(MEMORY_TIGHTLY).asBools).zipped){
port.bus.enable := arbitration.isValid && input(MEMORY_ENABLE) && sel && !arbitration.isStuck
port.bus.address := input(SRC_ADD).asUInt.resized
port.bus.write_enable := input(MEMORY_WR)
port.bus.write_data := input(MEMORY_STORE_DATA_RF)
port.bus.write_mask := size.mux (
U(0) -> B"0001",
U(1) -> B"0011",
default -> B"1111"
) //|<< port.bus.address(1 downto 0)
}
}
} }
val mmuAndBufferStage = if(writeBack != null) memory else execute val mmuAndBufferStage = if(writeBack != null) memory else execute
@ -391,6 +439,14 @@ class DBusCachedPlugin(val config : DataCacheConfig,
mmuBus.end := !arbitration.isStuck || arbitration.removeIt mmuBus.end := !arbitration.isStuck || arbitration.removeIt
cache.io.cpu.memory.mmuRsp := mmuBus.rsp cache.io.cpu.memory.mmuRsp := mmuBus.rsp
cache.io.cpu.memory.mmuRsp.isIoAccess setWhen(pipeline(DEBUG_BYPASS_CACHE) && !cache.io.cpu.memory.isWrite) cache.io.cpu.memory.mmuRsp.isIoAccess setWhen(pipeline(DEBUG_BYPASS_CACHE) && !cache.io.cpu.memory.isWrite)
if(tightlyGen){
when(input(MEMORY_TIGHTLY).orR){
cache.io.cpu.memory.isValid := False
input(HAS_SIDE_EFFECT) := False
}
insert(MEMORY_TIGHTLY_DATA) := OhMux(input(MEMORY_TIGHTLY), tightlyCoupledPorts.map(_.bus.read_data))
}
} }
val managementStage = stages.last val managementStage = stages.last
@ -465,7 +521,8 @@ class DBusCachedPlugin(val config : DataCacheConfig,
arbitration.haltItself.setWhen(cache.io.cpu.writeBack.isValid && cache.io.cpu.writeBack.haltIt) arbitration.haltItself.setWhen(cache.io.cpu.writeBack.isValid && cache.io.cpu.writeBack.haltIt)
val rspSplits = cache.io.cpu.writeBack.data.subdivideIn(8 bits) val rspData = CombInit(cache.io.cpu.writeBack.data)
val rspSplits = rspData.subdivideIn(8 bits)
val rspShifted = Bits(cpuDataWidth bits) val rspShifted = Bits(cpuDataWidth bits)
//Generate minimal mux to move from a wide aligned memory read to the register file shifter representation //Generate minimal mux to move from a wide aligned memory read to the register file shifter representation
for(i <- 0 until cpuDataWidth/8){ for(i <- 0 until cpuDataWidth/8){
@ -494,6 +551,16 @@ class DBusCachedPlugin(val config : DataCacheConfig,
} }
insert(MEMORY_LOAD_DATA) := rspShifted insert(MEMORY_LOAD_DATA) := rspShifted
if(tightlyGen){
when(input(MEMORY_TIGHTLY).orR){
cache.io.cpu.writeBack.isValid := False
exceptionBus.valid := False
redoBranch.valid := False
rspRf := input(MEMORY_TIGHTLY_DATA)
input(HAS_SIDE_EFFECT) := False
}
}
} }
//Share access to the dBus (used by self refilled MMU) //Share access to the dBus (used by self refilled MMU)
@ -552,3 +619,55 @@ class DBusCachedPlugin(val config : DataCacheConfig,
} }
class IBusDBusCachedTightlyCoupledRam(mapping : SizeMapping, withIBus : Boolean = true) extends Plugin[VexRiscv]{
var dbus : TightlyCoupledDataBus = null
var ibus : TightlyCoupledBus = null
override def setup(pipeline: VexRiscv) = {
dbus = pipeline.service(classOf[DBusCachedPlugin]).newTightlyCoupledPort(addr => mapping.hit(addr))
dbus.setCompositeName(this, "dbus").setAsDirectionLess()
if(withIBus){
ibus = pipeline.service(classOf[IBusCachedPlugin]).newTightlyCoupledPortV2(
TightlyCoupledPortParameter(
name = "tightlyCoupledIbus",
hit = addr => mapping.hit(addr)
)
)
ibus.setCompositeName(this, "ibus").setAsDirectionLess()
}
}
override def build(pipeline: VexRiscv) = {
val logic = pipeline plug new Area {
val dBusAddressReg = RegNextWhen(dbus.address, dbus.enable)
val banks = for (id <- 0 to 3) yield new Area {
val ram = Mem.fill(mapping.size.toInt)(Bits(8 bits))
val d = new Area {
val dataSel = id - dbus.address(1 downto 0)
val addr = (dbus.address + 3 - id) >> 2
val write = dbus.write_data.subdivideIn(8 bits).read(dataSel)
val read = ram.readWriteSync(
address = addr.resized,
data = write,
enable = dbus.enable,
write = dbus.write_enable && dbus.write_mask(dataSel)
)
}
val i = withIBus generate new Area {
val dataSel = id - ibus.address(1 downto 0)
val addr = (ibus.address + 3 - id) >> 2
val read = ram.readSync(
address = addr.resized,
enable = ibus.enable
)
}
}
dbus.read_data := (0 to 3).map(id => banks.map(_.d.read).read(id + dBusAddressReg(1 downto 0))).asBits
if(withIBus) ibus.data := (0 to 3).map(id => banks(id).i.read).asBits
}
}
}

View File

@ -82,6 +82,12 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
this this
} }
def newTightlyCoupledPortV2(p : TightlyCoupledPortParameter) = {
val port = TightlyCoupledPort(p, master(TightlyCoupledBus()))
tightlyCoupledPorts += port
port.bus
}
object FLUSH_ALL extends Stageable(Bool) object FLUSH_ALL extends Stageable(Bool)
object IBUS_ACCESS_ERROR extends Stageable(Bool) object IBUS_ACCESS_ERROR extends Stageable(Bool)
@ -149,7 +155,7 @@ class IBusCachedPlugin(resetVector : BigInt = 0x80000000l,
val stageOffset = if(relaxedPcCalculation) 1 else 0 val stageOffset = if(relaxedPcCalculation) 1 else 0
def stages = iBusRsp.stages.drop(stageOffset) def stages = iBusRsp.stages.drop(stageOffset)
tightlyCoupledPorts.foreach(p => p.bus = master(TightlyCoupledBus()).setName(p.p.name)) tightlyCoupledPorts.filter(_.bus == null).foreach(p => p.bus = master(TightlyCoupledBus()).setName(p.p.name))
val s0 = new Area { val s0 = new Area {
//address decoding //address decoding