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.lib._
|
||||
import spinal.lib.bus.amba4.axi.Axi4
|
||||
import spinal.lib.bus.misc.SizeMapping
|
||||
|
||||
import scala.collection.mutable.ArrayBuffer
|
||||
|
||||
|
@ -27,6 +28,24 @@ trait DBusEncodingService {
|
|||
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,
|
||||
memoryTranslatorPortConfig : Any = null,
|
||||
dBusCmdMasterPipe : Boolean = false,
|
||||
|
@ -63,6 +82,14 @@ class DBusCachedPlugin(val config : DataCacheConfig,
|
|||
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 = {
|
||||
val decoderService = pipeline.service(classOf[DecoderService])
|
||||
|
@ -127,6 +154,8 @@ class DBusCachedPlugin(val config : DataCacheConfig,
|
|||
object MEMORY_ENABLE extends Stageable(Bool)
|
||||
object MEMORY_MANAGMENT 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_AMO 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())
|
||||
)
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -391,6 +439,14 @@ class DBusCachedPlugin(val config : DataCacheConfig,
|
|||
mmuBus.end := !arbitration.isStuck || arbitration.removeIt
|
||||
cache.io.cpu.memory.mmuRsp := mmuBus.rsp
|
||||
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
|
||||
|
@ -465,7 +521,8 @@ class DBusCachedPlugin(val config : DataCacheConfig,
|
|||
|
||||
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)
|
||||
//Generate minimal mux to move from a wide aligned memory read to the register file shifter representation
|
||||
for(i <- 0 until cpuDataWidth/8){
|
||||
|
@ -494,6 +551,16 @@ class DBusCachedPlugin(val config : DataCacheConfig,
|
|||
}
|
||||
|
||||
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)
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
def newTightlyCoupledPortV2(p : TightlyCoupledPortParameter) = {
|
||||
val port = TightlyCoupledPort(p, master(TightlyCoupledBus()))
|
||||
tightlyCoupledPorts += port
|
||||
port.bus
|
||||
}
|
||||
|
||||
|
||||
object FLUSH_ALL 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
|
||||
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 {
|
||||
//address decoding
|
||||
|
|
Loading…
Reference in New Issue