D$ now support thightly coupled ram.
Add IBusDBusCachedTightlyCoupledRam plugin
This commit is contained in:
parent
220b599c9a
commit
9605b663bf
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue